Skip to content

Commit 31c1eb5

Browse files
committed
Swap schema validation for swagger-tools for stricter validation rules
1 parent 6a0bc7c commit 31c1eb5

File tree

4 files changed

+157
-94
lines changed

4 files changed

+157
-94
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# gulp-swagger v0.0.4
1+
# gulp-swagger v0.0.5
22
--------------------------
33

44
| | |

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
},
2424
"devDependencies": {
2525
"gulp": "^3.8.11",
26-
"gulp-swagger": "^0.0.4"
26+
"gulp-swagger": "^0.0.5"
2727
}
2828
}

index.js

Lines changed: 123 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var path = require('path');
33
var through = require('through2');
44
var gutil = require('gulp-util');
55
var parser = require('swagger-parser');
6+
var spec = require('swagger-tools').specs.v2; // Validate using the latest Swagger 2.x specification
67
var CodeGen = require('swagger-js-codegen').CodeGen;
78
var PLUGIN_NAME = 'gulp-swagger';
89

@@ -81,74 +82,135 @@ module.exports = function gulpSwagger (filename, options) {
8182
throw new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported');
8283
}
8384

84-
parser.parse(file.history[0], function parseSpec (error, swaggerSpec) {
85+
// Load and parse swagger schema main file.
86+
parser.parse(file.history[0], {
87+
dereference$Refs: false,
88+
validateSchema: false,
89+
strictValidation: false
90+
}, function parseSchema (error, swaggerObject) {
8591
if ( error ) {
8692
cb(new gutil.PluginError(PLUGIN_NAME, error));
8793
return;
8894
}
8995

90-
var fileBuffer;
91-
92-
if ( useCodeGen ) {
93-
var codeGenFunction = 'get' +
94-
codeGenSettings.type[0].toUpperCase() +
95-
codeGenSettings.type.slice(1, codeGenSettings.type.length) +
96-
'Code';
97-
98-
codeGenSettings.esnext = true;
99-
codeGenSettings.swagger = swaggerSpec;
100-
delete codeGenSettings.type;
101-
102-
codeGenSettings.mustache = codeGenSettings.mustache || {};
103-
// Allow swagger schema to be easily accessed inside templates.
104-
codeGenSettings.mustache.swagger = JSON.stringify(swaggerSpec);
105-
// Allow each individual JSON schema to be easily accessed inside templates (for validation purposes).
106-
codeGenSettings.mustache.JSONSchemas = JSON.stringify(
107-
Object.keys(swaggerSpec.paths)
108-
.reduce(function reducePaths (newPathCollection, currentPath) {
109-
var pathMethods = swaggerSpec.paths[currentPath] || {};
110-
var pathSchemas = Object.keys(pathMethods)
111-
.reduce(function reduceMethods (newMethodCollection, currentMethod) {
112-
var methodParameters = (pathMethods[currentMethod].parameters || [])
113-
.filter(function filterBodyParameter (parameter) {
114-
return parameter.in === 'body';
115-
})[0] || {};
116-
var methodResponses = pathMethods[currentMethod].responses || {};
117-
var methodSchemas = {
118-
request: methodParameters.schema,
119-
responses: Object.keys(methodResponses)
120-
.reduce(function reduceMethods (newResponsesCollection, currentResponse) {
121-
var responseSchema = methodResponses[currentResponse].schema || {};
122-
123-
newResponsesCollection[currentResponse] = responseSchema;
124-
return newResponsesCollection;
125-
}, {})
126-
};
127-
128-
newMethodCollection[currentMethod] = methodSchemas;
129-
return newMethodCollection;
130-
}, {});
131-
132-
newPathCollection[currentPath] = pathSchemas;
133-
return newPathCollection;
134-
}, {})
135-
);
136-
137-
fileBuffer = CodeGen[codeGenFunction](codeGenSettings);
138-
}
139-
else {
140-
fileBuffer = JSON.stringify(swaggerSpec);
141-
}
96+
// Validate resulting schema
97+
spec.validate(swaggerObject, function validateSchema (err, result) {
98+
if (err) {
99+
cb(new gutil.PluginError(PLUGIN_NAME, err));
100+
return;
101+
}
102+
103+
if ( typeof result !== 'undefined' ) {
104+
if ( result.errors.length > 0 ) {
105+
gutil.log(
106+
gutil.colors.red([
107+
'',
108+
'',
109+
'Swagger Schema Errors (' + result.errors.length + ')',
110+
'--------------------------',
111+
result.errors.map(function (err) {
112+
return '#/' + err.path.join('/') + ': ' + err.message +
113+
'\n' +
114+
JSON.stringify(err) +
115+
'\n';
116+
}).join('\n'),
117+
''
118+
].join('\n')),
119+
''
120+
);
121+
}
142122

143-
// Return processed file to gulp
144-
_this.push(new gutil.File({
145-
cwd: file.cwd,
146-
base: file.base,
147-
path: path.join(file.base, filename),
148-
contents: new Buffer(fileBuffer)
149-
}));
123+
if ( result.warnings.length > 0 ) {
124+
gutil.log(
125+
gutil.colors.yellow([
126+
'',
127+
'',
128+
'Swagger Schema Warnings (' + result.warnings.length + ')',
129+
'------------------------',
130+
result.warnings.map(function (warn) {
131+
return '#/' + warn.path.join('/') + ': ' + warn.message +
132+
'\n' +
133+
JSON.stringify(warn) +
134+
'\n';
135+
}).join('\n'),
136+
''
137+
].join('\n')),
138+
''
139+
);
140+
}
150141

151-
cb();
142+
if ( result.errors.length > 0 ) {
143+
cb(new gutil.PluginError(PLUGIN_NAME, 'The Swagger schema is invalid'));
144+
return;
145+
}
146+
}
147+
148+
// Swagger document is valid
149+
var fileBuffer;
150+
151+
if ( useCodeGen ) {
152+
var codeGenFunction = 'get' +
153+
codeGenSettings.type[0].toUpperCase() +
154+
codeGenSettings.type.slice(1, codeGenSettings.type.length) +
155+
'Code';
156+
157+
codeGenSettings.esnext = true;
158+
codeGenSettings.swagger = swaggerObject;
159+
delete codeGenSettings.type;
160+
161+
codeGenSettings.mustache = codeGenSettings.mustache || {};
162+
// Allow swagger schema to be easily accessed inside templates.
163+
codeGenSettings.mustache.swagger = JSON.stringify(swaggerObject);
164+
// Allow each individual JSON schema to be easily accessed inside templates (for validation purposes).
165+
codeGenSettings.mustache.JSONSchemas = JSON.stringify(
166+
Object.keys(swaggerObject.paths)
167+
.reduce(function reducePaths (newPathCollection, currentPath) {
168+
var pathMethods = swaggerObject.paths[currentPath] || {};
169+
var pathSchemas = Object.keys(pathMethods)
170+
.reduce(function reduceMethods (newMethodCollection, currentMethod) {
171+
var methodParameters = (pathMethods[currentMethod].parameters || [])
172+
.filter(function filterBodyParameter (parameter) {
173+
return parameter.in === 'body';
174+
})[0] || {};
175+
var methodResponses = pathMethods[currentMethod].responses || {};
176+
var methodSchemas = {
177+
request: methodParameters.schema,
178+
responses: Object.keys(methodResponses)
179+
.reduce(function reduceMethods (newResponsesCollection, currentResponse) {
180+
var responseSchema = methodResponses[currentResponse].schema || {};
181+
182+
newResponsesCollection[currentResponse] = responseSchema;
183+
return newResponsesCollection;
184+
}, {})
185+
};
186+
187+
newMethodCollection[currentMethod] = methodSchemas;
188+
return newMethodCollection;
189+
}, {});
190+
191+
newPathCollection[currentPath] = pathSchemas;
192+
return newPathCollection;
193+
}, {})
194+
);
195+
196+
fileBuffer = CodeGen[codeGenFunction](codeGenSettings);
197+
}
198+
else {
199+
fileBuffer = JSON.stringify(swaggerObject);
200+
}
201+
202+
// Return processed file to gulp
203+
_this.push(new gutil.File({
204+
cwd: file.cwd,
205+
base: file.base,
206+
path: path.join(file.base, filename),
207+
contents: new Buffer(fileBuffer)
208+
}));
209+
210+
cb();
211+
212+
});
152213
});
214+
153215
});
154216
};

