Skip to content

Commit 1fc5c7b

Browse files
committed
feat: Initial version.
0 parents  commit 1fc5c7b

File tree

22 files changed

+1675
-0
lines changed

22 files changed

+1675
-0
lines changed

.eslintrc.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"parser": "@typescript-eslint/parser",
3+
"parserOptions": {
4+
"project": "tsconfig.test.json"
5+
},
6+
"extends": ["@cowtech/eslint-config/typescript"]
7+
}

.github/workflows/ci.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
name: CI
3+
on: [push, pull_request]
4+
jobs:
5+
build:
6+
runs-on: ubuntu-latest
7+
steps:
8+
- name: Checkout
9+
uses: actions/checkout@v1
10+
- name: Use Node.js LTS
11+
uses: actions/setup-node@v1
12+
with:
13+
node-version: 14.x
14+
- name: Restore cached dependencies
15+
uses: actions/cache@v1
16+
with:
17+
path: node_modules
18+
key: node-modules-${{ hashFiles('package.json') }}
19+
- name: Install dependencies
20+
run: npm install
21+
- name: Run Tests
22+
run: npm run ci
23+
- name: Upload coverage to Codecov
24+
uses: codecov/codecov-action@v1
25+
with:
26+
file: ./coverage/coverage-final.json
27+
token: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package-lock.json
2+
yarn.lock
3+
4+
.nyc_output
5+
coverage/
6+
node_modules/
7+
tmp/
8+
9+
npm-debug.log
10+
npm-error.log
11+
yarn-debug.log
12+
yarn-error.log

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### 2021-01-01 / 0.1.0
2+
3+
- Initial version.

LICENSE.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ISC License
2+
3+
Copyright (c) 2021, and above Shogun <[email protected]>
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

