koa-oas-router
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -14,2 +14,3 @@ import * as Router from 'koa-router'; | ||
* Creates an instance of KoaOasRouter. | ||
* @param {IRouterOptions} [opt] | ||
* @memberof KoaOasRouter | ||
@@ -26,7 +27,7 @@ */ | ||
* @param {Specification} specification | ||
* @param {ReadSpecificationOpts} opts | ||
* @param {AddFromSpecificationOpts} [opts] | ||
* @returns {Promise<any>} | ||
* @memberof KoaOasRouter | ||
*/ | ||
addRoutesFromSpecification(specification: Specification, opts?: ReadSpecificationOpts): Promise<any>; | ||
addRoutesFromSpecification(specification: Specification, opts?: AddFromSpecificationOpts): Promise<any>; | ||
private createStubFromSpec; | ||
@@ -36,6 +37,25 @@ private mapToRouter; | ||
} | ||
/** | ||
* This is a extension of the Router.IRouterOptions. | ||
* | ||
* @export | ||
* @interface IRouterOptions | ||
* @property {Logger} [logger] A node-logger object | ||
* @property {string} [logLevel] Specifies the log level ('fatal' | 'error' | 'warn' | 'info' | 'debug') will be ignored if logger is specified | ||
* @extends {Router.IRouterOptions} | ||
*/ | ||
export interface IRouterOptions extends Router.IRouterOptions { | ||
logger: Logger; | ||
logger?: Logger; | ||
logLevel?: string; | ||
} | ||
interface ReadSpecificationOpts { | ||
/** | ||
* Options for adding the routes from a oas specification. | ||
* | ||
* @export | ||
* @interface AddFromSpecificationOpts | ||
* @property {string} [controllerBasePath] The base path in which the controllers can be found. | ||
* @property {boolean} [validateSpecification] Specifies if the oas-validator should be used. | ||
* @property {boolean} [provideStubs] Specifies if stubs should be provided. | ||
*/ | ||
export interface AddFromSpecificationOpts { | ||
controllerBasePath?: string; | ||
@@ -45,2 +65,10 @@ validateSpecification?: boolean; | ||
} | ||
/** | ||
* The oas specification as js object. (Convert it via js-yaml) | ||
* | ||
* @export | ||
* @interface Specification | ||
* @property {Paths} paths Object that hold all the paths. | ||
* @property {any} [x] Different other values. | ||
*/ | ||
export interface Specification { | ||
@@ -50,6 +78,30 @@ paths: Paths; | ||
} | ||
interface Paths { | ||
[path: string]: Path; | ||
/** | ||
* Representation of the oas paths. | ||
* | ||
* @export | ||
* @interface Paths | ||
* @property {Path} pathName Index type! Specifies one path object of oas. PathName is a string that specifies the path. | ||
*/ | ||
export interface Paths { | ||
[path: string]: { | ||
get?: Operation; | ||
post?: Operation; | ||
put?: Operation; | ||
patch?: Operation; | ||
delete?: Operation; | ||
}; | ||
} | ||
interface Path { | ||
/** | ||
* Representation of the oas path. | ||
* | ||
* @export | ||
* @interface Path | ||
* @property {Operation} [get] Specifies the get operation of the oas path. | ||
* @property {Operation} [post] Specifies the post operation of the oas path. | ||
* @property {Operation} [put] Specifies the put operation of the oas path. | ||
* @property {Operation} [patch] Specifies the patch operation of the oas path. | ||
* @property {Operation} [delete] Specifies the delete operation of the oas path. | ||
*/ | ||
export interface Path { | ||
get?: Operation; | ||
@@ -61,3 +113,12 @@ post?: Operation; | ||
} | ||
interface Operation { | ||
/** | ||
* Representation of one operation. | ||
* | ||
* @export | ||
* @interface Operation | ||
* @property {string} operationId Specifies the oas operationId. | ||
* @property {string[]} tags Specifies an array of oas tags. | ||
* @property {string} [x] Additional values. | ||
*/ | ||
export interface Operation { | ||
operationId: string; | ||
@@ -72,2 +133,1 @@ tags: string[]; | ||
} | ||
export {}; |
@@ -19,22 +19,4 @@ "use strict"; | ||
var logger_1 = require("logger"); | ||
var CONTROLLER_BASE_PATH = '../controller'; | ||
var VALIDATE_SPECIFICATION = true; | ||
var PROVIDE_STUBS = true; | ||
var FATAL_mapToRouter_INVALIDMETHOD = 'Invalid method:'; | ||
var ERROR_addRoutesFromSpecification_SPECUNDEFINED = 'Specification not defined!'; | ||
var ERROR_addRoutesFromSpecification_PATHUNDEFINED = 'Paths not found!'; | ||
var ERROR_addRoutesFromSpecification_IMPORTERROR = 'Import failed:'; | ||
var INFO_addRoutesFromSpecification_INITCONTROLLERBASEPATH = 'Basepath of controller:'; | ||
var INFO_addRoutesFromSpecification_INITVALIDATESPEC = 'Validate specification?'; | ||
var INFO_addRoutesFromSpecification_INITPROVIDESTUBS = 'Do provide stubs?'; | ||
var INFO_mapToRouter_MAPPED = 'Mapped method of path to controller:'; | ||
var DEBUG_addRoutesFromSpecification_LOOPTAGS = 'Looping through these tags:'; | ||
var DEBUG_addRoutesFromSpecification_LOOPOPERATIONS = 'Looping through these operations:'; | ||
var DEBUG_addRoutesFromSpecification_TRYTOIMPORTCONTROLLER = 'Try to import controller with path:'; | ||
var DEBUG_addRoutesFromSpecification_IMPORTCONTROLLER = 'Imported controller:'; | ||
var DEBUG_addRoutesFromSpecification_IMPORTMODULENOTFOUND = 'Module of following controller not found:'; | ||
var DEBUG_addRoutesFromSpecification_CONTROLLERFUNCTIONFOUND = 'Found function in controller:'; | ||
var DEBUG_addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND = 'Function not found:'; | ||
var WARN_addRoutesFromSpecification_IMPORTMODULENOTFOUND = 'Module not found and don\'t provide stub:'; | ||
var WARN_addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND = 'Function not found and don\'t provide stub:'; | ||
var CONST = require("./const.json"); | ||
var STRINGS = require("./strings.json"); | ||
/** | ||
@@ -51,2 +33,3 @@ * A child class of the koa-router. It extends the koa-router by some features that can be used with oas. | ||
* Creates an instance of KoaOasRouter. | ||
* @param {IRouterOptions} [opt] | ||
* @memberof KoaOasRouter | ||
@@ -73,3 +56,3 @@ */ | ||
* @param {Specification} specification | ||
* @param {ReadSpecificationOpts} opts | ||
* @param {AddFromSpecificationOpts} [opts] | ||
* @returns {Promise<any>} | ||
@@ -83,17 +66,17 @@ * @memberof KoaOasRouter | ||
if (!specification) { | ||
this.logger.error(ERROR_addRoutesFromSpecification_SPECUNDEFINED); | ||
Promise.reject(ERROR_addRoutesFromSpecification_SPECUNDEFINED); | ||
this.logger.error(STRINGS.logger.error.addRoutesFromSpecification_SPECUNDEFINED); | ||
Promise.reject(STRINGS.logger.error.addRoutesFromSpecification_SPECUNDEFINED); | ||
} | ||
if (!specification.paths) { | ||
this.logger.error(ERROR_addRoutesFromSpecification_PATHUNDEFINED); | ||
Promise.reject(ERROR_addRoutesFromSpecification_PATHUNDEFINED); | ||
this.logger.error(STRINGS.logger.error.addRoutesFromSpecification_PATHUNDEFINED); | ||
Promise.reject(STRINGS.logger.error.addRoutesFromSpecification_PATHUNDEFINED); | ||
} | ||
// Initialize default values | ||
opts = opts ? opts : {}; | ||
var controllerBasePath = (opts.controllerBasePath) ? opts.controllerBasePath : CONTROLLER_BASE_PATH; | ||
var validateSpecification = (opts.validateSpecification) ? opts.validateSpecification : VALIDATE_SPECIFICATION; | ||
var provideStubs = (opts.provideStubs) ? opts.provideStubs : PROVIDE_STUBS; | ||
this.logger.info(INFO_addRoutesFromSpecification_INITCONTROLLERBASEPATH, controllerBasePath); | ||
this.logger.info(INFO_addRoutesFromSpecification_INITVALIDATESPEC, validateSpecification.toString()); | ||
this.logger.info(INFO_addRoutesFromSpecification_INITPROVIDESTUBS, provideStubs.toString()); | ||
var controllerBasePath = (opts.controllerBasePath) ? opts.controllerBasePath : CONST.addRoutesFromSpecification.CONTROLLER_BASE_PATH; | ||
var validateSpecification = (opts.validateSpecification) ? opts.validateSpecification : CONST.addRoutesFromSpecification.VALIDATE_SPECIFICATION; | ||
var provideStubs = (opts.provideStubs) ? opts.provideStubs : CONST.addRoutesFromSpecification.PROVIDE_STUBS; | ||
this.logger.info(STRINGS.logger.info.addRoutesFromSpecification_INITCONTROLLERBASEPATH, controllerBasePath); | ||
this.logger.info(STRINGS.logger.info.addRoutesFromSpecification_INITVALIDATESPEC, validateSpecification.toString()); | ||
this.logger.info(STRINGS.logger.info.addRoutesFromSpecification_INITPROVIDESTUBS, provideStubs.toString()); | ||
// Get the mapping tag -> operation (with operationId) -> {path, operationSpecification} | ||
@@ -103,12 +86,12 @@ var operationTagMapping = this.mapOperationsByTag(specification.paths); | ||
var tags = Object.keys(operationTagMapping); | ||
this.logger.debug(DEBUG_addRoutesFromSpecification_LOOPTAGS, tags.toString()); | ||
this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_LOOPTAGS, tags.toString()); | ||
tags.forEach(function (tagName) { | ||
var operationMapping = operationTagMapping[tagName]; | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_TRYTOIMPORTCONTROLLER, path.join(controllerBasePath, tagName.toPascalCase())); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_TRYTOIMPORTCONTROLLER, path.join(controllerBasePath, tagName.toPascalCase())); | ||
// Import the controller belonging to it | ||
importPromises.push(Promise.resolve().then(function () { return require(path.join(controllerBasePath, tagName.toPascalCase())); }).then(function (controller) { | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_IMPORTCONTROLLER, tagName.toPascalCase()); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_IMPORTCONTROLLER, tagName.toPascalCase()); | ||
// For each operation (with operationId) | ||
var operationIds = Object.keys(operationMapping); | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_LOOPOPERATIONS, operationIds.toString()); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_LOOPOPERATIONS, operationIds.toString()); | ||
operationIds.forEach(function (operationId) { | ||
@@ -119,3 +102,3 @@ var operation = operationMapping[operationId]; | ||
if (operationInController) { | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_CONTROLLERFUNCTIONFOUND, operationId); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_CONTROLLERFUNCTIONFOUND, operationId); | ||
// If it is defined: Map the funcion to the router by the path and the method. | ||
@@ -125,3 +108,3 @@ _this.mapToRouter(operation.path, operation.method, operationInController, tagName.toPascalCase()); | ||
else { | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND, operationId); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND, operationId); | ||
// If it is not defined: create a stub if the flag is set. | ||
@@ -132,3 +115,3 @@ if (provideStubs) { | ||
else { | ||
_this.logger.warn(WARN_addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND, operationId); | ||
_this.logger.warn(STRINGS.logger.warn.addRoutesFromSpecification_CONTROLLERFUNCTIONNOTFOUND, operationId); | ||
} | ||
@@ -140,12 +123,12 @@ } | ||
if (error.code === 'MODULE_NOT_FOUND') { | ||
_this.logger.debug(DEBUG_addRoutesFromSpecification_IMPORTMODULENOTFOUND, tagName.toPascalCase()); | ||
_this.logger.debug(STRINGS.logger.debug.addRoutesFromSpecification_IMPORTMODULENOTFOUND, tagName.toPascalCase()); | ||
if (provideStubs) { | ||
_this.createStubFromSpec(operationMapping); | ||
_this.createStubFromSpec({ operationMapping: operationMapping }); | ||
} | ||
else { | ||
_this.logger.warn(WARN_addRoutesFromSpecification_IMPORTMODULENOTFOUND, tagName.toPascalCase()); | ||
_this.logger.warn(STRINGS.logger.warn.addRoutesFromSpecification_IMPORTMODULENOTFOUND, tagName.toPascalCase()); | ||
} | ||
} | ||
else { | ||
_this.logger.error(ERROR_addRoutesFromSpecification_IMPORTERROR, error.message); | ||
_this.logger.error(STRINGS.logger.error.addRoutesFromSpecification_IMPORTERROR, error.message); | ||
throw error; | ||
@@ -158,47 +141,52 @@ } | ||
KoaOasRouter.prototype.createStubFromSpec = function (toStub) { | ||
var _this = this; | ||
var dummyFunction = function (ctx, next) { | ||
ctx.body = { code: 501, message: 'Not Implemented' }; | ||
ctx.status = 501; | ||
}; | ||
if (!toStub) { | ||
throw new Error('Specification cannot be undefined'); | ||
} | ||
// TODO call routes mapping function | ||
// this.mapToRouter(path, method, dummyFunction, 'Stub'); | ||
if ('path' in toStub) { | ||
// If only single operation | ||
this.mapToRouter(toStub.path, toStub.method, dummyFunction, 'Stub'); | ||
} | ||
else { | ||
// If whole controller | ||
// recursive? | ||
var opertionIds = Object.keys(toStub.operationMapping); | ||
opertionIds.forEach(function (operationId) { | ||
_this.createStubFromSpec({ path: toStub.operationMapping[operationId].path, method: toStub.operationMapping[operationId].method }); | ||
}); | ||
} | ||
}; | ||
KoaOasRouter.prototype.mapToRouter = function (path, method, controllerFunction, controllerName) { | ||
path = path.replace(/{/g, ':').replace(/}/g, ''); | ||
KoaOasRouter.prototype.mapToRouter = function (pathToMap, method, controllerFunction, controllerName) { | ||
pathToMap = pathToMap.replace(/{/g, ':').replace(/}/g, ''); | ||
controllerName = controllerName ? controllerName : ''; | ||
switch (method) { | ||
case 'get': { | ||
this.get(path, controllerFunction); | ||
this.logger.info(INFO_mapToRouter_MAPPED, method, path, controllerName); | ||
this.get(pathToMap, controllerFunction); | ||
this.logger.info(STRINGS.logger.info.mapToRouter_MAPPED, method, pathToMap, controllerName); | ||
break; | ||
} | ||
case 'post': { | ||
this.post(path, controllerFunction); | ||
this.logger.info(INFO_mapToRouter_MAPPED, method, path, controllerName); | ||
this.post(pathToMap, controllerFunction); | ||
this.logger.info(STRINGS.logger.info.mapToRouter_MAPPED, method, pathToMap, controllerName); | ||
break; | ||
} | ||
case 'put': { | ||
this.put(path, controllerFunction); | ||
this.logger.info(INFO_mapToRouter_MAPPED, method, path, controllerName); | ||
this.put(pathToMap, controllerFunction); | ||
this.logger.info(STRINGS.logger.info.mapToRouter_MAPPED, method, pathToMap, controllerName); | ||
break; | ||
} | ||
case 'patch': { | ||
this.patch(path, controllerFunction); | ||
this.logger.info(INFO_mapToRouter_MAPPED, method, path, controllerName); | ||
this.patch(pathToMap, controllerFunction); | ||
this.logger.info(STRINGS.logger.info.mapToRouter_MAPPED, method, pathToMap, controllerName); | ||
break; | ||
} | ||
case 'delete': { | ||
this.delete(path, controllerFunction); | ||
this.logger.info(INFO_mapToRouter_MAPPED, method, path, controllerName); | ||
this.delete(pathToMap, controllerFunction); | ||
this.logger.info(STRINGS.logger.info.mapToRouter_MAPPED, method, pathToMap, controllerName); | ||
break; | ||
} | ||
default: { | ||
this.logger.fatal(FATAL_mapToRouter_INVALIDMETHOD, method); | ||
throw new Error(FATAL_mapToRouter_INVALIDMETHOD + ' ' + method); | ||
this.logger.fatal(STRINGS.logger.fatal.mapToRouter_INVALIDMETHOD, method); | ||
throw new Error(STRINGS.logger.fatal.mapToRouter_INVALIDMETHOD + ' ' + method); | ||
} | ||
@@ -250,2 +238,11 @@ } | ||
exports.KoaOasRouter = KoaOasRouter; | ||
; | ||
; | ||
; | ||
; | ||
; | ||
; | ||
; | ||
; | ||
; | ||
/** | ||
@@ -252,0 +249,0 @@ * Convert a string to Pascal Case (removing non alphabetic characters). |
{ | ||
"name": "koa-oas-router", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "This module extends the koa-router with some features usable with oas.", | ||
@@ -8,2 +8,3 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"doc:api": "jsdoc2md --files ./src/**/*.ts --configure ./jsdoc2md.json > ./docs/API.md", | ||
"test": "ava", | ||
@@ -31,2 +32,8 @@ "start:test": "ts-node tmp/test.js", | ||
"devDependencies": { | ||
"@babel/cli": "^7.5.5", | ||
"@babel/core": "^7.5.5", | ||
"@babel/plugin-proposal-class-properties": "^7.5.5", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.5.5", | ||
"@babel/preset-env": "^7.5.5", | ||
"@babel/preset-typescript": "^7.3.3", | ||
"@types/koa-router": "^7.0.42", | ||
@@ -36,2 +43,4 @@ "@types/logger": "0.0.0", | ||
"ava": "^2.2.0", | ||
"jsdoc-babel": "^0.5.0", | ||
"jsdoc-to-markdown": "^5.0.0", | ||
"rimraf": "^2.6.3", | ||
@@ -38,0 +47,0 @@ "ts-node": "^8.3.0", |
@@ -1,5 +0,62 @@ | ||
# koa-oas-router | ||
This module extends the koa-router with some features usable with oas. | ||
# Welcome to koa-oas-router 👋 | ||
 | ||
[](https://github.com/maHecht/koa-oas-router#readme) | ||
[](https://github.com/maHecht/koa-oas-router/graphs/commit-activity) | ||
[](https://github.com/maHecht/koa-oas-router/blob/master/LICENSE) | ||
## information | ||
More information coming soon. | ||
> This module extends the koa-router with some features usable with oas. | ||
### 🏠 [Homepage](https://github.com/maHecht/koa-oas-router#readme) | ||
## Install | ||
```sh | ||
npm i koa-oas-router --save | ||
``` | ||
## Usage | ||
```js | ||
const KoaOasRouter = require('koa-oas-router'); | ||
const router = new KoaOasRouter.KoaOasRouter(opts) | ||
``` | ||
```typescript | ||
import { KoaOasRouter } from 'koa-oas-router'; | ||
const router = new KoaOasRouter(opts); | ||
``` | ||
## API | ||
[API](docs/API.md) | ||
## Run tests | ||
```sh | ||
npm run test | ||
``` | ||
## Author | ||
👤 **Matthias Hecht** | ||
* Github: [@maHecht](https://github.com/maHecht) | ||
## 🤝 Contributing | ||
Contributions, issues and feature requests are welcome! | ||
Feel free to check [issues page](https://github.com/maHecht/koa-oas-router/issues). | ||
## Show your support | ||
Give a ⭐️ if this project helped you! | ||
## 📝 License | ||
Copyright © 2019 [Matthias Hecht](https://github.com/maHecht). | ||
This project is [MIT](https://github.com/maHecht/koa-oas-router/blob/master/LICENSE) licensed. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
31167
9
432
63
16