package.json

100755100644
Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
{
2-
"name": "gulp-swagger",
3-
"version": "0.0.4",
4-
"homepage": "http://github.com/gersongoulart/gulp-swagger",
5-
"description": "Gulp plugin that parses Swagger specs in JSON or YAML format, validates against the official Swagger 2.0 schema, dereferences all $ref pointers, including pointers to external files and generates client-side API code.",
6-
"main": "./index.js",
7-
"dependencies": {
8-
"gulp-util": "*",
9-
"through2": "0.x.x",
10-
"swagger-parser": "*",
11-
"swagger-js-codegen": "*"
12-
},
13-
"repository": {
14-
"type": "git",
15-
"url": "git://github.com/gersongoulart/gulp-swagger.git"
16-
},
17-
"keywords": [
18-
"gulp",
19-
"plugin",
20-
"gulpplugin",
21-
"swagger",
22-
"codegen"
23-
],
24-
"author": "Gerson Goulart <gerson.goulart@gmail.com>",
25-
"license": "MIT",
26-
"bugs": {
27-
"url": "http://github.com/gersongoulart/gulp-swagger/issues"
28-
},
29-
"engines": {
30-
"node": ">=0.8"
31-
}
32-
}
2+
"name": "gulp-swagger",
3+
"version": "0.0.5",
4+
"homepage": "http://github.com/gersongoulart/gulp-swagger",
5+
"description": "Gulp plugin that parses Swagger specs in JSON or YAML format, validates against the official Swagger 2.0 schema, dereferences all $ref pointers, including pointers to external files and generates client-side API code.",
6+
"main": "./index.js",
7+
"dependencies": {
8+
"gulp-util": "*",
9+
"swagger-js-codegen": "*",
10+
"swagger-parser": "*",
11+
"swagger-tools": "*",
12+
"through2": "0.x.x"
13+
},
14+
"repository": {
15+
"type": "git",
16+
"url": "git://github.com/gersongoulart/gulp-swagger.git"
17+
},
18+
"keywords": [
19+
"gulp",
20+
"plugin",
21+
"gulpplugin",
22+
"swagger",
23+
"codegen"
24+
],
25+
"author": "Gerson Goulart <gerson.goulart@gmail.com>",
26+
"license": "MIT",
27+
"bugs": {
28+
"url": "http://github.com/gersongoulart/gulp-swagger/issues"
29+
},
30+
"engines": {
31+
"node": ">=0.8"
32+
}
33+
}

0 commit comments

Comments
 (0)