Generate express api documentation automagically.
yarn add -D ClearC2/c2-api-docs
Create a new routes
directory.
server/
routes/
server.js
In your express api bootstrap file:
import express from 'express'
import bodyParser from 'body-parser'
import path from 'path'
import cors from 'cors'
import documentAPI from 'c2-api-docs'
const app = express()
app.use(cors())
app.use(bodyParser.json())
// routes added here
documentAPI(app, {
title: 'IOP API Docs',
description: String(fs.readFileSync(path.resolve(__dirname, '..', 'readme.md'))),
routes: path.resolve(__dirname, 'routes'),
src: path.resolve(__dirname, '..', 'src'),
server: [
path.resolve(__dirname),
path.resolve(__dirname, '..', 'src', 'redux', 'server')
],
hidePath: path.resolve(__dirname, '..')
})
const PORT = process.env.PORT || 5033
app.listen(PORT, () => {
console.log('Dev Express server running at localhost:' + PORT)
})
After starting your mock server, you will have an api explorer at http://localhost:<port>/_docs
.
The second argument to the documentAPI
function is a configuration object. All are optional.
Turns into the header of the api explorer.
General api description/documentation. Supports markdown.
The directory to the route files. See route file documentation below.
The source code path. Can be a single path or array of paths.
The mock server path. Can be a single path or array of paths.
Removes the path from the file names in the api explorer.
This package gives you a new way to define mock endpoints through route files. Route files can be nested in the routes
directory. Example:
server/
routes/
auth-info.js
companies/
get-companies.js
save-company.js
server.js
The files will automatically get incorporated into the mock server as functional endpoints.
Route files can either be a .js
file that exports an object or a .json
file. See this example route file.
// server/routes/companies/employees.js
export default {
path: '/companies/:companyUnid/employees',
methods: ['GET'],
title: 'Company employees',
description: 'Fetches all active employees',
response: {
employees: [
{
name: 'John Doe'
},
{
name: 'Bob Smith'
}
]
}
}
The equivalent json file of the above would look like below and behave identically.
{
"path": "/companies/:companyUnid/employees",
"methods": ["GET"],
"title": "Company employees",
"description": "Fetches all active employees",
"response": {
"employees": [
{
"name": "John Doe"
},
{
"name": "Bob Smith"
}
]
}
}
This must be a valid express route path.
A single http verb that this endpoint responds to. Ex. POST
Routes can respond to multiple http methods. This must be an array of http verbs that this endpoint responds to.
Ex. ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
Only used for documentation in the api explorer ui.
Only used for documentation in the api explorer ui. Supports markdown.
URL params are the tokens prefixed by :
in the path. These params can be further defined:
export default {
path: '/companies/:companyUnid/employees',
params: {
companyUnid: 'abcdef'
}
// ...
}
The above will prepopulate this param's input in the api explorer. You can provide additional help text by using an object.
export default {
path: '/companies/:companyUnid/employees',
params: {
companyUnid: {
value: 'abcdef',
help: 'Company Unid'
}
}
// ...
}
The help
text will show up directly beneath the param's input in the api explorer.
Query params can be defined in the same way.
export default {
path: '/companies/:companyUnid/employees',
query: {
hiredAfter: {
value: '01-01-2018',
help: 'Format MM-DD-YYYY'
}
}
// ...
}
POST
, PUT
, and PATCH
methods allow for example payloads. These payloads will populate the payload input in the api explorer.
export default {
path: '/contact',
methods: ['POST'],
payload: {
contact: {
firstName: 'John',
lastName: 'Doe'
}
}
// ...
}
In the case of endpoints accepting both POST
and PUT
requests, you can define unique payloads for both.
export default {
path: '/contact',
methods: ['POST', 'PUT'],
payload: {
POST: {
contact: {
firstName: 'John',
lastName: 'Doe'
}
},
PUT: {
contact: {
id: 'abcded',
firstName: 'John',
lastName: 'Doe'
}
}
}
// ...
}
Responses can be simple javascript objects...
export default {
path: '/people',
methods: ['GET'],
response: {
people: {
[
{name: 'John Doe'},
{name: 'Bob Smith'}
]
}
}
}
Or come from fixture files...
export default {
path: '/people',
methods: ['GET'],
response: require('../fixtures/peope.json')
}
Or dynamically generated based on the request...
export default {
path: '/people',
methods: ['GET', 'POST', 'PUT'],
response: (req, res) => {
if (req.method === 'POST') {
return res.status(400).json({
errors: [
{detail: 'Something went wrong :('}
]
})
}
if (req.method === 'PUT') {
return res.status(500).json({
errors: [
{detail: 'CRITICAL FAILURE'}
]
})
}
return res.status(200).json(require('../fixtures/people.json'))
}
}
Fixture files can be nested in the routes
directory but their file names must be prefixed with an underscore
to not be interpreted as a route file. Example:
server/
routes/
people/
get-people/
_people.json # will not be interpreted as a route file
route.js # will be interpreted as a route file
save-person.js # will be interpreted as a route file
update-person.json # will be interpreted as a route file
Searching in the frontend is case-insensitive. You can omit path variables and simply provide a colon. Ex.
/companies/:/employees/:/address
The above would match:
/companies/:companyUnid/employees/:unid/address
10 lines are shown by default in the code excerpts. This can be increased by providing a lines
query parameter
to the url. Ex.
http://localhost:8083/request/Z2V0LS9jb21wYW5pZXM=?lines=30
Hovering over file names will show the last modified date according to git.