Skip to content
This repository was archived by the owner on Feb 28, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 25 additions & 24 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ module.exports = class extends Generator {
this.skipPrompt = true;
let bluemix_ok= this._sanitizeOption(this.options, OPTION_BLUEMIX);
let spec_ok= this._sanitizeOption(this.options, OPTION_SPEC);
if ( ! (bluemix_ok || spec_ok )) throw ("Must specify either bluemix or spec parameter");
if ( typeof this.options.bluemix.quiet == "undefined" || ! this.options.bluemix.quiet ) {
if ( ! (bluemix_ok || spec_ok )) throw ("Must specify either bluemix or spec parameter");

if ( typeof this.options.bluemix.quiet == "undefined" || ! this.options.bluemix.quiet ) {
logger.info("Package info ::", Bundle.name, Bundle.version);
}
}

let appName = this.options.bluemix.name || this.options.spec.appname;
this.options.sanitizedAppName = this._sanitizeAppName(appName);
this.options.genSwagger= false;
this.options.openApiFileType= "yaml"; // default
this.options.genSwagger= false;
this.options.openApiFileType= "yaml"; // default

this.options.parsedSwagger = undefined;
let formatters = {
Expand All @@ -75,18 +75,18 @@ module.exports = class extends Generator {
.then(response => {
this.options.loadedApi = response.loaded;
this.options.parsedSwagger = response.parsed;
this.options.openApiFileType= response.type;
this.options.genSwagger= true;
this.options.openApiFileType= response.type;
this.options.genSwagger= true;
})
.catch(err => {
err.message = 'failed to parse document from bluemix.openApiServers ' + err.message;
throw err;
})
}

// micro service always gets swagger ui and no public
// micro service always gets swagger ui and no public
if(this.options.spec && this.options.spec.applicationType === 'MS') {
this.options.genSwagger= true;
this.options.genSwagger= true;
}

}
Expand Down Expand Up @@ -115,34 +115,35 @@ module.exports = class extends Generator {
this.fs.copyTpl(this.templatePath('Dockerfile-tools'), this.destinationPath('Dockerfile-tools'), this.options);
this.fs.copyTpl(this.templatePath('package.json'), this.destinationPath('package.json'), this.options);
this.fs.copyTpl(this.templatePath('README.md'), this.destinationPath('README.md'), this.options);
this.fs.copyTpl(this.templatePath('idt.js'), this.destinationPath('idt.js'), this.options);

// if project will have swagger doc, ensure swagger ui and api route
// if project will have swagger doc, ensure swagger ui and api route
if ( this.options.genSwagger ) {
this.fs.copy(this.templatePath('public/swagger-ui'), this.destinationPath('public/swagger-ui'));
// if open api doc provided, write it else write default
// if open api doc provided, write it else write default

if ( this.options.loadedApi ) {
let yaml= this.options.bluemix.openApiServers[0].spec;
//this.fs.writeJSON('public/swagger.'+this.options.openApiFileType, this.options.loadedApi);
this.fs.write('public/swagger.'+this.options.openApiFileType, yaml);
}
this.fs.write('public/swagger.'+this.options.openApiFileType, yaml);
}
else {
this.fs.copyTpl(this.templatePath('public/swagger.yaml'), this.destinationPath('public/swagger.yaml'), this.options);
}
}
else {
else {
this.fs.delete(this.destinationPath('server/routers/swagger.js'));
}

// if there is swagger, there is no index page
if( this.options.genSwagger ) {
this.fs.delete(this.destinationPath('server/routers/public.js'));
}
else {
else {
this.fs.copy(this.templatePath('public/index.html'), this.destinationPath('public/index.html'));
}

// blank project is stripped down to bare minimum
// blank project is stripped down to bare minimum
if(this.options.spec && this.options.spec.applicationType === 'BLANK') {
this.fs.delete(this.destinationPath('server/routers/health.js'));
}
Expand All @@ -153,29 +154,29 @@ module.exports = class extends Generator {
return name.toLowerCase().replace(REGEX_LEADING_ALPHA, '').replace(REGEX_ALPHA_NUM, '');
}

// return true if 'sanitized', false if missing, exception if bad data
// return true if 'sanitized', false if missing, exception if bad data
_sanitizeOption(options, name) {
let optionValue = options[name];
if (!optionValue) {
logger.error("Missing", name, "parameter");
return false;
return false;
}

if (typeof optionValue === "string" && optionValue.indexOf("file:") === 0) {
let fileName = optionValue.replace("file:", "");
let filePath = this.destinationPath("./" + fileName);
logger.info("Reading", name, "parameter from local file", filePath);
this.options[name] = this.fs.readJSON(filePath);
return true;
return true;
}

try {
this.options[name] = typeof(this.options[name]) === "string" ?
JSON.parse(this.options[name]) : this.options[name];
return true;
return true;
} catch (e) {
logger.error(e);
throw name + " parameter is expected to be a valid stringified JSON object";
}
}
}
};
};
16 changes: 15 additions & 1 deletion app/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,22 @@ A generated Bluemix application
[![](https://img.shields.io/badge/bluemix-powered-blue.svg)](https://bluemix.net)

## Run locally as Node.js application

```bash
npm install
npm test
npm start
```
```

## Build, run, and deploy using IDT

```bash
# Install needed dependencies:
npm run idt:install
# Build the docker image for your app:
npm run idt:build
# Run the app locally through docker:
npm run idt:run
# Deploy your app to IBM Cloud:
npm run idt:deploy
```
89 changes: 89 additions & 0 deletions app/templates/idt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict'

/*
* Wrapper for the idt (IBM Developer Tools) command.
* Run with the same arguments as `idt`, e.g.
* `node idt.js build` -> `idt build`.
* If `idt` isn't installed, this will prompt you to install. Or you can run
* `node idt.js install` to automatically install idt and any other
* required dependencies (e.g. docker, git, kubernetes, helm).
*
*/

const fs = require('fs');
const process = require('process');
const cp = require('child_process');
const request = require('request');
const path = require('path');

const chalk = require('chalk');

const node = process.execPath;
// Array of args passed to idt.js.
const args = process.argv.slice(2);
let win = (process.platform === 'win32');

// Either install idt or run idt + args.
if (args.includes('install')) {
downloadInstaller();
} else {
// TODO(gib): Check for idt once this works in scripts:
// const checkCmd = win ? 'where idt' : 'which idt';
const checkCmd = 'bx plugin show dev';
let hasIDT = false;
try {
console.log(chalk.blue('Checking for idt'));
cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.
hasIDT = true; // If we didn't have idt, the previous command would have thrown.
} catch (e) {
const prompt = require('prompt-confirm');
new prompt({ name: 'install',
message: 'IDT not found, do you want to install it? y/N',
default: false
}).ask((answer) => {
if (answer) {
downloadInstaller(() => runIDT(args));
} else {
console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));
}
});
}
if (hasIDT) runIDT(args);
}

// Run IDT with whatever args we were given.
function runIDT(args) {
const cmd = 'bx dev ' + args.join(' ');
console.log(chalk.blue('Running:'), cmd);
cp.execSync(cmd, {stdio: 'inherit'});
}

// Download the IDT installer script and trigger runIDT().
function downloadInstaller(cb) {
const url = win ?
'https://ibm.biz/yeoman-idt-win-install' :
'http://ibm.biz/yeoman-idt-install';

const fileName = url.split('/').pop()

console.log(chalk.blue('Downloading installer from:'), url);

const file = fs.createWriteStream(fileName);

request
.get({url, followAllRedirects: true})
.on('error', (err) => { console.error(err); })
.pipe(file)
.on('finish', () => runInstaller(fileName, cb));
}

// Run the installer script and trigger callback (cb).
function runInstaller(fileName, cb) {
const shell = win ? 'powershell.exe' : 'bash';

const filePath = path.resolve(__dirname, fileName);
console.log(`Now running: ${shell} ${filePath}`);

cp.spawnSync(shell, [filePath], {stdio: 'inherit'});
cb();
}
15 changes: 13 additions & 2 deletions app/templates/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,30 @@
"start": "node server/server.js",
"start:cluster": "sl-run server/server.js",
"debug": "node --debug server/server.js",
"test": "nyc mocha"
"test": "nyc mocha",
"build": "npm run build:idt",
"idt:build": "node idt.js build",
"idt:test": "node idt.js test",
"idt:debug": "node idt.js debug",
"idt:run": "node idt.js run",
"idt:deploy": "node idt.js deploy",
"idt:install": "node idt.js install"
},
"dependencies": {
"appmetrics-dash": "^3.3.2",
"appmetrics-prometheus": "^0.0.2",
"body-parser": "^1.17.2",
"express": "^4.15.3",
"strong-supervisor": "^6.2.0",
"log4js": "^1.1.1"
},
"devDependencies": {
"chai": "^4.0.0",
"chalk": "^1.1.3",
"mocha": "^3.4.2",
"nyc": "^10.3.2",
"proxyquire": "^1.8.0"
"prompt-confirm": "^1.2.0",
"proxyquire": "^1.8.0",
"request": "^2.82.0"
}
}
2 changes: 1 addition & 1 deletion app/templates/server/config/local.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"port": 3000
"port": 3000
}
6 changes: 3 additions & 3 deletions app/templates/server/routers/public.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var express = require('express');

module.exports = function(app){
var router = express.Router();
router.use(express.static(process.cwd() + '/public'));
app.use(router);
var router = express.Router();
router.use(express.static(process.cwd() + '/public'));
app.use(router);
}
18 changes: 10 additions & 8 deletions app/templates/server/server.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require('appmetrics-dash').attach();
require('appmetrics-prometheus').attach();

const appName = require('./../package').name;
const express = require('express');
const log4js = require('log4js');
Expand All @@ -14,12 +16,12 @@ require('./routers/index')(app);

const port = process.env.PORT || localConfig.port;
app.listen(port, function(){
logger.info(`<%= bluemix.name %> listening on http://localhost:${port}/appmetrics-dash`);
<% if( !genSwagger ){ %>
logger.info(`<%= bluemix.name %> listening on http://localhost:${port}`);
<% } %>
<% if( genSwagger ){ %>
logger.info(`OpenAPI (Swagger) spec is available at http://localhost:${port}/swagger/api`);
logger.info(`Swagger UI is available at http://localhost:${port}/explorer`);
<% } %>
logger.info(`<%= bluemix.name %> listening on http://localhost:${port}/appmetrics-dash`);
<% if( !genSwagger ){ %>
logger.info(`<%= bluemix.name %> listening on http://localhost:${port}`);
<% } %>
<% if( genSwagger ){ %>
logger.info(`OpenAPI (Swagger) spec is available at http://localhost:${port}/swagger/api`);
logger.info(`Swagger UI is available at http://localhost:${port}/explorer`);
<% } %>
});
4 changes: 2 additions & 2 deletions lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
exports.reformatPathToNodeExpress = (path) => path.replace(/{/g, ':').replace(/}/g, '')

exports.resourceNameFromPath = function (path) {
// grab the first valid element of a path (or partial path) and return it.
return path.match(/^\/*([^/]+)/)[1]
// grab the first valid element of a path (or partial path) and return it.
return path.match(/^\/*([^/]+)/)[1]
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "generator-ibm-core-node-express",
"version": "0.0.60",
"version": "0.0.64",
"description": "Yeoman generator for core node express application",
"license": "Apache-2.0",
"keywords": [
Expand Down
3 changes: 2 additions & 1 deletion test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ exports.file = {
index_router: 'server/routers/index.js',
public: 'server/routers/public.js',
index_service: 'server/services/index.js',
idt_js: 'idt.js',
cliconfig: 'cli-config.yml'
};

// Default port defined in app/index.js.
exports.defaultPort = 3000;

// The npm start command.
exports.npmStart = "node server.js"
exports.npmStart = "node server.js"
Loading