Skip to content

Commit

Permalink
type annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
Carmine DiMascio committed Dec 29, 2019
1 parent 40b3cd1 commit 73111e0
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/framework/base.path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ export class BasePath {
return this.allPaths;
}

public static fromServers(servers: OpenAPIV3.ServerObject[]) {
public static fromServers(servers: OpenAPIV3.ServerObject[]): BasePath[] {
if (!servers) {
return [new BasePath({ url: '' })];
}
return servers.map(server => new BasePath(server));
}

private findUrlPath(u) {
private findUrlPath(u: string): string {
const findColonSlashSlash = p => {
const r = /:\/\//.exec(p);
if (r) return r.index;
Expand Down
2 changes: 1 addition & 1 deletion src/framework/openapi.spec.loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class OpenApiSpecLoader {
// let apiDoc: OpenAPIV3.Document = null;
// let basePaths: string[] = null;
const { apiDoc, basePaths } = await this.framework.initialize({
visitApi(ctx: OpenAPIFrameworkAPIContext) {
visitApi(ctx: OpenAPIFrameworkAPIContext): void {
const apiDoc = ctx.getApiDoc();
const basePaths = ctx.basePaths;
for (const bpa of basePaths) {
Expand Down
11 changes: 7 additions & 4 deletions src/middlewares/openapi.request.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import { RequestParameterMutator } from './parsers/req.parameter.mutator';

type OperationObject = OpenAPIV3.OperationObject;
type SchemaObject = OpenAPIV3.SchemaObject;
type ReferenceObject = OpenAPIV3.ReferenceObject;
type SecurityRequirementObject = OpenAPIV3.SecurityRequirementObject;
type SecuritySchemeObject = OpenAPIV3.SecuritySchemeObject;
type ApiKeySecurityScheme = OpenAPIV3.ApiKeySecurityScheme;

export class RequestValidator {
private middlewareCache: { [key: string]: RequestHandler } = {};
Expand Down Expand Up @@ -186,17 +189,17 @@ class Security {

private static getSecurityQueryParams(
usedSecuritySchema: SecurityRequirementObject[],
securitySchema,
securitySchema: { [key: string]: ReferenceObject | SecuritySchemeObject },
): string[] {
return usedSecuritySchema && securitySchema
? usedSecuritySchema
.filter(obj => Object.entries(obj).length !== 0)
.map(sec => {
const securityKey = Object.keys(sec)[0];
return securitySchema[securityKey];
return <SecuritySchemeObject>securitySchema[securityKey];
})
.filter(sec => sec?.in === 'query')
.map(sec => sec.name)
.filter(sec => sec?.type === 'apiKey' && sec?.in == 'query')
.map((sec: ApiKeySecurityScheme) => sec.name)
: [];
}
}
23 changes: 16 additions & 7 deletions src/middlewares/openapi.response.validator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ono from 'ono';
import { RequestHandler } from 'express';
import * as ajv from 'ajv';
import mung from '../framework/modded.express.mung';
import { createResponseAjv } from '../framework/ajv';
Expand All @@ -8,7 +9,11 @@ import {
ajvErrorsToValidatorError,
validationError,
} from './util';
import { OpenAPIV3 } from '../framework/types';
import {
OpenAPIV3,
OpenApiRequest,
OpenApiRequestMetadata,
} from '../framework/types';
import * as mediaTypeParser from 'media-typer';
import * as contentTypeParser from 'content-type';

Expand All @@ -25,10 +30,11 @@ export class ResponseValidator {
};
}

public validate() {
return mung.json((body, req: any, res) => {
public validate(): RequestHandler {
return mung.json((body, req, res) => {
if (req.openapi) {
const responses = req.openapi.schema?.responses;
const openapi = <OpenApiRequestMetadata>req.openapi;
const responses = openapi.schema?.responses;
const validators = this._getOrBuildValidator(req, responses);
const statusCode = res.statusCode;
const path = req.originalUrl;
Expand All @@ -39,7 +45,10 @@ export class ResponseValidator {
}

// TODO public for test only - fix me
public _getOrBuildValidator(req, responses) {
public _getOrBuildValidator(
req: OpenApiRequest,
responses: OpenAPIV3.ResponsesObject,
): { [key: string]: ajv.ValidateFunction } {
if (!req) {
// use !req is only possible in unit tests
return this.buildValidators(responses);
Expand All @@ -58,7 +67,7 @@ export class ResponseValidator {
}

// TODO public for test only - fix me
public _validate({ validators, body, statusCode, path }) {
public _validate({ validators, body, statusCode, path }): void {
// find the validator for the 'status code' e.g 200, 2XX or 'default'
let validator;
const status = statusCode;
Expand Down Expand Up @@ -100,7 +109,7 @@ export class ResponseValidator {
* @param responses
* @returns a map of validators
*/
private buildValidators(responses) {
private buildValidators(responses): { [key: string]: ajv.ValidateFunction } {
const canValidate = response => {
if (typeof response.content !== 'object') {
return false;
Expand Down
14 changes: 8 additions & 6 deletions src/middlewares/openapi.security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ class SecuritySchemes {
this.securities = securities;
}

async executeHandlers(req: OpenApiRequest): Promise<SecurityHandlerResult[]> {
public async executeHandlers(
req: OpenApiRequest,
): Promise<SecurityHandlerResult[]> {
// use a fallback handler if security handlers is not specified
// This means if security handlers is specified, the user must define
// all security handlers
Expand Down Expand Up @@ -190,21 +192,21 @@ class AuthValidator {
this.validateOpenID();
}

private validateOauth2() {
private validateOauth2(): void {
const { req, scheme, path } = this;
if (['oauth2'].includes(scheme.type.toLowerCase())) {
// TODO oauth2 validation
}
}

private validateOpenID() {
private validateOpenID(): void {
const { req, scheme, path } = this;
if (['openIdConnect'].includes(scheme.type.toLowerCase())) {
// TODO openidconnect validation
}
}

private validateHttp() {
private validateHttp(): void {
const { req, scheme, path } = this;
if (['http'].includes(scheme.type.toLowerCase())) {
const authHeader =
Expand All @@ -228,7 +230,7 @@ class AuthValidator {
}
}

private validateApiKey() {
private validateApiKey(): void {
const { req, scheme, path } = this;
if (scheme.type === 'apiKey') {
if (scheme.in === 'header') {
Expand All @@ -246,7 +248,7 @@ class AuthValidator {
}
}

private dissallowScopes() {
private dissallowScopes(): void {
if (this.scopes.length > 0) {
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#security-requirement-object
throw {
Expand Down
11 changes: 7 additions & 4 deletions src/middlewares/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Request } from 'express';
import { ValidationError } from '../framework/types';

export class ContentType {
private withoutBoundary: string = null;
public contentType = null;
public contentType: string = null;
public mediaType: string = null;
public charSet: string = null;
private withoutBoundary: string = null;
private constructor(contentType: string | null) {
this.contentType = contentType;
if (contentType) {
Expand Down Expand Up @@ -84,8 +84,11 @@ export function ajvErrorsToValidatorError(
status,
errors: errors.map(e => {
const params: any = e.params;
const required = params?.missingProperty && e.dataPath + '.' + params.missingProperty;
const additionalProperty = params?.additionalProperty && e.dataPath + '.' + params.additionalProperty;
const required =
params?.missingProperty && e.dataPath + '.' + params.missingProperty;
const additionalProperty =
params?.additionalProperty &&
e.dataPath + '.' + params.additionalProperty;
const path = required ?? additionalProperty ?? e.dataPath ?? e.schemaPath;
return {
path,
Expand Down
14 changes: 9 additions & 5 deletions test/common/myapp.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Request, Response, ErrorRequestHandler } from 'express';
import * as express from 'express';
import * as path from 'path';
import * as cookieParser from 'cookie-parser';
Expand Down Expand Up @@ -28,20 +29,23 @@ new OpenApiValidator({
}).install(app);

// 2. Add routes
app.get('/v1/pets', function(req, res, next) {
res.json([{ id: 1, name: 'max' }, { id: 2, name: 'mini' }]);
app.get('/v1/pets', function(req: Request, res: Response) {
res.json([
{ id: 1, name: 'max' },
{ id: 2, name: 'mini' },
]);
});

app.post('/v1/pets', function(req, res, next) {
app.post('/v1/pets', function(req: Request, res: Response) {
res.json({ name: 'sparky' });
});

app.get('/v1/pets/:id', function(req, res, next) {
app.get('/v1/pets/:id', function(req: Request, res: Response) {
res.json({ id: req.params.id, name: 'sparky' });
});

// 2a. Add a route upload file(s)
app.post('/v1/pets/:id/photos', function(req, res, next) {
app.post('/v1/pets/:id/photos', function(req: Request, res: Response) {
// DO something with the file
// files are found in req.files
// non file multipar params are in req.body['my-param']
Expand Down
3 changes: 2 additions & 1 deletion test/response.validator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as jsyaml from 'js-yaml';
import { expect } from 'chai';
import { ResponseValidator } from '../src/middlewares/openapi.response.validator';
import * as packageJson from '../package.json';
import { OpenAPIV3 } from '../src/framework/types';

const apiSpecPath = path.join('test', 'resources', 'response.validation.yaml');
const apiSpec = jsyaml.safeLoad(fs.readFileSync(apiSpecPath, 'utf8'));
Expand Down Expand Up @@ -94,7 +95,7 @@ describe(packageJson.name, () => {
}
});
});
function petsResponseSchema() {
function petsResponseSchema(): OpenAPIV3.ResponsesObject{
return {
'200': {
description: 'pet response',
Expand Down

0 comments on commit 73111e0

Please sign in to comment.