@loopback/cli
Version:
Yeoman generator for LoopBack 4
84 lines (76 loc) • 2.59 kB
JavaScript
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
// Node module: @loopback/cli
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
;
const chalk = require('chalk');
const SwaggerParser = require('swagger-parser');
const swagger2openapi = require('swagger2openapi');
const {debugJson, cloneSpecObject} = require('./utils');
const {generateControllerSpecs} = require('./spec-helper');
const {generateModelSpecs, registerNamedSchemas} = require('./schema-helper');
const {ResolverError} = require('@apidevtools/json-schema-ref-parser');
/**
* Load swagger specs from the given url or file path; handle yml or json
* @param {String} specUrlStr The url or file path to the swagger spec
*/
async function loadSpec(specUrlStr, {log, validate} = {}) {
if (typeof log === 'function') {
log(chalk.blue('Loading ' + specUrlStr + '...'));
}
const parser = new SwaggerParser();
let spec = await parser.parse(specUrlStr);
if (spec.swagger === '2.0') {
debugJson('Swagger spec loaded: ', spec);
spec = (await swagger2openapi.convertObj(spec, {patch: true})).openapi;
debugJson('OpenAPI spec converted from Swagger: ', spec);
} else if (spec.openapi) {
debugJson('OpenAPI spec loaded: ', spec);
}
spec = cloneSpecObject(spec);
// Validate and deference the spec
if (validate) {
spec = await parser.validate(spec, {
dereference: {
circular: true, // Allow circular $refs
},
validate: {
spec: true, // Don't validate against the Swagger spec
},
});
} else {
try {
spec = await parser.dereference(spec);
} catch (error) {
// If returns http unauthorized error, ignore resolving external ref$ pointer
if (error instanceof ResolverError) {
spec = await parser.dereference(spec, {resolve: {external: false}});
}
}
}
return spec;
}
async function loadAndBuildSpec(
url,
{log, validate, promoteAnonymousSchemas} = {},
) {
const apiSpec = await loadSpec(url, {log, validate});
// First populate the type registry for named schemas
const typeRegistry = {
objectTypeMapping: new Map(),
schemaMapping: {},
promoteAnonymousSchemas,
};
registerNamedSchemas(apiSpec, typeRegistry);
const controllerSpecs = generateControllerSpecs(apiSpec, typeRegistry);
const modelSpecs = generateModelSpecs(apiSpec, typeRegistry);
return {
apiSpec,
modelSpecs,
controllerSpecs,
};
}
module.exports = {
loadSpec,
loadAndBuildSpec,
};