Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
function inner(obj,key,state){
if (obj[key] && isRef(obj[key],'$ref')) {
let $ref = obj[key].$ref;
if (!$ref.startsWith('#')) { // is external
let $extra = '';
if (!refs[$ref]) {
let potential = Object.keys(refs).find(function(e,i,a){
return $ref.startsWith(e+'/');
});
if (potential) {
if (options.verbose) console.warn('Found potential subschema at',potential);
$extra = '/'+($ref.split('#')[1]||'').replace(potential.split('#')[1]||'');
$extra = $extra.split('/undefined').join(''); // FIXME
$ref = potential;
}
}
}
let resultStr = yaml.stringify(result);
if (typeof result !== 'boolean') try {
if (!options.yaml) {
try {
resultStr = yaml.stringify(result); // should be representable safely in yaml
let resultStr2 = yaml.stringify(result); // FIXME dropped 'noRefs:true' here
should(resultStr).not.be.exactly('{}','Result should not be empty');
should(resultStr).equal(resultStr2,'Result should have no object identity ref_s');
}
catch (ex) {
if (options.verbose>1) {
fs.writeFileSync('./debug.yaml',resultStr,'utf8');
console.warn('Result dumped to debug.yaml fixed.yaml');
let fix = reref(result);
fs.writeFileSync('./fixed.yaml',yaml.stringify(fix),'utf8');
}
should.fail(false,true,'Result cannot be represented safely in YAML');
}
}
validator.validate(result, options)
.then(function(options){
finalise(null,options);
})
.catch(function(ex){
finalise(ex,options);
});
}
catch (ex) {
console.warn(common.colour.normal + options.file);
let context = clone(options.cache[target]);
let data = options.externalRef = context;
if (fragment) {
data = jptr(data, fragment);
if (data === false) {
data = {}; // case:A(2) where the resolution fails
if (options.fatal) {
let ex = new Error('Cached $ref resolution failed '+target+fragment);
if (options.promise) options.promise.reject(ex)
else throw(ex);
}
}
}
data = resolveAllFragment(data, context, pointer, fragment, target, options);
data = filterData(data, options);
callback(clone(data), target, options);
return Promise.resolve(data);
}
if (options.verbose) console.warn('GET', target, fragment);
if (options.handlers && options.handlers[effectiveProtocol]) {
return options.handlers[effectiveProtocol](base, pointer, fragment, options)
.then(function (data) {
options.externalRef = data;
data = filterData(data, options);
options.cache[target] = data;
callback(data, target, options);
return data;
})
.catch(function(ex){
if (options.verbose) console.warn(ex);
}
}
if (!refs[$ref]) {
refs[$ref] = { resolved: false, paths: [], extras:{}, description: obj[key].description };
}
if (refs[$ref].resolved) {
if (options.rewriteRefs) {
// we've already seen it
let newRef = refs[$ref].resolvedAt;
if (options.verbose>1) console.warn('Rewriting ref', $ref, newRef);
obj[key]['x-miro'] = $ref;
obj[key].$ref = newRef+$extra; // resolutionCase:C (new string)
}
else {
obj[key] = clone(refs[$ref].data); // resolutionCase:D (cloned:yes)
}
}
else {
refs[$ref].paths.push(state.path);
refs[$ref].extras[state.path] = $extra;
}
}
}
}
function fixupRefs(obj, key, state) {
let options = state.payload.options;
if (isRef(obj,key)) {
if (obj[key].startsWith('#/components/')) {
// no-op
}
else if (obj[key] === '#/consumes') {
// people are *so* creative
delete obj[key];
state.parent[state.pkey] = clone(options.openapi.consumes);
}
else if (obj[key] === '#/produces') {
// and by creative, I mean devious
delete obj[key];
state.parent[state.pkey] = clone(options.openapi.produces);
}
else if (obj[key].startsWith('#/definitions/')) {
//only the first part of a schema component name must be sanitised
let keys = obj[key].replace('#/definitions/', '').split('/');
let newKey = componentNames.schemas[decodeURIComponent(keys[0])]; // lookup, resolves a $ref
if (newKey) {
keys[0] = newKey;
}
else {
throwOrWarn('Could not resolve reference '+obj[key],obj,options);
}
let target;
if (effectiveProtocol === 'file:') {
target = path.resolve(base ? base + '/' : '', pointer);
}
else {
target = url.resolve(base ? base + '/' : '', pointer);
}
if (options.cache[target]) {
if (options.verbose) console.warn('CACHED', target, fragment);
/*
resolutionSource:A this is where we have cached the externally-referenced document from a
file, http or custom handler
*/
let context = clone(options.cache[target]);
let data = options.externalRef = context;
if (fragment) {
data = jptr(data, fragment);
if (data === false) {
data = {}; // case:A(2) where the resolution fails
if (options.fatal) {
let ex = new Error('Cached $ref resolution failed '+target+fragment);
if (options.promise) options.promise.reject(ex)
else throw(ex);
}
}
}
data = resolveAllFragment(data, context, pointer, fragment, target, options);
data = filterData(data, options);
callback(clone(data), target, options);
return Promise.resolve(data);
let newRef = url.resolve(base,obj[key]).toString();
if (options.verbose>1) console.warn(common.colour.yellow+'Rewriting external url ref',obj[key],'as',newRef,common.colour.normal);
obj['x-miro'] = obj[key];
obj[key] = newRef;
}
else if (!obj['x-miro']) {
let newRef = url.resolve(base,obj[key]).toString();
if (options.verbose>1) console.warn(common.colour.yellow+'Rewriting external ref',obj[key],'as',newRef,common.colour.normal);
obj['x-miro'] = obj[key]; // we use x-miro as a flag so we don't do this > once
obj[key] = newRef;
}
}
});
}
recurse(obj,{},function(obj,key,state){
if (isRef(obj, key)) {
if (typeof obj.$fixed !== 'undefined') delete obj.$fixed;
}
});
if (options.verbose>1) console.warn('Finished fragment resolution');
return obj;
}
options.allowFailure = false;
if ((options.source.indexOf('!')>=0) && (options.source.indexOf('swagger.')>=0)) {
expectFailure = true;
options.expectFailure = true;
options.allowFailure = true;
}
if ((options.source.indexOf('!')>=0) && (options.source.indexOf('openapi.')>=0)) {
expectFailure = true;
options.expectFailure = false; // because some things are corrected
options.allowFailure = true;
}
if (file.startsWith('http')) {
swagger2openapi.convertUrl(file, clone(options))
.then(function(options){
handleResult(null,options);
})
.catch(function(ex){
console.warn(common.colour.red+ex,common.colour.normal);
if (expectFailure) {
warnings.push('Converter failed ' + options.source);
}
else {
failures.push('Converter failed ' + options.source);
fail++;
}
genStackNext();
result = false;
});
}
return maybe(callback, new Promise(function (resolve, reject) {
if (!swagger) swagger = {};
options.original = swagger;
if (!options.text) options.text = yaml.stringify(swagger);
options.externals = [];
options.externalRefs = {};
options.rewriteRefs = true; // avoids stack explosions
options.preserveMiro = true;
options.promise = {};
options.promise.resolve = resolve;
options.promise.reject = reject;
if (!options.cache) options.cache = {};
if (options.source) options.cache[options.source] = options.original;
if (swagger.openapi && (typeof swagger.openapi === 'string') && swagger.openapi.startsWith('3.')) {
options.openapi = cclone(swagger);
fixInfo(options.openapi, options, reject);
fixPaths(options.openapi, options, reject);
resolver.optionalResolve(options) // is a no-op if options.resolve is not set
.then(function(){
if (options.direct) {
return resolve(options.openapi);
}
else {
return resolve(options);
}
})
.catch(function(ex){
console.warn(ex);
reject(ex);
});
function checkContent(content, contextServers, openapi, options) {
contextAppend(options, 'content');
content.should.be.an.Object();
content.should.not.be.an.Array();
for (let ct in content) {
contextAppend(options, jptr.jpescape(ct));
// validate ct against https://tools.ietf.org/html/rfc6838#section-4.2
should(/[a-zA-Z0-9!#$%^&\*_\-\+{}\|'.`~]+\/[a-zA-Z0-9!#$%^&\*_\-\+{}\|'.`~]+/.test(ct)).be.exactly(true,'media-type should match RFC6838 format'); // this is a SHOULD not MUST
let contentType = content[ct];
should(contentType).be.an.Object();
should(contentType).not.be.an.Array();
if (typeof contentType.schema !== 'undefined') {
checkSchema(contentType.schema,emptySchema,'schema',openapi,options);
}
if (contentType.example) {
contentType.should.not.have.property('examples');
}
if (contentType.examples) {
contextAppend(options, 'examples');
contentType.should.not.have.property('example');
contentType.examples.should.be.an.Object();