Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 4.0.1 #39

Merged
merged 17 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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