README.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# fastify-openapi-docs
2+
3+
[![Package Version](https://img.shields.io/npm/v/fastify-openapi-docs.svg)](https://npm.im/fastify-openapi-docs)
4+
[![Dependency Status](https://img.shields.io/david/ShogunPanda/fastify-openapi-docs)](https://david-dm.org/ShogunPanda/fastify-openapi-docs)
5+
[![Build](https://github.com/ShogunPanda/fastify-openapi-docs/workflows/CI/badge.svg)](https://github.com/ShogunPanda/fastify-openapi-docs/actions?query=workflow%3ACI)
6+
[![Code Coverage](https://img.shields.io/codecov/c/gh/ShogunPanda/fastify-openapi-docs?token=d0ae1643f35c4c4f9714a357f796d05d)](https://codecov.io/gh/ShogunPanda/fastify-openapi-docs)
7+
8+
A simple plugin for Fastify that generates OpenAPI spec automatically.
9+
10+
http://sw.cowtech.it/fastify-openapi-docs
11+
12+
## Installation
13+
14+
Just run:
15+
16+
```bash
17+
npm install fastify-openapi-docs --save
18+
```
19+
20+
## Usage
21+
22+
Register as a plugin as early as possible (in order to track all routes), optional providing any of the following options:
23+
24+
- `openapi`: The OpenAPI document header.
25+
- `prefix`: Where to serve the OpenAPI files. The default value is `/docs/`.
26+
- `skipUI`: If set `true`, the the OpenAPI / Swagger UI will not be served.
27+
28+
Routes should contain a `openapi` object inside the `config` with all desired OpenAPI annotations.
29+
30+
Non JSON responses can be generated by setting the `$raw` key in the response schema to the appropriate MIME type.
31+
32+
Empty responses can be generated by setting the `$empty` key in the response schema to `true`.
33+
34+
Routes can be omitted from spec by the list by setting `hide` option to `true` inside their `config`.
35+
36+
Once the server is started, it will serve the OpenAPI specification on both `/{prefix}/openapi.json` and `/{prefix}/openapi.yaml`.
37+
38+
If the UI is enabled, it will be reachable at `/${prefix}`.
39+
40+
## Example
41+
42+
```js
43+
const server = require('fastify')()
44+
45+
server.register(require('fastify-openapi-docs'), {
46+
openapi: {
47+
// All these fields are optional, but they should be provided to satisfy OpenAPI specification.
48+
openapi: '3.0.3',
49+
info: {
50+
title: 'Title',
51+
description: 'Description',
52+
contact: {
53+
name: 'Shogun',
54+
url: 'https://cowtech.it',
55+
56+
},
57+
license: {
58+
name: 'ISC',
59+
url: `https://choosealicense.com/licenses/isc/`
60+
},
61+
version: '1.0.0'
62+
},
63+
servers: [
64+
{ url: 'https://example.com', description: 'Production Server' },
65+
{ url: 'https://dev.example.com', description: 'Development Server' }
66+
],
67+
tags: [{ name: 'service', description: 'Service' }],
68+
components: {
69+
securitySchemes: {
70+
jwtBearer: {
71+
type: 'http',
72+
scheme: 'bearer',
73+
bearerFormat: 'JWT'
74+
}
75+
}
76+
}
77+
}
78+
})
79+
80+
server.addSchema({
81+
type: 'object',
82+
$id: '#request',
83+
description: 'The request payload',
84+
properties: {
85+
id: {
86+
type: 'string',
87+
description: 'The operation id',
88+
pattern: '^.+$',
89+
example: true
90+
}
91+
},
92+
required: ['id'],
93+
additionalProperties: false
94+
})
95+
96+
server.addSchema({
97+
type: 'object',
98+
$id: '#response',
99+
description: 'The response payload',
100+
properties: {
101+
ok: {
102+
type: 'boolean',
103+
description: 'The operation response',
104+
example: true
105+
}
106+
},
107+
required: ['ok'],
108+
additionalProperties: false
109+
})
110+
111+
server.route({
112+
method: 'POST',
113+
url: '/path',
114+
schema: {
115+
body: { $ref: '#request' },
116+
response: {
117+
200: { $ref: '#response' }
118+
}
119+
},
120+
config: {
121+
openapi: {
122+
description: 'Makes a request',
123+
summary: 'Main route',
124+
tags: ['service'],
125+
security: [{ jwtBearer: [] }]
126+
}
127+
},
128+
handler(_, reply) {
129+
reply.send({ ok: true })
130+
}
131+
})
132+
133+
server.listen(3000)
134+
```
135+
136+
Once started, the following routes will be available:
137+
138+
- `http://localhost:3000/docs/openapi.yaml`
139+
- `http://localhost:3000/docs/openapi.json`
140+
- `http://localhost:3000/docs` (OpenAPI UI)
141+
142+
Note that `$ref` in the schemas will be resolved and replaced accordingly to OpenAPI spec.
143+
144+
## Contributing to fastify-openapi-docs
145+
146+
- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
147+
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
148+
- Fork the project.
149+
- Start a feature/bugfix branch.
150+
- Commit and push until you are happy with your contribution.
151+
- Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
152+
153+
## Copyright
154+
155+
Copyright (C) 2021 and above Shogun ([email protected]).
156+
157+
Licensed under the ISC license, which can be found at https://choosealicense.com/licenses/isc.

lib/index.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
exports.plugin = void 0;
7+
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8+
const js_yaml_1 = require("js-yaml");
9+
const spec_1 = require("./spec");
10+
const ui_1 = require("./ui");
11+
exports.plugin = fastify_plugin_1.default(function (instance, options, done) {
12+
var _a, _b;
13+
let prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : '/docs';
14+
let spec = (_b = options.openapi) !== null && _b !== void 0 ? _b : {};
15+
const routes = [];
16+
if (prefix.indexOf('/') !== 0) {
17+
prefix = `/${prefix}`;
18+
}
19+
if (!options.skipUI) {
20+
ui_1.addUI(instance, prefix);
21+
}
22+
// Register spec routes
23+
instance.route({
24+
method: 'GET',
25+
url: `${prefix}/openapi.yaml`,
26+
handler(_, reply) {
27+
reply.type('text/yaml');
28+
reply.send(js_yaml_1.dump(spec));
29+
},
30+
config: { hide: false }
31+
});
32+
instance.route({
33+
method: 'GET',
34+
url: `${prefix}/openapi.json`,
35+
handler(_, reply) {
36+
reply.send(spec);
37+
},
38+
config: { hide: false }
39+
});
40+
// Utility to track all the RouteOptions we add
41+
instance.addHook('onRoute', (route) => {
42+
routes.push(route);
43+
});
44+
// When the server starts, add all schemas and routes to the spec
45+
instance.addHook('onReady', (done) => {
46+
spec = spec_1.buildSpec(instance, spec, instance.getSchemas(), routes);
47+
done();
48+
});
49+
done();
50+
}, { name: 'fastify-openapi-docs' });
51+
exports.default = exports.plugin;
52+
module.exports = exports.plugin;
53+
Object.assign(module.exports, exports);

0 commit comments

Comments
 (0)