apiconnect-cli-loopback
Version:
Plugin for IBM API Connect Developer Toolkit
150 lines (134 loc) • 5.52 kB
JavaScript
/********************************************************* {COPYRIGHT-TOP} ***
* Licensed Materials - Property of IBM
* 5725-Z22, 5725-Z63, 5725-U33, 5725-Z63
*
* (C) Copyright IBM Corporation 2016, 2017
*
* All Rights Reserved.
* US Government Users Restricted Rights - Use, duplication or disclosure
* restricted by GSA ADP Schedule Contract with IBM Corp.
********************************************************** {COPYRIGHT-END} **/
// Node module: apiconnect-cli-loopback
'use strict';
var _ = require('lodash');
var config = require('apiconnect-config');
var childProcess = require('child_process');
var createProduct = require('apiconnect-cli-create').createProduct;
var resolveApiTemplateFile = require('apiconnect-cli-create').resolveApiTemplateFile;
var debug = require('debug')('apiconnect-cli-loopback:lib:swagger');
var fs = require('fs');
var g = require('strong-globalize')();
var generateSlugFromText = require('apiconnect-cli-create').generateSlugFromText;
var handlebars = require('handlebars');
var jsYaml = require('js-yaml');
var logger = require('apiconnect-cli-logger');
var mkdirp = require('mkdirp');
var os = require('os');
var path = require('path');
var project = require('apiconnect-project');
var rimraf = require('rimraf');
/**
* Get swagger for loopback application
*/
function swaggerGen(lbRoot) {
var tmpPath = path.join(os.tmpdir(), Math.random() + '-' + (+new Date()));
mkdirp.sync(tmpPath);
var swaggerPath = path.join(tmpPath, 'swagger.json');
// In-process swagger generation results in using a cached version of the loopback app which doesnt update when
// new models are added. Generate it in a spawned process instead.
var childOut = childProcess.spawnSync(
process.argv[0],
[ require.resolve('./swaggerGenProc'), swaggerPath, lbRoot ],
{ cwd: lbRoot }
);
debug(childOut.stdout.toString());
debug(childOut.status);
if (childOut.status !== 0) {
throw new Error(g.f('The LoopBack application is not loaded.\n%s',
childOut.stderr.toString()));
}
var apiDef = jsYaml.safeLoad(fs.readFileSync(swaggerPath, 'utf8'));
rimraf(tmpPath, { disableGlob: true }, function(err) {
// error here indicates tmp dir was not cleaned up
debug(err);
});
return apiDef;
}
function genApiAndProduct(lbAppDir) {
logger.writeln();
logger.writeln(g.f('Updating swagger and product definitions'));
var projectInfo = project.inspectPath(lbAppDir || process.cwd());
if (projectInfo.type !== 'project' || projectInfo.projectType !== 'loopback') {
throw new Error(g.f('This is not a LoopBack project directory.'));
}
lbAppDir = projectInfo.basePath;
var apiFileName = projectInfo.name + '.yaml';
return project.loadProject(lbAppDir).then(function(artifacts) {
artifacts = _.filter(artifacts, { type: 'product' });
var productFile = null;
if (artifacts.length > 0) {
productFile = artifacts[0].filePath;
}
var swaggerData = _.pick(swaggerGen(lbAppDir), [ 'paths', 'definitions', 'basePath' ]);
debug('generated: %j', swaggerData);
var apiFilePath = path.resolve(lbAppDir, path.join('definitions', apiFileName));
var templatePath = resolveApiTemplate(lbAppDir);
try {
var oldSwaggerData = jsYaml.safeLoad(fs.readFileSync(apiFilePath, 'utf8'));
_.defaults(swaggerData, oldSwaggerData);
writeSwaggerFile(apiFilePath, jsYaml.safeDump(swaggerData));
} catch (_) {
try {
var template = handlebars.compile(fs.readFileSync(templatePath, 'utf8'));
} catch (err) {
debug(err);
throw new Error(g.f('The template %s is not found.', templatePath));
}
writeSwaggerFile(apiFilePath, template({
title: projectInfo.name,
name: generateSlugFromText(projectInfo.name),
version: '1.0.0',
basePath: '/api',
paths: jsYaml.safeDump({ paths: swaggerData.paths }),
definitions: jsYaml.safeDump({ definitions: swaggerData.definitions }),
pathsObj: swaggerData.paths,
definitionsObj: swaggerData.definitions,
}));
}
if (productFile == null) {
var productFilePath = path.join('definitions', projectInfo.name + '-product.yaml');
productFilePath = path.resolve(lbAppDir, productFilePath);
debug('Generating product file at %s', productFilePath);
var apis = {};
apis = path.relative(path.dirname(productFilePath), apiFilePath);
var productData = {
title: projectInfo.name,
filename: productFilePath,
apis: apis,
};
debug('productData %j', productData);
return createProduct(productData);
} else {
debug('Product file was found at %s. Not regenning', productFile);
}
});
}
exports.genApiAndProduct = genApiAndProduct;
function writeSwaggerFile(apiFilePath, data) {
mkdirp.sync(path.dirname(apiFilePath));
debug('Writing swagger %s', apiFilePath);
logger.writeln(g.f('Created %s swagger description', apiFilePath));
fs.writeFileSync(apiFilePath, data);
}
module.exports.resolveApiTemplate = resolveApiTemplate;
function resolveApiTemplate(confDir) {
var templatePath;
var conf = confDir ? config.loadConfig(confDir) : config.loadConfig();
var defaultApiTemplate = conf.getOne('template-default-api');
if (defaultApiTemplate) {
templatePath = resolveApiTemplateFile(defaultApiTemplate + '.hbs', { config: conf });
} else {
templatePath = path.resolve(__dirname, path.join('templates', 'swagger.hbs'));
}
return templatePath;
}