Skip to content

Commit 4564197

Browse files
author
Vishal Shingala
committed
Added optional support for remote refs resolution
1 parent b64d910 commit 4564197

File tree

4 files changed

+124
-68
lines changed

4 files changed

+124
-68
lines changed

lib/options.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,24 @@ module.exports = {
107107
external: true,
108108
usage: ['CONVERSION']
109109
},
110+
{
111+
name: 'Resolve remote references',
112+
id: 'resolveRemoteRefs',
113+
type: 'boolean',
114+
default: false,
115+
description: 'Select whether to resolve remote references.',
116+
external: true,
117+
usage: ['CONVERSION']
118+
},
119+
{
120+
name: 'Source URL of definition',
121+
id: 'sourceUrl',
122+
type: 'string',
123+
default: '',
124+
description: 'Specify source URL of definition to resolve remote references mentioned in it.',
125+
external: true,
126+
usage: ['CONVERSION']
127+
},
110128
{
111129
name: 'Enable Schema Faking',
112130
id: 'schemaFaker',

lib/parse.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,34 @@ module.exports = {
183183
});
184184
},
185185

186+
/**
187+
* Resolves remote and URL $ref from OpenAPI definition based on given options
188+
*
189+
* @param {*} openapi - OpenAPI definition
190+
* @param {*} options - options
191+
* @param {*} cb - callback function
192+
* @return {*} - err if present
193+
*/
194+
resolveRemoteRefs: function (openapi, options, cb) {
195+
if (options.resolveRemoteRefs) {
196+
resolver.resolve(openapi, options.sourceUrl, {
197+
resolve: true,
198+
externals: [],
199+
externalRefs: {},
200+
openapi: openapi
201+
})
202+
.then(function() {
203+
return cb(null);
204+
})
205+
.catch(function(err) {
206+
return cb(err);
207+
});
208+
}
209+
else {
210+
return cb(null);
211+
}
212+
},
213+
186214
/** Resolves all OpenAPI file references and returns a single OAS Object
187215
*
188216
* @param {Object} source Root file path

lib/schemapack.js

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -237,90 +237,99 @@ class SchemaPack {
237237
return callback(new OpenApiErr('The schema must be validated before attempting conversion'));
238238
}
239239

240-
// this cannot be attempted before validation
241-
componentsAndPaths = {
242-
components: this.openapi.components,
243-
paths: this.openapi.paths
244-
};
240+
parse.resolveRemoteRefs(this.openapi, options, (err) => {
241+
if (err) {
242+
return callback(null, {
243+
result: false,
244+
reason: err.name + ': ' + err.message
245+
});
246+
}
245247

246-
// create and sanitize basic spec
247-
openapi = this.openapi;
248-
openapi.servers = _.isEmpty(openapi.servers) ? [{ url: '/' }] : openapi.servers;
249-
openapi.securityDefs = _.get(openapi, 'components.securitySchemes', {});
250-
openapi.baseUrl = _.get(openapi, 'servers.0.url', '{{baseURL}}');
248+
// this cannot be attempted before validation
249+
componentsAndPaths = {
250+
components: this.openapi.components,
251+
paths: this.openapi.paths
252+
};
251253

252-
// TODO: Multiple server variables need to be saved as environments
253-
openapi.baseUrlVariables = _.get(openapi, 'servers.0.variables');
254+
// create and sanitize basic spec
255+
openapi = this.openapi;
256+
openapi.servers = _.isEmpty(openapi.servers) ? [{ url: '/' }] : openapi.servers;
257+
openapi.securityDefs = _.get(openapi, 'components.securitySchemes', {});
258+
openapi.baseUrl = _.get(openapi, 'servers.0.url', '{{baseURL}}');
254259

255-
// Fix {scheme} and {path} vars in the URL to :scheme and :path
256-
openapi.baseUrl = schemaUtils.fixPathVariablesInUrl(openapi.baseUrl);
260+
// TODO: Multiple server variables need to be saved as environments
261+
openapi.baseUrlVariables = _.get(openapi, 'servers.0.variables');
257262

258-
// Creating a new instance of a Postman collection
259-
// All generated folders and requests will go inside this
260-
generatedStore.collection = new sdk.Collection({
261-
info: {
262-
name: _.get(openapi, 'info.title', COLLECTION_NAME)
263-
}
264-
});
263+
// Fix {scheme} and {path} vars in the URL to :scheme and :path
264+
openapi.baseUrl = schemaUtils.fixPathVariablesInUrl(openapi.baseUrl);
265+
266+
// Creating a new instance of a Postman collection
267+
// All generated folders and requests will go inside this
268+
generatedStore.collection = new sdk.Collection({
269+
info: {
270+
name: _.get(openapi, 'info.title', COLLECTION_NAME)
271+
}
272+
});
265273

266-
if (openapi.security) {
267-
authHelper = schemaUtils.getAuthHelper(openapi, openapi.security);
268-
if (authHelper) {
269-
generatedStore.collection.auth = authHelper;
274+
if (openapi.security) {
275+
authHelper = schemaUtils.getAuthHelper(openapi, openapi.security);
276+
if (authHelper) {
277+
generatedStore.collection.auth = authHelper;
278+
}
270279
}
271-
}
272-
// ---- Collection Variables ----
273-
// adding the collection variables for all the necessary root level variables
274-
// and adding them to the collection variables
275-
schemaUtils.convertToPmCollectionVariables(
276-
openapi.baseUrlVariables,
277-
'baseUrl',
278-
openapi.baseUrl
279-
).forEach((element) => {
280-
generatedStore.collection.variables.add(element);
281-
});
280+
// ---- Collection Variables ----
281+
// adding the collection variables for all the necessary root level variables
282+
// and adding them to the collection variables
283+
schemaUtils.convertToPmCollectionVariables(
284+
openapi.baseUrlVariables,
285+
'baseUrl',
286+
openapi.baseUrl
287+
).forEach((element) => {
288+
generatedStore.collection.variables.add(element);
289+
});
282290

283-
generatedStore.collection.describe(schemaUtils.getCollectionDescription(openapi));
291+
generatedStore.collection.describe(schemaUtils.getCollectionDescription(openapi));
284292

285-
// Only change the stack limit if the optimizeConversion option is true
286-
if (options.optimizeConversion) {
287-
// Deciding stack limit based on size of the schema, number of refs and number of paths.
288-
analysis = schemaUtils.analyzeSpec(openapi);
293+
// Only change the stack limit if the optimizeConversion option is true
294+
if (options.optimizeConversion) {
295+
// Deciding stack limit based on size of the schema, number of refs and number of paths.
296+
analysis = schemaUtils.analyzeSpec(openapi);
289297

290-
// Update options on the basis of analysis.
291-
options = schemaUtils.determineOptions(analysis, options);
292-
}
298+
// Update options on the basis of analysis.
299+
options = schemaUtils.determineOptions(analysis, options);
300+
}
293301

294302

295-
// ---- Collection Items ----
296-
// Adding the collection items from openapi spec based on folderStrategy option
297-
// For tags, All operations are grouped based on respective tags object
298-
// For paths, All operations are grouped based on corresponding paths
299-
try {
300-
if (options.folderStrategy === 'tags') {
301-
schemaUtils.addCollectionItemsUsingTags(openapi, generatedStore, componentsAndPaths, options, schemaCache);
303+
// ---- Collection Items ----
304+
// Adding the collection items from openapi spec based on folderStrategy option
305+
// For tags, All operations are grouped based on respective tags object
306+
// For paths, All operations are grouped based on corresponding paths
307+
try {
308+
if (options.folderStrategy === 'tags') {
309+
schemaUtils.addCollectionItemsUsingTags(openapi, generatedStore, componentsAndPaths, options, schemaCache);
310+
}
311+
else {
312+
schemaUtils.addCollectionItemsUsingPaths(openapi, generatedStore, componentsAndPaths, options, schemaCache);
313+
}
302314
}
303-
else {
304-
schemaUtils.addCollectionItemsUsingPaths(openapi, generatedStore, componentsAndPaths, options, schemaCache);
315+
catch (e) {
316+
return callback(e);
305317
}
306-
}
307-
catch (e) {
308-
return callback(e);
309-
}
310318

311-
collectionJSON = generatedStore.collection.toJSON();
319+
collectionJSON = generatedStore.collection.toJSON();
312320

313-
// this needs to be deleted as even if version is not specified to sdk,
314-
// it returns a version property with value set as undefined
315-
// this fails validation against v2.1 collection schema definition.
316-
delete collectionJSON.info.version;
321+
// this needs to be deleted as even if version is not specified to sdk,
322+
// it returns a version property with value set as undefined
323+
// this fails validation against v2.1 collection schema definition.
324+
delete collectionJSON.info.version;
317325

318-
return callback(null, {
319-
result: true,
320-
output: [{
321-
type: 'collection',
322-
data: collectionJSON
323-
}]
326+
return callback(null, {
327+
result: true,
328+
output: [{
329+
type: 'collection',
330+
data: collectionJSON
331+
}]
332+
});
324333
});
325334
}
326335

lib/utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module.exports = {
2222

2323
// check the type of the value of that option came from the user
2424
switch (defaultOptions[id].type) {
25+
case 'string':
2526
case 'boolean':
2627
if (typeof userOptions[id] === defaultOptions[id].type) {
2728
retVal[id] = userOptions[id];

0 commit comments

Comments
 (0)