Skip to content

Commit 073fc0a

Browse files
authored
Merge pull request #869 from swagger-api/issue-863
added vendor extensions
2 parents 9407ae6 + 25aaa4a commit 073fc0a

File tree

10 files changed

+481
-185
lines changed

10 files changed

+481
-185
lines changed

browser/swagger-client.js

Lines changed: 181 additions & 91 deletions
Large diffs are not rendered by default.

browser/swagger-client.min.js

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/auth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ var _ = {
1111
};
1212

1313
/**
14-
* SwaggerAuthorizations applys the correct authorization to an operation being executed
14+
* SwaggerAuthorizations applies the correct authorization to an operation being executed
1515
*/
1616
var SwaggerAuthorizations = module.exports.SwaggerAuthorizations = function (authz) {
1717
this.authz = authz || {};

lib/client.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ SwaggerClient.prototype.buildFromSpec = function (response) {
289289
this.info = response.info || {};
290290
this.produces = response.produces;
291291
this.schemes = response.schemes || [];
292-
this.securityDefinitions = response.securityDefinitions;
292+
this.securityDefinitions = _.cloneDeep(response.securityDefinitions);
293293
this.security = response.security;
294294
this.title = response.title || '';
295295

@@ -298,7 +298,26 @@ SwaggerClient.prototype.buildFromSpec = function (response) {
298298
}
299299

300300
// legacy support
301-
this.authSchemes = response.securityDefinitions;
301+
this.authSchemes = this.securityDefinitions;
302+
303+
if(this.securityDefinitions) {
304+
for(var key in this.securityDefinitions) {
305+
var securityDefinition = this.securityDefinitions[key];
306+
securityDefinition.vendorExtensions = {};
307+
for(var ext in securityDefinition) {
308+
helpers.extractExtensions(ext, securityDefinition);
309+
if (ext === 'scopes') {
310+
var scopes = securityDefinition[ext];
311+
if(typeof scopes === 'object') {
312+
scopes.vendorExtensions = {};
313+
for (var s in scopes) {
314+
helpers.extractExtensions(s, scopes);
315+
}
316+
}
317+
}
318+
}
319+
}
320+
}
302321

303322
var definedTags = {};
304323
var k;
@@ -307,8 +326,16 @@ SwaggerClient.prototype.buildFromSpec = function (response) {
307326
definedTags = {};
308327

309328
for (k = 0; k < response.tags.length; k++) {
310-
var t = response.tags[k];
329+
var t = _.cloneDeep(response.tags[k]);
311330
definedTags[t.name] = t;
331+
for(var i in t) {
332+
if(i === 'externalDocs' && typeof t[i] === 'object') {
333+
for(var j in t[i]) {
334+
helpers.extractExtensions(j, t[i]);
335+
}
336+
}
337+
helpers.extractExtensions(i, t);
338+
}
312339
}
313340
}
314341

@@ -421,6 +448,19 @@ SwaggerClient.prototype.buildFromSpec = function (response) {
421448
self.models,
422449
self.clientAuthorizations);
423450

451+
operationObject.vendorExtensions = {};
452+
for(var i in operation) {
453+
helpers.extractExtensions(i, operationObject, operation[i]);
454+
}
455+
operationObject.externalDocs = operation.externalDocs;
456+
if(operationObject.externalDocs) {
457+
operationObject.externalDocs = _.cloneDeep(operationObject.externalDocs);
458+
operationObject.externalDocs.vendorExtensions = {};
459+
for(var i in operationObject.externalDocs) {
460+
helpers.extractExtensions(i, operationObject.externalDocs);
461+
}
462+
}
463+
424464
// bind self operation's execute command to the api
425465
_.forEach(tags, function (tag) {
426466
var clientProperty = _.indexOf(reservedClientTags, tag) > -1 ? '_' + tag : tag;
@@ -458,6 +498,7 @@ SwaggerClient.prototype.buildFromSpec = function (response) {
458498
if (!_.isUndefined(tagDef)) {
459499
operationGroup.description = tagDef.description;
460500
operationGroup.externalDocs = tagDef.externalDocs;
501+
operationGroup.vendorExtensions = tagDef.vendorExtensions;
461502
}
462503

463504
self[clientProperty].help = _.bind(self.help, operationGroup);
@@ -662,7 +703,6 @@ SwaggerClient.prototype.setSchemes = function (schemes) {
662703
}
663704
};
664705

665-
666706
SwaggerClient.prototype.fail = function (message) {
667707
if (this.usePromise) {
668708
this.deferredClient.reject(message);

lib/helpers.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,24 @@ var simpleRef = module.exports.simpleRef = function (name) {
4646
}
4747
};
4848

49+
/**
50+
* helper to remove extensions and add them to an object
51+
*
52+
* @param keyname
53+
* @param obj
54+
*/
55+
module.exports.extractExtensions = function (keyname, obj, value) {
56+
if(!keyname || !obj) {
57+
return;
58+
}
59+
60+
if (typeof keyname === 'string' && keyname.indexOf('x-') === 0) {
61+
obj.vendorExtensions = obj.vendorExtensions || {};
62+
if(value) {
63+
obj.vendorExtensions[keyname] = value;
64+
}
65+
else {
66+
obj.vendorExtensions[keyname] = obj[keyname];
67+
}
68+
}
69+
}

lib/resolver.js

Lines changed: 81 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -123,106 +123,110 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
123123
var method, operation, responseCode;
124124
path = spec.paths[name];
125125

126-
for (method in path) {
127-
// operation reference
128-
if(method === '$ref') {
129-
// location = path[method];
130-
location = '/paths' + name;
131-
this.resolveInline(root, spec, path, resolutionTable, unresolvedRefs, location);
132-
}
133-
else {
134-
operation = path[method];
135-
var sharedParameters = path.parameters || [];
136-
var parameters = operation.parameters || [];
137-
138-
for (i in sharedParameters) {
139-
var parameter = sharedParameters[i];
140-
parameters.unshift(parameter);
141-
}
142-
if(method !== 'parameters' && _.isObject(operation)) {
143-
operation.parameters = operation.parameters || parameters;
126+
if(typeof path === 'object') {
127+
for (method in path) {
128+
// operation reference
129+
if (method === '$ref') {
130+
// location = path[method];
131+
location = '/paths' + name;
132+
this.resolveInline(root, spec, path, resolutionTable, unresolvedRefs, location);
144133
}
134+
else {
135+
operation = path[method];
136+
var sharedParameters = path.parameters || [];
137+
var parameters = operation.parameters || [];
145138

146-
for (i in parameters) {
147-
var parameter = parameters[i];
148-
location = '/paths' + name + '/' + method + '/parameters';
149-
150-
if (parameter.in === 'body' && parameter.schema) {
151-
if(_.isArray(parameter.schema.allOf)) {
152-
// move to a definition
153-
var modelName = 'inline_model';
154-
var name = modelName;
155-
var done = false; var counter = 0;
156-
while(!done) {
157-
if(typeof spec.definitions[name] === 'undefined') {
158-
done = true;
159-
break;
160-
}
161-
name = modelName + '_' + counter;
162-
counter ++;
163-
}
164-
spec.definitions[name] = { allOf: parameter.schema.allOf };
165-
delete parameter.schema.allOf;
166-
parameter.schema.$ref = '#/definitions/' + name;
167-
this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec);
168-
}
169-
else {
170-
this.resolveTo(root, parameter.schema, resolutionTable, location);
171-
}
139+
for (i in sharedParameters) {
140+
var parameter = sharedParameters[i];
141+
parameters.unshift(parameter);
172142
}
173-
174-
if (parameter.$ref) {
175-
// parameter reference
176-
this.resolveInline(root, spec, parameter, resolutionTable, unresolvedRefs, parameter.$ref);
143+
if (method !== 'parameters' && _.isObject(operation)) {
144+
operation.parameters = operation.parameters || parameters;
177145
}
178-
}
179146

180-
for (responseCode in operation.responses) {
181-
var response = operation.responses[responseCode];
182-
location = '/paths' + name + '/' + method + '/responses/' + responseCode;
147+
for (i in parameters) {
148+
var parameter = parameters[i];
149+
location = '/paths' + name + '/' + method + '/parameters';
183150

184-
if(_.isObject(response)) {
185-
if(response.$ref) {
186-
// response reference
187-
this.resolveInline(root, spec, response, resolutionTable, unresolvedRefs, location);
188-
}
189-
if (response.schema) {
190-
var responseObj = response;
191-
if(_.isArray(responseObj.schema.allOf)) {
151+
if (parameter.in === 'body' && parameter.schema) {
152+
if (_.isArray(parameter.schema.allOf)) {
192153
// move to a definition
193154
var modelName = 'inline_model';
194155
var name = modelName;
195-
var done = false; var counter = 0;
196-
while(!done) {
197-
if(typeof spec.definitions[name] === 'undefined') {
156+
var done = false;
157+
var counter = 0;
158+
while (!done) {
159+
if (typeof spec.definitions[name] === 'undefined') {
198160
done = true;
199161
break;
200162
}
201163
name = modelName + '_' + counter;
202-
counter ++;
164+
counter++;
203165
}
204-
spec.definitions[name] = { allOf: responseObj.schema.allOf };
205-
delete responseObj.schema.allOf;
206-
delete responseObj.schema.type;
207-
responseObj.schema.$ref = '#/definitions/' + name;
166+
spec.definitions[name] = {allOf: parameter.schema.allOf};
167+
delete parameter.schema.allOf;
168+
parameter.schema.$ref = '#/definitions/' + name;
208169
this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec);
209170
}
210-
else if('array' === responseObj.schema.type) {
211-
if(responseObj.schema.items && responseObj.schema.items.$ref) {
212-
// response reference
213-
this.resolveInline(root, spec, responseObj.schema.items, resolutionTable, unresolvedRefs, location);
214-
}
215-
}
216171
else {
217-
this.resolveTo(root, response.schema, resolutionTable, location);
172+
this.resolveTo(root, parameter.schema, resolutionTable, location);
173+
}
174+
}
175+
176+
if (parameter.$ref) {
177+
// parameter reference
178+
this.resolveInline(root, spec, parameter, resolutionTable, unresolvedRefs, parameter.$ref);
179+
}
180+
}
181+
182+
for (responseCode in operation.responses) {
183+
var response = operation.responses[responseCode];
184+
location = '/paths' + name + '/' + method + '/responses/' + responseCode;
185+
186+
if (_.isObject(response)) {
187+
if (response.$ref) {
188+
// response reference
189+
this.resolveInline(root, spec, response, resolutionTable, unresolvedRefs, location);
190+
}
191+
if (response.schema) {
192+
var responseObj = response;
193+
if (_.isArray(responseObj.schema.allOf)) {
194+
// move to a definition
195+
var modelName = 'inline_model';
196+
var name = modelName;
197+
var done = false;
198+
var counter = 0;
199+
while (!done) {
200+
if (typeof spec.definitions[name] === 'undefined') {
201+
done = true;
202+
break;
203+
}
204+
name = modelName + '_' + counter;
205+
counter++;
206+
}
207+
spec.definitions[name] = {allOf: responseObj.schema.allOf};
208+
delete responseObj.schema.allOf;
209+
delete responseObj.schema.type;
210+
responseObj.schema.$ref = '#/definitions/' + name;
211+
this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec);
212+
}
213+
else if ('array' === responseObj.schema.type) {
214+
if (responseObj.schema.items && responseObj.schema.items.$ref) {
215+
// response reference
216+
this.resolveInline(root, spec, responseObj.schema.items, resolutionTable, unresolvedRefs, location);
217+
}
218+
}
219+
else {
220+
this.resolveTo(root, response.schema, resolutionTable, location);
221+
}
218222
}
219223
}
220224
}
221225
}
222226
}
227+
// clear them out to avoid multiple resolutions
228+
path.parameters = [];
223229
}
224-
// clear them out to avoid multiple resolutions
225-
path.parameters = [];
226230
}
227231

228232
var expectedCalls = 0, toResolve = [];

lib/spec-converter.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,9 @@ SwaggerSpecConverter.prototype.securityDefinitions = function(obj, swagger) {
557557
var name;
558558
for(name in obj.authorizations) {
559559
var isValid = false;
560-
var securityDefinition = {};
560+
var securityDefinition = {
561+
vendorExtensions: {}
562+
};
561563
var definition = obj.authorizations[name];
562564
if(definition.type === 'apiKey') {
563565
securityDefinition.type = 'apiKey';

lib/types/operation.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,6 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMeth
110110
if (param.type === 'array') {
111111
param.isList = true;
112112
param.allowMultiple = true;
113-
// the enum can be defined at the items level
114-
//if (param.items && param.items.enum) {
115-
// param['enum'] = param.items.enum;
116-
//}
117113
}
118114

119115
var innerType = this.getType(param);
@@ -124,6 +120,9 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMeth
124120
param['enum'] = [true, false]; // use actual primitives
125121
}
126122

123+
for(key in param) {
124+
helpers.extractExtensions(key, param);
125+
}
127126
if(typeof param['x-example'] !== 'undefined') {
128127
var d = param['x-example'];
129128
param.default = d;
@@ -198,6 +197,30 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMeth
198197
defaultResponseCode = 'default';
199198
}
200199

200+
for(var keyname in responses) {
201+
helpers.extractExtensions(keyname, responses);
202+
if(typeof keyname === 'string' && keyname.indexOf('x-') === -1) {
203+
var responseObject = responses[keyname];
204+
if(typeof responseObject === 'object' && typeof responseObject.headers === 'object') {
205+
var headers = responseObject.headers;
206+
for(var headerName in headers) {
207+
var header = headers[headerName];
208+
if(typeof header === 'object') {
209+
for(var headerKey in header) {
210+
helpers.extractExtensions(headerKey, header);
211+
}
212+
}
213+
}
214+
}
215+
}
216+
}
217+
218+
if (response) {
219+
for(var keyname in response) {
220+
helpers.extractExtensions(keyname, response);
221+
}
222+
}
223+
201224
if (response && response.schema) {
202225
var resolvedModel = this.resolveModel(response.schema, definitions);
203226
var successResponse;
@@ -218,6 +241,7 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMeth
218241
}
219242

220243
if (successResponse) {
244+
successResponse.vendorExtensions = response.vendorExtensions;
221245
// Attach response properties
222246
if (response.description) {
223247
successResponse.description = response.description;

0 commit comments

Comments
 (0)