-
Notifications
You must be signed in to change notification settings - Fork 228
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
Add support for jsDoc filtering #111
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,9 @@ const options = { | |
}, | ||
}, | ||
apis: ['./routes.js'], // Path to the API docs | ||
jsDocFilter: (jsDocComment) => { // Optional filtering mechanism applied on each API doc | ||
return true; | ||
} | ||
}; | ||
|
||
// Initialize swagger-jsdoc -> returns validated swagger spec in json format | ||
|
@@ -34,6 +37,10 @@ app.get('/api-docs.json', function(req, res) { | |
}); | ||
``` | ||
|
||
- `options.jsDocFilter` is a function which accepts only one variable `jsDocComment`. This `jsDocComment` represents each route documentation being iterated upon. | ||
|
||
If you want to optionally perform filters on each route documentation, return boolean `true` or `false` accordingly on certain logical conditions. This is useful for conditionally displaying certain route documentation based on different server deployments. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned in the comment above, I'd personally prefer to keep boolean and object types separate in terms of logic. For instance, |
||
|
||
You could also use a framework like [swagger-tools](https://www.npmjs.com/package/swagger-tools) to serve the spec and a `swagger-ui`. | ||
|
||
### How to document the API | ||
|
@@ -68,6 +75,74 @@ app.post('/login', function(req, res) { | |
}); | ||
``` | ||
|
||
As said earlier, API documentation filters could be put in place before having such API rendered on the JSON file. A sample is shown in [app.js](../example/v2/app.js) where some form of filtering is done. | ||
```javascript | ||
function jsDocFilter(jsDocComment) { | ||
// Do filtering logic here in order to determine whether | ||
// the JSDoc under scrunity will be displayed or not. | ||
// This function must return boolean. `true` to display, `false` to hide. | ||
const docDescription = jsDocComment.description; | ||
|
||
const features = docDescription.indexOf('feature') > -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the approach of storing checks in variables. For readability, you can name them |
||
const featureX = docDescription.indexOf('featureX') > -1; // featureX is the filter keyword | ||
const featureY = docDescription.indexOf('featureY') > -1; // featureY is also another filter keyword | ||
|
||
// `featureFilter` is some external environment variable | ||
const enabledX = | ||
featureX && envVars && envVars.featureFilter.indexOf('X') > -1; | ||
const enabledY = | ||
featureY && envVars && envVars.featureFilter.indexOf('Y') > -1; | ||
|
||
const featuresEnabled = enabledX || enabledY; | ||
|
||
const existingRoutes = []; | ||
|
||
function includeDocs() { | ||
const route = | ||
jsDocComment && | ||
jsDocComment.tags && | ||
jsDocComment.tags[0] && | ||
jsDocComment.tags[0].description && | ||
jsDocComment.tags[0].description.split(':')[0]; | ||
|
||
if (existingRoutes.indexOf(route) === -1) { | ||
// need to perform check if the route doc was previously added | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
// featured route documentation | ||
if (features) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the place where I'd change the logic to return a reduced version of the docs. |
||
if (featuresEnabled) { | ||
return includeDocs(); | ||
} | ||
} else { | ||
// original routes included here | ||
return includeDocs(); | ||
} | ||
|
||
return false; | ||
}, | ||
}; | ||
``` | ||
|
||
When a route filter needs to be applied, the filter keyword may be used. In the example below, the `featureX` (coded above `@swagger`) is a filter keyword for the route to be included in the rendering of the JSON. | ||
Note that the filter only reads keywords above the `@swagger` identifier. | ||
```javascript | ||
/** | ||
* featureX | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you tried using tags for grouping endpoints per given logical separation? https://swagger.io/docs/specification/grouping-operations-with-tags/ |
||
* @swagger | ||
* /newFeatureX: | ||
* get: | ||
* description: Part of feature X | ||
* responses: | ||
* 200: | ||
* description: hello feature X | ||
*/ | ||
``` | ||
|
||
### Re-using Model Definitions | ||
|
||
A model may be the same for multiple endpoints (Ex. User POST,PUT responses). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Mimics a Node server's set of environment variables | ||
*/ | ||
module.exports = { | ||
/* | ||
* Switch between sample values of filter 'X' or 'Y'. | ||
* to see display behavior in swagger-jsdoc filtering. | ||
* If 'X' is defined, 'featureY' documentation should | ||
* not show up in the /api-docs.json and vice-versa. | ||
*/ | ||
featureFilter: 'X', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, it feels a bit weird to return a boolean after receiving an argument. I mean, if this is meant to be a flag for a logic to be attached, I'd personally prefer something like
jsDocFilter: true
and pass the function on another property of the definition object. Or maybe simply attach the function which returns a reduced object.