Skip to content

Commit

Permalink
Merge pull request #39 from aleksandryackovlev/release-4.0.1
Browse files Browse the repository at this point in the history
Release 4.0.1
  • Loading branch information
aleksandryackovlev authored Jan 31, 2022
2 parents b9f8951 + 6e41e9c commit 336d528
Show file tree
Hide file tree
Showing 12 changed files with 1,262 additions and 1,260 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:

strategy:
matrix:
node-version: [12.x, 14.x]
node-version: [14.x, 16.x]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 14
registry-url: https://registry.npmjs.org/
- uses: actions/download-artifact@v2
with:
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [4.0.1](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/compare/v3.0.2...v4.0.1) (2022-01-31)


### ⚠ BREAKING CHANGES

* **generator:** The generation of `examples` can be overwritten
* **router:** Error handling must be confgured outside of the middleware.
* **options:** The deprecated `file` option is removed. The `locale` option is removed because
Faker.js is no longer used inside the middleware be default and should be configured separetely.
`jsfCallback` is renamed into `configure`.

### Features

* **generator:** allow to overwrite the behavior for `examples` ([1466fed](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/commit/1466fedd5efd61c1e6404c24c172432b6a8da6f8))


### Bug Fixes

* **operations:** support parameters in the path section ([90cbae6](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/commit/90cbae6371800ebf8256bf22da1f4d725637d078)), closes [#37](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/issues/37)


* **options:** refactor middleware options ([c7fdf85](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/commit/c7fdf85c304ca7066c44154738c530e207edfdbc))
* **router:** remove error handlers from the router ([3af3fc7](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/commit/3af3fc77d88a1c03eed1d32754eb813f786ddfa4))

### [3.0.2](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/compare/v3.0.1...v3.0.2) (2021-10-27)

### [3.0.1](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/compare/v3.0.0...v3.0.1) (2021-10-24)
Expand Down
79 changes: 67 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
</div>

[![npm][npm]][npm-url]
[![deps][deps]][deps-url]
[![Build Status](https://travis-ci.org/aleksandryackovlev/openapi-mock-express-middleware.svg?branch=master)](https://travis-ci.org/aleksandryackovlev/openapi-mock-express-middleware)
[![Build Status](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/workflows/build/badge.svg)](https://github.com/aleksandryackovlev/openapi-mock-express-middleware/actions)
[![codecov](https://codecov.io/gh/aleksandryackovlev/openapi-mock-express-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/aleksandryackovlev/openapi-mock-express-middleware)
[![size](https://packagephobia.now.sh/badge?p=openapi-mock-express-middleware)](https://packagephobia.now.sh/result?p=openapi-mock-express-middleware)

# openapi-mock-express-middleware

Generates an express mock server from an [Open API 3.0](https://swagger.io/docs/specification/about/) documentation.
Generates express mock-servers from [Open API 3.0](https://swagger.io/docs/specification/about/) specs.

## Installation

Expand All @@ -42,7 +41,7 @@ app.listen(80, () => console.log('Server listening on port 80'));
```

### Advanced Config
The middleware uses [json-schmea-faker](https://github.com/json-schema-faker/json-schema-faker) under the hood. To configure it, you can pass locale and the options object to the factory function. (The full list of available options can be seen [here](https://github.com/json-schema-faker/json-schema-faker/tree/master/docs#available-options))
The middleware uses [json-schmea-faker](https://github.com/json-schema-faker/json-schema-faker) under the hood. To configure it, you can pass the options object to the factory function. (The full list of available options can be seen [here](https://github.com/json-schema-faker/json-schema-faker/tree/master/docs#available-options))

```javascript
const express = require('express');
Expand All @@ -54,13 +53,12 @@ app.use(
'/api',
createMockMiddleware({
spec: '/absolute/path/to/your/openapi/spec.yml', // string or OpenAPIV3.Document object
locale: 'ru', // json-schema-faker locale, default to 'en'
options: { // json-schema-faker options
alwaysFakeOptionals: true,
useExamplesValue: true,
// ...
},
jsfCallback: (jsf, faker) => {
configure: (jsf) => {
// function where you can extend json-schema-faker
...
}
Expand Down Expand Up @@ -105,10 +103,35 @@ paths:
}
```

### Faker generated responses
In addition faker functions can be specified for data generation. The list of all available function can be found in the [faker documentation](https://github.com/marak/Faker.js/#api-methods).
### Faker or Chance generated responses
In addition `faker.js` or `chance.js` methods can be specified for data generation. In order to use these generators you have to configure middleware through the `configure` option of the factory function.

**doc.yml**
```javascript
const express = require('express');
const { createMockMiddleware } = require('openapi-mock-express-middleware');
import faker from '@faker-js/faker';
import Chance from 'chance';

const app = express();

app.use(
'/api',
createMockMiddleware({
spec: '/absolute/path/to/your/openapi/spec.yml',
configure: (jsf) => {
jsf.extend('faker', () => faker);
jsf.extend('chance', () => new Chance());
}
}),
);

app.listen(80, () => console.log('Server listening on port 80'));

```

After that you can use 'x-faker' and/or 'x-chance' attributes in your openapi specs.

**spec.yml**
```
...
paths:
Expand All @@ -130,14 +153,20 @@ paths:
name:
type: string
x-faker: name.findName
email:
type: string
x-chance:
email:
domain: fake.com
...
```

**GET /user response**
```javascript
{
id: '8c4a4ed2-efba-4913-9604-19a27f36f322',
name: 'Mr. Braxton Dickens'.
name: 'Mr. Braxton Dickens',
email: '[email protected]'
}
```

Expand Down Expand Up @@ -224,6 +253,34 @@ paths:
}
```

If you want to use some other logic for generating responses from the `examples` attributes you can easily implement it by overwriting this behavior in the `configure` option of the middleware's factory function:

```javascript
const express = require('express');
const { createMockMiddleware } = require('openapi-mock-express-middleware');

const app = express();

app.use(
'/api',
createMockMiddleware({
spec: '/absolute/path/to/your/openapi/spec.yml',
configure: (jsf) => {
jsf.define('examples', (value) => {
if (typeof value === 'object' && value !== null && Object.keys(value).length) {
return value[Object.keys(value)[0]].value;
}

return '';
});
}
}),
);

app.listen(80, () => console.log('Server listening on port 80'));

```

## Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.
Expand All @@ -237,5 +294,3 @@ Please take a moment to read our contributing guidelines if you haven't yet done

[npm]: https://img.shields.io/npm/v/openapi-mock-express-middleware.svg
[npm-url]: https://npmjs.com/package/openapi-mock-express-middleware
[deps]: https://david-dm.org/aleksandryackovlev/openapi-mock-express-middleware.svg
[deps-url]: https://david-dm.org/aleksandryackovlev/openapi-mock-express-middleware
54 changes: 24 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "openapi-mock-express-middleware",
"version": "3.0.2",
"description": "Generates an express mock server from an Open API spec",
"version": "4.0.1",
"description": "Generates express mock-servers from OpenAPI specs",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
Expand Down Expand Up @@ -31,13 +31,9 @@
"openapi",
"swagger",
"typescript",
"fetch",
"client",
"sdk",
"mock",
"server",
"express",
"webpack"
"express"
],
"author": "Aleksandr Yackovlev <[email protected]>",
"license": "MIT",
Expand All @@ -52,46 +48,44 @@
],
"dependencies": {
"@apidevtools/swagger-parser": "^10.0.3",
"ajv": "^8.6.3",
"chokidar": "^3.5.2",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"faker": "^5.5.3",
"json-schema-faker": "0.5.0-rcv.40",
"ajv": "^8.9.0",
"chokidar": "^3.5.3",
"cookie-parser": "^1.4.6",
"express": "^4.17.2",
"json-schema-faker": "0.5.0-rcv.41",
"lodash": "^4.17.20",
"method-override": "^3.0.0",
"openapi-types": "^9.3.0",
"openapi-types": "^10.0.0",
"path-to-regexp": "^6.2.0"
},
"devDependencies": {
"@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.13",
"@types/faker": "^5.5.9",
"@types/jest": "^27.0.2",
"@types/lodash": "^4.14.176",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.178",
"@types/method-override": "0.0.32",
"@types/node": "^16.11.4",
"@types/node": "^17.0.13",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.1.0",
"@typescript-eslint/parser": "^5.1.0",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"commitizen": "^4.2.4",
"concurrently": "^6.3.0",
"concurrently": "^7.0.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.1.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint": "^8.8.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.4",
"jest": "^27.3.1",
"jest": "^27.4.7",
"json-schema-faker-types": "^0.1.6",
"nodemon": "^2.0.14",
"prettier": "^2.4.1",
"nodemon": "^2.0.15",
"prettier": "^2.5.1",
"standard-version": "^9.3.2",
"supertest": "^6.1.6",
"ts-jest": "^27.0.7",
"supertest": "^6.2.2",
"ts-jest": "^27.1.3",
"ts-node": "^10.4.0",
"typescript": "^4.4.4"
"typescript": "^4.5.5"
},
"husky": {
"hooks": {
Expand Down
33 changes: 6 additions & 27 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import fs from 'fs';

import express from 'express';
Expand All @@ -16,36 +15,24 @@ import {
import { JSFOptions, JSFCallback } from './utils';

export interface MiddlewareOptions {
file?: string;
spec?: string | OpenAPIV3.Document;
locale?: string;
options?: Partial<JSFOptions>;
jsfCallback?: JSFCallback;
configure?: JSFCallback;
}

export const createMockMiddleware = ({
/**
* @deprecated
*/
file,
spec,
locale = 'en',
options = {},
jsfCallback,
configure,
}: MiddlewareOptions): express.Router => {
if (file) {
console.warn('The file option is deprecated. Please, use spec option instead.');
}

const docSpec = !spec ? file : spec;
if (typeof docSpec === 'string' && !fs.existsSync(docSpec)) {
throw new Error(`OpenAPI spec not found at location: ${docSpec}`);
} else if (docSpec === undefined) {
if (typeof spec === 'string' && !fs.existsSync(spec)) {
throw new Error(`OpenAPI spec not found at location: ${spec}`);
} else if (spec === undefined) {
throw new Error(`OpenAPI spec not provided`);
}

const router = createRouter();
const operations = createOperations({ spec: docSpec, locale, options, callback: jsfCallback });
const operations = createOperations({ spec, options, callback: configure });

router.use('/{0,}', async (req, res, next) => {
res.locals.operation = await operations.match(req);
Expand All @@ -58,13 +45,5 @@ export const createMockMiddleware = ({
return res.locals.operation ? res.locals.operation.generateResponse(req, res) : next();
});

router.use((req, res) => {
res.status(404).send({ message: 'Not found' });
});

router.use((err: Error, req: express.Request, res: express.Response): void => {
res.status(500).send({ message: 'Something broke!' });
});

return router;
};
Loading

0 comments on commit 336d528

Please sign in to comment.