@@ -3,6 +3,7 @@ var path = require('path');
3
3
var through = require ( 'through2' ) ;
4
4
var gutil = require ( 'gulp-util' ) ;
5
5
var parser = require ( 'swagger-parser' ) ;
6
+ var spec = require ( 'swagger-tools' ) . specs . v2 ; // Validate using the latest Swagger 2.x specification
6
7
var CodeGen = require ( 'swagger-js-codegen' ) . CodeGen ;
7
8
var PLUGIN_NAME = 'gulp-swagger' ;
8
9
@@ -81,74 +82,135 @@ module.exports = function gulpSwagger (filename, options) {
81
82
throw new gutil . PluginError ( PLUGIN_NAME , 'Streaming not supported' ) ;
82
83
}
83
84
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 ) {
85
91
if ( error ) {
86
92
cb ( new gutil . PluginError ( PLUGIN_NAME , error ) ) ;
87
93
return ;
88
94
}
89
95
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
+ }
142
122
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
+ }
150
141
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
+ } ) ;
152
213
} ) ;
214
+
153
215
} ) ;
154
216
} ;
0 commit comments