Skip to content

Commit

Permalink
Merge aeedf75 into 0f8ec69
Browse files Browse the repository at this point in the history
  • Loading branch information
nicofuccella committed May 17, 2021
2 parents 0f8ec69 + aeedf75 commit acb0abb
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 0 deletions.
@@ -0,0 +1,39 @@
// args.apiDoc needs to be a js object. This file could be a json file, but we can't add
// comments in json files.
module.exports = {
swagger: '2.0',

// all routes will now have /v3 prefixed.
basePath: '/v3',

info: {
title: 'express-openapi sample project',
version: '3.0.0',
},

definitions: {
Error: {
additionalProperties: true,
},
User: {
properties: {
name: {
type: 'string',
},
friends: {
type: 'array',
items: {
$ref: '#/definitions/User',
},
},
},
required: ['name'],
additionalProperties: false,
},
},

// paths are derived from args.routes. These are filled in by fs-routes.
paths: {},

tags: [{ name: 'users' }],
};
@@ -0,0 +1,54 @@
module.exports = {
// parameters for all operations in this path
parameters: [
{
name: 'id',
in: 'path',
type: 'string',
required: true,
description: "Fred's age.",
},
],
// or they may also be an array of middleware + the method handler. This allows
// for flexible middleware management. express-openapi middleware generated from
// the <path>.parameters + <methodHandler>.apiDoc.parameters is prepended to this
// array.
post: [
function (req, res, next) {
next();
},
function (req, res) {
res.status(200).json(req.body);
},
],
};

module.exports.post.apiDoc = {
description: 'Create a user.',
operationId: 'createUser',
tags: ['users'],
parameters: [
{
name: 'user',
in: 'body',
schema: {
$ref: '#/definitions/User',
},
},
],

responses: {
200: {
description: 'Requested user',
schema: {
$ref: '#/definitions/User',
},
},
default: {
description: 'Unexpected error',
schema: {
$ref: '#/definitions/Error',
},
},
},
};
@@ -0,0 +1,28 @@
var app = require('express')();
var bodyParser = require('body-parser');
// normally you'd just do require('express-openapi'), but this is for test purposes.
var openapi = require('../../../');
var path = require('path');
var cors = require('cors');

app.use(cors());
app.use(bodyParser.json());

openapi.initialize({
apiDoc: require('./api-doc.js'),
app: app,
paths: path.resolve(__dirname, 'api-routes'),
requestAjvOptions: { removeAdditional: true },
});

app.use(function (err, req, res, next) {
err.status = err.status || 500;
res.status(err.status).json(err);
});

module.exports = app;

var port = parseInt(process.argv[2], 10);
if (port) {
app.listen(port);
}
@@ -0,0 +1,53 @@
// args.apiDoc needs to be a js object. This file could be a json file, but we can't add
// comments in json files.
module.exports = {
swagger: '2.0',

// all routes will now have /v3 prefixed.
basePath: '/v3',

info: {
title: 'express-openapi sample project',
version: '3.0.0',
},

definitions: {
Error: {
additionalProperties: true,
},
User: {
properties: {
name: {
type: 'string',
},
friends: {
type: 'array',
items: {
$ref: '#/definitions/User',
},
},
},
required: ['name'],
},
UserRes: {
properties: {
name: {
type: 'string',
},
friends: {
type: 'array',
items: {
$ref: '#/definitions/User',
},
},
},
required: ['name'],
additionalProperties: false,
},
},

// paths are derived from args.routes. These are filled in by fs-routes.
paths: {},

tags: [{ name: 'users' }],
};
@@ -0,0 +1,55 @@
module.exports = {
// parameters for all operations in this path
parameters: [
{
name: 'id',
in: 'path',
type: 'string',
required: true,
description: "Fred's age.",
},
],
// or they may also be an array of middleware + the method handler. This allows
// for flexible middleware management. express-openapi middleware generated from
// the <path>.parameters + <methodHandler>.apiDoc.parameters is prepended to this
// array.
post: [
function (req, res, next) {
next();
},
function (req, res) {
res.validateResponse(200, req.body);
res.status(200).json(req.body);
},
],
};

module.exports.post.apiDoc = {
description: 'Create a user.',
operationId: 'createUser',
tags: ['users'],
parameters: [
{
name: 'user',
in: 'body',
schema: {
$ref: '#/definitions/User',
},
},
],

responses: {
200: {
description: 'Requested user',
schema: {
$ref: '#/definitions/UserRes',
},
},
default: {
description: 'Unexpected error',
schema: {
$ref: '#/definitions/Error',
},
},
},
};
@@ -0,0 +1,28 @@
var app = require('express')();
var bodyParser = require('body-parser');
// normally you'd just do require('express-openapi'), but this is for test purposes.
var openapi = require('../../../');
var path = require('path');
var cors = require('cors');

