
Security News
rv Is a New Rust-Powered Ruby Version Manager Inspired by Python's uv
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
gulp-swagger-codegen
Advanced tools
Flexible code generation for Swagger projects, targets ES6+.
This gulp module generates code from Swagger API definitions and is intended to be used to simplify implementation of API servers/clients by providing generated code for the request/response objects, and also some templates to simplify use of the swagger-tools package.
This package uses ES6, and thus is only available for Node.js 4.x+ or suitable Io.js versions. If in doubt, please review our .travis.yml file to determine if we are currently testing for your particular version of Node.
To install this plugin:
npm install --save-dev gulp-swagger-codegen
If the plugin fails, a console error message should indicate the nature of the problem. Typically most errors are templating syntax related. If you are having trouble and not sure where to look, you can validate the logical behaviour of the plugin by setting:
(On windows)
SET DEBUG=gulp-swagger-codegen
(On OS/X and Linux)
export DEBUG=gulp-swagger-codegen
This will cause the debug output to be produced for the plugin when it runs, giving you an insight into why it's doing certain things or not producing any output.
The following code snippet shows the module being used in a standard Gulp workflow, where we assume that the various templates below exist in your project(s):
gulp.task('default', () => {
return gulp.src(['./path/to/your/swagger.yaml'])
.pipe(task({
helpers: {
/* Assign handlebars helpers with this syntax.
someName: yourHelperFunction
someName will become the #someName helper in the files.
*/
}
perDefinition: {
'./templates/es6/definition.hbs': {
target: './definitions',
extension: '.js',
},
},
perPath: {
'./templates/es6/swagger-tools-controller.hbs': {
target: './controllers',
groupBy: 'x-swagger-router-controller',
extension: '.js',
operations: ['get', 'put', 'post', 'delete'],
},
}
}))
.pipe(gulp.dest('./server/api/'))
});
You can dramatically simplify this by using a template-helper module, such
as swagger-template-es6-server
:
const templateSet = require('swagger-template-es6-server');
const codegen = require('gulp-swagger-codegen');
gulp.task('generate-code', () =>
gulp.src(['./examples/waffle-maker/service-contract.yaml'])
.pipe(codegen(templateSet({
implementationPath: '../implementation',
})))
.pipe(gulp.dest('./examples/waffle-maker')));
For more information on this template set, see the official NPM package site.
Within the NPM package for this module, several templates are included to help serve as examples and potentially jump-start your development:
{package-root}/templates/es6/definition.hbs
{package-root}/templates/es6/swagger-tools-controller.hbs
Other templates may be included from time to time.
This defines templates that are executed per request/response definition in your Swaggerfile. The keys of this object represent the path to a handlebars template.
The supported schema of perDefinition is:
{
'template-file-path': {
target: 'relative-output-root',
_extension: '.ext',
/* Any user-set options for templates */
}
}
perDefinition: {
'./templates/es6/definition.hbs': {
target: './definitions',
extension: '.js',
},
},
This will, for each definition object in a Swaggerfile:
Definition file names are by default lowercase. You can execute as many different templates or types of template per definition as you require, the only constraint is that you cannot use the same template multiple times per definition.
This defines templates that are executed per groups of operations, aggregated by some
attribute of the path (or operation within the path). An operation is a method such
as get
, put
, delete
, post
defined within a path. An example attribute to group
on would by x-swagger-router-controller
from the swagger-tools
swaggerRouter middleware, which lets you map operationId's to controllers.
The supported schema of perPath is:
{
'template-file-path.ext': {
target: 'output-folder',
groupBy: 'some-group-attribute',
operations: ['some-http-verb', 'other-http-verb'],
extension: '.ext',
/* Any user-set options for templates */
},
}
Consider the following example:
perPath: {
'./templates/es6/swagger-tools-controller.hbs': {
target: './controllers',
groupBy: 'x-swagger-router-controller',
operations: ['get', 'put', 'post', 'delete'],
extension: '.js',
},
}
This example will:
Multiple template sets, grouping by different attributes of paths or operations are possible.
The structure of data that is passed to the templates is described in the following section(s):
When being passed to templates, the following object-schema extensions are applied:
definitionName
- The swaggerfile 'name' of this definition
(i.e. Pet, Purchase etc)referencePath
- The $ref equivelent path of the definition
(i.e. #/definitions/Pet)Each handlebars template in perDefinition is run with the following initial context:
{
model, (overall parsed YAML/JSON swaggerfile)
definition, (the current definition being generated)
definitionMap, (name to definition map of all definitions)
options (Options for this template path, allows passing of extra fields)
}
Each handlebars template in perPath is run with the following initial context:
{
fileName, (filename of template, i.e. PetsController becomes petscontroller)
groupKey, (value of the groupBy attribute)
members, (Operations grouped into this group)
definitions, (Definition map for all definitions)
model, (overall parsed YAML/JSON swaggerfile)
options, (Options for this template path, allows passing of extra fields)
}
The swagger-tools-controller.hbs
template is intended to provide a simplification of
code when using swagger-tools to generate most of your microservice. Each operationId must
be extended with:
x-swagger-router-controller
- Defines which 'controller.js' class contains the operation.
This can be applied either at the path level or per-operation, overriding the path.operationId
- Defines a method name on the controller we generate, with a (req, res) input set.Here's an example config section:
perPath: {
'./templates/es6/swagger-tools-controller.hbs': {
groupBy: 'x-swagger-router-controller',
target: './controllers',
extension: '.js',
operations: ['get', 'put', 'post', 'delete'],
implementationPath: '../implementation',
// Extension properties you can use inside templates
// for example, the bellow is only for the swagger-tools example
defsRelativeToController: '../definitions' // relative path of /definitions vs controller output for requires.
},
},
The configuration for the template must pass an additional implementationPath
: this is used
because we generate a call to `require('implementationPath/controller-name.js'). However this
module must have an export per operationId.
The templated controller will parse out each input in swaggerfile declaration order and then
call a method on your implementation
type, suich as:
// Create responder: This will set the content type, status code and also
// terminate the request. Note that you must set x-gulp-swagger-codegen-outcome
// on operations in order to have a mapping here. Enforce typing of the
// responses with swaggerValidator from swagger-tools.
const responder = {
req,
res,
// Handle status 200 [success]
success: function endSuccess(result) {
res.json(result || {}, 200);
},
// Handle status 400 [invalidId]
invalidId: function endInvalidId(result) {
res.json(result || {}, 400);
},
// Handle status 404 [notFound]
notFound: function endNotFound(result) {
res.json(result || {}, 404);
},
}
// Validate implementation presence
const impl = resolveImplementation(usersImplementation);
if (!impl) {
throw new Error('Cannot resolve implementation of users');
} else if (!impl.getUserByName) {
throw new Error('Implementation is missing operation getUserByName for users');
} else if (!(typeof impl.getUserByName === 'function')) {
throw new Error('Implementation is not a function: getUserByName for users');
}
// Execute
impl.getUserByName(
username,
responder
);
Note that in this example, we are calling getUserByName on the implementation type and passing both the parameters (username) and a responder object. The responder object is a function-map for terminating the request, so that when your implementation is done, you can call the correct result-name and the generated code will set the result code and end the request.
You can annotate the names of the responder
actions with the annotation x-gulp-swagger-codegen-outcome
such as:
responses:
"404":
x-gulp-swagger-codegen-outcome: notFound
description: User not found
"200":
x-gulp-swagger-codegen-outcome: success
description: successful operation
schema:
$ref: "#/definitions/User"
"400":
x-gulp-swagger-codegen-outcome: invalidId
description: Invalid username supplied
Any operations without an annotation will not be processed by the template. You can
manually use the res
property from the responder for this scenario if you wish.
This code is MIT licensed and free for re-use in your projects and for forking. Whilst I'll do my best to maintain it for the forseeable future, you're more than welcome to submit feature requests or pull requests.
FAQs
Flexible code generation for Swagger projects, targets ES6+.
We found that gulp-swagger-codegen demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.
Security News
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.