UNPKG

apiconnect-cli-loopback

Version:

Plugin for IBM API Connect Developer Toolkit

150 lines (134 loc) 5.52 kB
/********************************************************* {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; }