app.use(cors());
app.use(bodyParser.json());

openapi.initialize({
apiDoc: require('./api-doc.js'),
app: app,
paths: path.resolve(__dirname, 'api-routes'),
responseAjvOptions: { removeAdditional: true },
});

app.use(function (err, req, res, next) {
err.status = err.status || 500;
res.status(err.status).json(err);
});

module.exports = app;

var port = parseInt(process.argv[2], 10);
if (port) {
app.listen(port);
}
8 changes: 8 additions & 0 deletions packages/openapi-framework/index.ts
@@ -1,3 +1,4 @@
import * as Ajv from 'ajv';
import fsRoutes from 'fs-routes';
import OpenAPIDefaultSetter from 'openapi-default-setter';
import OpenAPIRequestCoercer from 'openapi-request-coercer';
Expand Down Expand Up @@ -86,6 +87,8 @@ export default class OpenAPIFramework implements IOpenAPIFramework {
private validateApiDoc;
private validator;
private logger: Logger;
private requestAjvOptions: Ajv.Options;
private responseAjvOptions: Ajv.Options;

constructor(protected args = {} as OpenAPIFrameworkConstructorArgs) {
this.name = args.name;
Expand Down Expand Up @@ -183,6 +186,9 @@ export default class OpenAPIFramework implements IOpenAPIFramework {
);
}
}

this.requestAjvOptions = args.requestAjvOptions;
this.responseAjvOptions = args.responseAjvOptions;
}

public initialize(visitor: OpenAPIFrameworkVisitor) {
Expand Down Expand Up @@ -443,6 +449,7 @@ export default class OpenAPIFramework implements IOpenAPIFramework {
route
),
customFormats: this.customFormats,
ajvOptions: this.responseAjvOptions,
});

operationContext.features.responseValidator = responseValidator;
Expand Down Expand Up @@ -487,6 +494,7 @@ export default class OpenAPIFramework implements IOpenAPIFramework {
customFormats: this.customFormats,
customKeywords: this.customKeywords,
requestBody,
ajvOptions: this.requestAjvOptions,
});
operationContext.features.requestValidator = requestValidator;
this.logger.debug(
Expand Down
2 changes: 2 additions & 0 deletions packages/openapi-framework/src/types.ts
Expand Up @@ -97,6 +97,8 @@ interface OpenAPIFrameworkArgs {
securityHandlers?: SecurityHandlers; // TODO define the handlers more here
validateApiDoc?: boolean;
logger?: Logger;
requestAjvOptions?: Ajv.Options;
responseAjvOptions?: Ajv.Options;
}

export interface OpenAPIFrameworkAPIContext {
Expand Down
@@ -0,0 +1,7 @@
swagger: '2.0'
info:
title: sample api doc
version: '3'
security:
- basic: []
paths: {}
@@ -0,0 +1,23 @@
module.exports = {
GET,
};

function GET() {
return;
}
GET.apiDoc = {
parameters: [
{
format: 'foo',
in: 'query',
name: 'foo',
type: 'string',
},
],
responses: {
default: {
description: 'return foo',
schema: {},
},
},
};
@@ -0,0 +1,21 @@
import { expect } from 'chai';
import OpenapiFramework from '../../../';
const path = require('path');

describe(path.basename(__dirname), () => {
let framework: OpenapiFramework;

beforeEach(() => {
framework = new OpenapiFramework({
apiDoc: path.resolve(__dirname, 'apiDoc.yml'),
featureType: 'middleware',
name: 'some-framework',
paths: path.resolve(__dirname, 'paths'),
requestAjvOptions: { removeAdditional: true },
});
});

it('should work', () => {
framework.initialize({});
});
});
@@ -0,0 +1,7 @@
swagger: '2.0'
info:
title: sample api doc
version: '3'
security:
- basic: []
paths: {}
@@ -0,0 +1,23 @@
module.exports = {
GET,
};

function GET() {
return;
}
GET.apiDoc = {
parameters: [
{
format: 'foo',
in: 'query',
name: 'foo',
type: 'string',
},
],
responses: {
default: {
description: 'return foo',
schema: {},
},
},
};

0 comments on commit acb0abb

Please sign in to comment.