npm package: @noveo/swagger-middleware
Description: The package is a wrapper for [swagger-express-middleware@1.1.1](https://github.com/APIDevTools/swagger-express-middleware) It helps you to deal with swagger@2.0 defined apis. It does NOT support openapi@3
Author: Noveo
Latest version: 0.4.0-beta

# @noveo/swagger-middleware
The package is a wrapper for [swagger-express-middleware@1.1.1](https://github.com/APIDevTools/swagger-express-middleware)
It helps you to deal with swagger@2.0 defined apis.
It does NOT support openapi@3



## install
```
npm i --save @noveo/swagger-middleware
```
or
```
npm i --save git+https://gitlab%2Bdeploy-token-10:y6fu7AnyXgsxn1sJ6zxz@gitlab.noveogroup.com/devteam/back/swagger-middleware.git
```



## usage
```javascript
const swagger = require('@noveo/swagger-middleware');

// Load modules
const loaded = await swagger.loaders.byPackageJson({
  folders: ['essences', 'scenarios'],
  root: __dirname,
  logger: log.child('modules-loader'),
  baseApiPath: resolve(__dirname, './api.yml'),
  app: { name: appName, version },
  server: { protocol, host, port }
});

const app = express();

// Init secureCollection for adding secure adapters 
const secureCollection = swagger.secureCollection;
// Adapters presets for security
const adapters = swagger.adapters;

// Initiate adapter with apiKey presets to secureCollection, passing function secure ad 2nd parameter for checking security
await secureCollection.add(adapters.apiKey, {
    check(key) {
        return key === 'authKey'
    }
});

// Initiate adapter with basic auth presets to secureCollection, passing function secure ad 2nd parameter for checking security
await secureCollection.add(adapters.basic, {
    check(email, password) {
        const user  = db.users.findOne({email}, ['password', 'salt']).lean();
        
        if (! user) {
            return false;
        }
        
        const cryptoPassword = sha512(password, user.salt);
        
        return (cryptoPassword === user.password);
    }
});


// Init Doc UI and schema get endpoint
app.use(api.basePath, middleware.docs({
  jsonPath: '/swagger.json',
  yamlPath: '/swagger.yaml',
  ui: {
    baseUrl: '/ui/',
    docUrl: `${api.basePath}/swagger.json`
  }
}));

app.use(
  // Checks out the correctness of json-response via the provided 
  // OpenAPI 2 or OpenAPI 3 schema
  middleware.validateResponse(),  
  // Annotates each request with all the relevant information from the Swagger definition. 
  // The path, the operation, the parameters, the security requirements. 
  // They’re all easily accessible at req.swagger. It just parses parameters definitions from the API, not the values.
  // Values are parsed by parseRequest
  middleware.metadata(),    
  // Initiate secure middleware passing secureCollection to it
  middleware.secure(secureCollection),
  // Adds the appropriate CORS headers to each request and automatically responds to CORS preflight requests,
  // all in compliance with your Swagger API definition.
  middleware.CORS(),
  // Parses incoming requests and converts everything into the correct data types, 
  // according to your Swagger API definition.
  // It uses body-parser, cookie-parser, multer
  middleware.parseRequest(),
  // Ensures that every request complies with your Swagger API definition, 
  // or returns the appropriate HTTP error codes if needed
  middleware.validateRequest(),
  // You may put handlerStorage made by modules loader or by your hands
  middleware.handler({
    handlerStorage: loaded.handlerStorage
  }),
  // It is for mocks
  middleware.mock(),
);

app.listen(8000);
```



## QnA
### Why do we use our `docs` middleware? Why don't we use swagger-express-middleware `files` middleware
Our middleware provides not only json api definition, but It provides yaml definition too.
Then our middleware provides api definition explorer UI. You may use `files` middleware if you need or
if you find `docs` middleware incompatible for you or insecure etc. Please, notice the maintainer 
if you have any issues 


## Debug and logging
It uses [debug](https://github.com/visionmedia/debug) with main prefix as `swagger` as default logger ;


## API
Exported lib is an object with two properties: initMiddleware and loaders

- [initMiddleware(options)](#initMiddleware)
    - [initMiddlewareResponse](#initMiddlewareResponse)
        - [middlewareFactories](#middlewareFactories)
            - [docs(options)](#docsMiddlewareFactory)
            - [handler(options)](#handlerMiddlewareFactory)
            - [validateResponse(options)](#validateResponse)
- [loaders](#loaders)
    - [loaderResponse](#loaderResponse)
    - [byPackageJsonLoader(options)](#byPackageJsonLoader)
        - [byPackageJsonLoader-packageDef](#byPackageJsonLoader-packageDef)
        


<a name="initMiddleware"></a>
### initMiddleware(options) ⇒ <code>Promise.<[initMiddlewareResponse](#initMiddlewareResponse)></code>
It is a wrapper for `swagger-express-middleware#createMiddleware`.
It initializes middlewares

**Kind**: `Function`<br/>
**Returns**: <code>Promise.<[initMiddlewareResponse](#initMiddlewareResponse)></code>

| Param             | Type                                           | Mandatory    | Default                                                                     | Example                               | Description                          |
| ----------------- | :--------------------------------------------: | :----------: | :-------------------------------------------------------------------------: | :-----------------------------------: | ------|
| options.apiDef    | `Object` or `String`                           | **REQUIRED** |                                                                             | `'./api.yml'`                         | A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object), or the json file path or URL of your Swagger API. It is forwarded to [swagger-parser.dereference](https://apidevtools.org/swagger-parser/docs/swagger-parser.html#dereferenceapi-options-callback) |
| options.app       | `express#Router`                               | **REQUIRED** |                                                                             | `express()`                           | An [Express app](https://expressjs.com/en/4x/api.html#app) It is forwarded to swagger-express-middleware#createMiddleware method |
| options.logger    | <code>[loggerInstance](#loggerInstance)</code> | Optional     | [debug](https://github.com/visionmedia/debug) with main prefix as `swagger` | `noveoLogger.getLogger('swagger')`    | Logger instance |
|                   | thisisforcellwithyeah                          |              |                                                                             | thisisforcellwidthyeah                |      |



<a name="initMiddlewareResponse"></a>
### initMiddlewareResponse
`middleware` is initialized by `swagger-express-middleware#createMiddleware`.
Then some middleware factories like `docs` and `handler` were added to `middleware`.
`api` and `parser` are from `swagger-express-middleware#createMiddleware`.
They are forwarded to callback as third and fourth params, but it is not documented.

**Kind**: `Object`

| Property   | Type                                                                                            | Description                          |
| ---------- | :---------------------------------------------------------------------------------------------: | -------------------------------------|
| middleware | <code>[middlewareFactories](#middlewareFactories)</code>                                        | Container with `swagger-express-middleware` middlewares and our middlewares |
| api        | `Object`                                                                                        | It is a [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object), dereferenced by [swager-parser.dereference](https://apidevtools.org/swagger-parser/docs/swagger-parser.html#dereferenceapi-options-callback)|
| parser     | <code>[SwaggerParser](https://apidevtools.org/swagger-parser/docs/swagger-parser.html)</code>   | It is a [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object), dereferenced by [swager-parser.dereference](https://apidevtools.org/swagger-parser/docs/swagger-parser.html#dereferenceapi-options-callback)|


<a name="middlewareFactories"></a>
### middlewareFactories

**Kind**: `Object` extends instance of swagger-express-middleware [Middleware class](https://github.com/APIDevTools/swagger-express-middleware/blob/master/docs/exports/Middleware.md)

| Property   | Type                                                                                     | Description                            |
| ---------- | :--------------------------------------------------------------------------------------: | -------------------------------------- |
| docs       | <code>[docsMiddlewareFactory](#docsMiddlewareFactory)</code>                             | Factory for creating docs middleware   |
| handler    | <code>[handlerMiddlewareFactory](#handlerMiddlewareFactory)</code>                       | Factory for creating handlerMiddleware |
| `<String>` |                                                                                          | Other factories of [`swagger-express-middleware`](https://github.com/APIDevTools/swagger-express-middleware/blob/master/docs/exports/Middleware.md)|


<a name="docsMiddlewareFactory"></a>
### docsMiddlewareFactory(options) ⇒ <code>[express.Router](http://expressjs.com/en/4x/api.html#router)</code>
Factory for middleware, which creates routes with json and yaml 
api definitions and ui documentation explorer.
The recommended way of usage is to hang it on express route defined as 
application basePath. For example, `app.use('/base-path', middleware.docs())`

**Kind**: `Function`<br/>
**Returns**: <code>[express.Router](http://expressjs.com/en/4x/api.html#router)</code> instance

| Param              | Type                                                                                  | Mandatory | Default                                                                                                                         | Example                               | Description                                                                                                                |
| ------------------ | :-----------------------------------------------------------------------------------: | :-------: | :-----------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------: | -------------------------------------------------------------------------------------------------------------------------  |
| options.jsonPath   | `String`                                                                              | Optional  | `undefined`                                                                                                                     | `'/swagger.json'`                     | Path for json api definition route. Route does not initialize if the option is falsey                                      |
| options.yamlPath   | `String`                                                                              | Optional  | `undefined`                                                                                                                     | `'/swagger.yaml'`                     | Path for yaml api definition route. Route does not initialize if the option is falsey                                      |
| options.ui.baseUrl | `String`                                                                              | Optional  | `undefined`                                                                                                                     | `'/ui/'`                              | Url for hanging on some ui routes for html, css, js files. Explorer UI does not initialize if the option is falsey         |
| options.ui.docUrl  | `String`                                                                              | Optional  | `'https://petstore.swagger.io/v2/swagger.json'`                                                                                 | `'/base-path/swagger.json'`           | Url could be relative or absolute. It should contains json api definition. Explorer UI helps to explore the api definition |
| options.router     | <code>[express.Router](http://expressjs.com/en/4x/api.html#router)</code> constructor | Optional  | `express.Router` of `express@4.16.4`                                                                                            | `express.Router`                      | You may put your own express.Router class of your express version                                                          |
| options.api        | `Object`                                                                              | Optional  | api produced by [initMiddleware](#initMiddleware)                                                                               | `{ swagger: '2.0', ... }`             | You may put your own dereferenced api def object                                                                           |
| options.logger     | <code>[loggerInstance](#loggerInstance)</code>                                        | Optional  | logger put to [initMiddleware](#initMiddleware) or [debug](https://github.com/visionmedia/debug) with main prefix as `swagger`  | `noveoLogger.getLogger('swagger')`    | Logger instance                                                                                                            |
|                    | thisisforcellwidthyeh                                                                 |           | thisisforcellwidthyeh                                                                                                           | thisisforcellwidthyeah                |                                                                                                                            |

#### Notice
Use `options.ui.baseUrl` with finishing slash like `/ui/` but not like `/ui`. 
It uses wildcard like `/ui/*` for express routing and `swagger-ui-dist` package, that uses relative paths like
`./swagger-ui.css`. So, the relative with `/base/ui` (without finishing slash) would be `/base/swagger-ui.css`,
which is incorrect. The relative with `/base/ui/` will be `/base/ui/swagger-ui.css`, which is correct.



<a name="handlerMiddlewareFactory"></a>
### handlerMiddlewareFactory(options) ⇒ <code>[express.Middleware](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples)</code>
It is a factory for producing a middleware that handles a handlers which are indexed by operationId.
It chooses an operationId by req.swagger data provided by `middleware.metadata` middleware.
It fails without `middleware.metadata` middleware.

**Kind**: `Function`<br/>
**Returns**: <code>[express.Middleware](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples)</code>

| Param                  | Type                                             | Mandatory    | Default                                                                                                                         | Example                                              | Description                      |
| ---------------------- | :----------------------------------------------: | :----------: | :-----------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------: | -------------------------------- |
| options.handlerStorage | Map                                              | **REQUIRED** |                                                                                                                                 | `new Map([['operationId', (req, res, next) => {}]])` | A storage of operations handlers |
| options.logger         | <code>[loggerInstance](#loggerInstance)</code>   | Optional     | logger put to [initMiddleware](#initMiddleware) or [debug](https://github.com/visionmedia/debug) with main prefix as `swagger`  | `noveoLogger.getLogger('swagger')`                   | Logger instance                  |



<a name="validateResponse"></a>
### validateResponseFactory(options) ⇒ <code>[express.Middleware](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples)</code>
It is a factory for response validation

**Kind**: `Function`<br/>
**Returns**: <code>[express.Middleware](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples)</code>

| Param                  | Type                                             | Mandatory    | Example                            | Default                                                                                                                          | Description                                      |
| ---------------------- | :---------------------------------------------:  | :----------: | :--------------------------------: | :------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------ |
| options.schema         | Object                                           | Optional     | `{ swagger: '2.0', ... }`          | api produced by [initMiddleware](#initMiddleware)                                                                                | You may put your own dereferenced api def object |
| options.logger         | <code>[loggerInstance](#loggerInstance)</code>   | Optional     | `noveoLogger.getLogger('swagger')` | logger put to [initMiddleware](#initMiddleware) or [debug](https://github.com/visionmedia/debug) with main prefix as `swagger`   | Logger instance                                  |



<a name="loaders"></a>
### loaders
Container for loaders. We have one implemented loader. Each loader should be a `Function`, that returns 
<code>Promise.<[loaderResponse](#loaderResponse)</code>

**Kind**: `Object`

| Property      | Type                                                     | Description                                      |
| ------------- | :------------------------------------------------------: | ------------------------------------------------ |
| byPackageJson | <code>[byPackageJsonLoader](#byPackageJsonLoader)</code> | Loader with algorithm based on package.json file |



<a name="loaderResponse"></a>
### loaderResponse
An object that loader should resolves

**Kind**: `Object`

| Property       | Type                                                                                                                         | Description                           |
| -------------- | :--------------------------------------------------------------------------------------------------------------------------: | ------------------------------------- |
| api            | `Object`                                                                                                                     | Dereferenced api definition object    |
| handlerStorage | <code>Map<String,[express.Middleware](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples)></code>     | A storage of operations handlers      |



<a name="byPackageJsonLoader"></a>
### byPackageJsonLoader(options) ⇒ <code>Promise<[loaderResponse](#loaderResponse)></code>

**Kind**: `Function`<br/>
**Returns**: <code>Promise<[loaderResponse](#loaderResponse)></code>

| Param                   | Type                                             | Mandatory    | Default                                                                     | Example                                | Description                                                                                                 | 
| ----------------------- | :----------------------------------------------: | :----------: | :-------------------------------------------------------------------------: | :------------------------------------: | ----------------------------------------------------------------------------------------------------------- |
| options.folders         | `String[]`                                       | Optional     | `[]`                                                                        | `['essences', 'modules']`              | Array of paths for modules directories. Paths are relative to the root path defined in the root option      |
| options.root            | `String`                                         | Optional     | `process.cwd()`                                                             | `'./home/web/app/modules-container'`   | It is path to root directory of modules.                                                                    |
| options.baseApiPath     | `String`                                         | **REQUIRED** |                                                                             | `'./home/web/app/swagger.yml'`         | Path to the api def with base api information                                                               |
| options.app.name        | `String`                                         | Optional     | `undefined`                                                                 | `'my-app'`                             | App name could be merge into api def `info.title` field                                                     |
| options.app.version     | `String`                                         | Optional     | `undefined`                                                                 | `'v0'`                                 | App version could be merged into api def `info.version` field                                               |
| options.server.protocol | `String`                                         | Optional     | `undefined`                                                                 | `'https'`                              | Server protocol could be merges into api def `schemes#0` field                                              |
| options.server.host     | `String`                                         | Optional     | `undefined`                                                                 | `'localhost'`                          | Server host partly could be merged into api def `host` field                                                |
| options.server.port     | `String` or `Number`                             | Optional     | `undefined`                                                                 | `'8000'`                               | Server port partly could be merged into api def `host` filed                                                |
| options.logger          | <code>[loggerInstance](#loggerInstance)</code>   | Optional     | [debug](https://github.com/visionmedia/debug) with main prefix as `swagger` | `noveoLogger.getLogger('swagger')`     | Logger instance                                                                                             |
|                         | thisisforcellwidth                               |              | thisisforcellwidth                                                          | thisisforcellwidth                     |                                                                                                             |


**How it loads modules**
- It looks for directories into the folders you pointed as `folders` option
- It looks for files `package.json` in the directories
- It considers `package.json` as `object` of [byPackageJsonLoader-packageDef](#byPackageJsonLoader-packageDef) type
- It loads api definitions from files described in api definition options
- It loads controllers from files described in api actions options
- If it finds valid package.json it loads the module as defined in package.json.
  That means it advances common api definition with module routes.
  
  

<a name="byPackageJsonLoader-packageDef"></a>
### byPackageJsonLoader-packageDef
It is an object that describes how to load module using [byPackageJsonLoader](#byPackageJsonLoader)

**Kind**: `Object`

| Property         | Type               | Example              | Description                          |
| ---------------- | :----------------: | :------------------: | ------------------------------------ | 
| name             | `String`           | `'Module name'`      | Name of the module                   |
| api[].definition | `String`           | `'./api.yml'`        | Path to the module api definition. It is forwarded to `swagger-parser` to [.dereference()](https://apidevtools.org/swagger-parser/docs/swagger-parser.html#dereferenceapi-options-callback) method. Look at `swagger-parser` if you have any questions    |
| api[].actions    | `String`           | `'./controllers.js'` | Path to the js file that exports object with props keys like operationIds in the module api definition. And props values should be route controllers which implement such interface as `function (req, res, next)`. Yes, it should be handlers like for express and for swagger-express-middleware. Each should responds with `res.send()` or `res.json()` or forwards errors with `next(err)` | 
|                  | thisisforcellwidth | thisisforcellwidth   |   | 




<a name="loggerInstance"></a>
### loggerInstance

**Kind**: `Object` instance of logger with defined methods

| Property         | Type                                     | Description                          |
| ---------------- | :--------------------------------------: | ------------------------------------ | 
| info             | <code>[logMethod](#logMethod)</code>     | logger on info level                 |
| debug            | <code>[logMethod](#logMethod)</code>     | logger on debug level                |
| warn             | <code>[logMethod](#logMethod)</code>     | logger on warn level                 | 
| error            | <code>[logMethod](#logMethod)</code>     | logger on error level                | 
|                  | thisisforcellwidth                 |                                      |



<a name="logMethod"></a>
### logMethod(msg)

**Kind**: `Function`
**Returns**: `void`

| Param | Type     | Mandatory    | Default | Example                    | Description          | 
| ----- | :------: | :----------: | :-----: | :------------------------: | -------------------- |
| msg   | `String` | Optional     | `''`    | `'controller is requestd'` | Message for logging  |
|       |          |              |         | thisisforcellwidth         |                      |


<a name="secure"></a>
### secure

**Kind**: `Function`
**Description** `Main secure middleware, checking every response for contain security`
**Returns**: `void`

| Param              | Type     | Mandatory    | Description                                                         |
| :----------------: | :------: | :----------: | :-----------------------------------------------------------------: |
| secureCollection   | Object   |  **REQUIRED**| Object that contains initiated secure functions                     |



<a name="secureCollection"></a>
### secureCollection

**Kind**: `Factory`
**Description** `Factory that used for adding/getting and store all security functions that passed to her.`
**Returns**: `void`

| Functions     | Example                                                  | Description                                      |
| :-----------: | :------------------------------------------------------: | :----------------------------------------------: |
| add           | `secureCollection.add(adapters.apiKey, {check => {}})`   | Add adapter to registeredAdapters list           |
| get           | `secureCollection.get(`apiKey`)`                         | Get adapter by name from registeredAdapters list |                                                                     |



<a name="adapters"></a>
### adapters

**Kind**: `Object`
**Description** `Collection that contains auth type templates like apiKey,basicAuth. Each element of collection is an object and contains adapter defaultType and init function`
**Returns**: `Object with adapters`

| Param              | Type     | Example                                 | Description             |
| :----------------: | :------: | :-------------------------------------: | :---------------------: |
| apiKey             | Object   | `{defaultType: 'apiKey', init() => {}`  | apiKey auth object      |
| basic              | Object   | `{defaultType: 'basic', init() => {}`   | basic auth object       |



## TODO and questions
- Add logging to responseValidation
- Check with security definitions
- Add tests
- Put secure and validateResponse into middlewareFactories description (documentation)
- Put secure and adapters into  Index (documentation)
- Update swagger-express-middleware to v2.0.0