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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
# If eslint goes into this dir it will read package.json as a config file
# We either rename the package.json template, or we don't lint this dir
app/templates/
coverage/
14 changes: 14 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
env:
node: true
es6: true
mocha: true

rules:
strict: 0
no-var: 2
no-console: 0
indent: ["error", "tab", { "SwitchCase": 1}]

extends: eslint:recommended

plugins: [ejs]
18 changes: 17 additions & 1 deletion node_modules/cloneable-readable/.npmignore → .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ lib-cov
# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

Expand All @@ -23,11 +26,24 @@ coverage
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

test/tmp
.idea
.vscode

# output from generator
# Dockerfile
# Dockerfile-tools
# cli-config.yml
# manifest.yml
# .cfignore
# .bluemix
13 changes: 13 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"check-coverage": true,
"statements": 85,
"branches": 72,
"functions": 100,
"lines": 85,
"include": [
"app/*.js"
],
"exclude": [
"app/templates/**"
]
}
23 changes: 23 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
language: node_js

node_js:
- '8'

script: npm test && npm run coveralls && ./npm_patch.sh

branches:
only:
- development
- master

notifications:
slack:
rooms:
- $SLACK_ARF_DEVOPS

deploy:
provider: npm
email: $NPM_EMAIL
api_key: $NPM_TOKEN
on:
branch: master
250 changes: 128 additions & 122 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const Generator = require('yeoman-generator');
const Bundle = require("./../package.json")
const Log4js = require('log4js');
const logger = Log4js.getLogger("generator-core-node-express");
const helpers = require("../lib/helpers");
//const swaggerize = require('@arf/swaggerize');
// TODO: const helpers = require("../lib/helpers");
// TODO: const swaggerize = require('@arf/swaggerize');
const OPTION_BLUEMIX = "bluemix";
const OPTION_SPEC = "spec";

Expand All @@ -26,124 +26,130 @@ const REGEX_ALPHA_NUM = /[^a-zA-Z0-9]/g;

module.exports = class extends Generator {

constructor(args, opts) {
super(args, opts);
logger.info("Package info ::", Bundle.name, Bundle.version);

// bluemix option for YaaS integration
this.argument(OPTION_BLUEMIX, {
desc: 'Option for deploying with Bluemix. Stringified JSON.',
required: false,
hide: true,
type: String
});

// spec as json
this.argument(OPTION_SPEC, {
desc: 'The generator specification. Stringified JSON.',
required: false,
hide: true,
type: String
});
}

initializing() {
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");
let appName = this.options.bluemix.name || this.options.spec.appname;
this.options.sanitizedAppName = this._sanitizeAppName(appName);

this.options.parsedSwagger = undefined;
let formatters = {
'pathFormatter': helpers.reformatPathToNodeExpress,
'resourceFormatter': helpers.resourceNameFromPath
}

if (this.options.bluemix && this.options.bluemix.openApiServers && this.options.bluemix.openApiServers[0].spec) {
let openApiDocumentBytes = typeof this.options.bluemix.openApiServers[0].spec === 'object'
? JSON.stringify(this.options.bluemix.openApiServers[0].spec)
: this.options.bluemix.openApiServers[0].spec;
return swaggerize.parse(openApiDocumentBytes, formatters)
.then(response => {
this.options.loadedApi = response.loaded;
this.options.parsedSwagger = response.parsed;
})
.catch(err => {
err.message = 'failed to parse document from bluemix.openApiServers ' + err.message;
throw err;
})
}
}

writing() {
this.fs.copyTpl(this.templatePath('server'), this.destinationPath('server'), this.options);

if (this.options.parsedSwagger) {
Object.keys(this.options.parsedSwagger.resources).forEach(function(resource) {
let context = {
'resource': resource,
'routes': this.options.parsedSwagger.resources[resource],
'basepath': this.options.parsedSwagger.basepath
}
this.fs.copyTpl(this.templatePath('fromswagger/routers/router.js'), this.destinationPath(`server/routers/${resource}.js`), context);
this.fs.copyTpl(this.templatePath('test/resource.js'), this.destinationPath(`test/${resource}.js`), context);
}.bind(this));
}

this.fs.copyTpl(this.templatePath('test/test-server.js'), this.destinationPath('test/test-server.js'), this.options);
this.fs.copyTpl(this.templatePath('test/test-demo.js'), this.destinationPath('test/test-demo.js'), this.options);
this.fs.copyTpl(this.templatePath('_gitignore'), this.destinationPath('.gitignore'), this.options);
this.fs.copyTpl(this.templatePath('cli-config.yml'), this.destinationPath('cli-config.yml'), this.options);
this.fs.copyTpl(this.templatePath('Dockerfile'), this.destinationPath('Dockerfile'), this.options);
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('_package-lock.json'), this.destinationPath('package-lock.json'), this.options);
this.fs.copyTpl(this.templatePath('README.md'), this.destinationPath('README.md'), this.options);

if(this.options.spec && this.options.spec.applicationType === 'MS') {
this.fs.copy(this.templatePath('public/swagger-ui'), this.destinationPath('public/swagger-ui'));
this.fs.copyTpl(this.templatePath('public/swagger.yaml'), this.destinationPath('public/swagger.yaml'), this.options);
this.fs.delete(this.destinationPath('server/routers/public.js'));
} else {
this.fs.copy(this.templatePath('public/index.html'), this.destinationPath('public/index.html'));
this.fs.delete(this.destinationPath('server/routers/swagger.js'));
}

if(this.options.spec && this.options.spec.applicationType === 'BLANK') {
this.fs.delete(this.destinationPath('server/routers/health.js'));
}
}

_sanitizeAppName(name) {
name = name || 'appname';
return name.toLowerCase().replace(REGEX_LEADING_ALPHA, '').replace(REGEX_ALPHA_NUM, '');
}

// 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;
}

if (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;
}

try {
this.options[name] = typeof(this.options[name]) === "string" ?
JSON.parse(this.options[name]) : this.options[name];
return true;
} catch (e) {
logger.error(e);
throw name + " parameter is expected to be a valid stringified JSON object";
}
}
constructor(args, opts) {
super(args, opts);
logger.info("Package info ::", Bundle.name, Bundle.version);

// bluemix option for YaaS integration
this.argument(OPTION_BLUEMIX, {
desc: 'Option for deploying with Bluemix. Stringified JSON.',
required: false,
hide: true,
type: String
});

// spec as json
this.argument(OPTION_SPEC, {
desc: 'The generator specification. Stringified JSON.',
required: false,
hide: true,
type: String
});
}

initializing() {
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");
let appName = this.options.bluemix.name || this.options.spec.appname;
this.options.sanitizedAppName = this._sanitizeAppName(appName);

this.options.parsedSwagger = undefined;
/* TODO:
let formatters = {
'pathFormatter': helpers.reformatPathToNodeExpress,
'resourceFormatter': helpers.resourceNameFromPath
}
*/
/* TODO:
if (this.options.bluemix && this.options.bluemix.openApiServers && this.options.bluemix.openApiServers[0].spec) {
let openApiDocumentBytes = typeof this.options.bluemix.openApiServers[0].spec === 'object'
? JSON.stringify(this.options.bluemix.openApiServers[0].spec)
: this.options.bluemix.openApiServers[0].spec;

return swaggerize.parse(openApiDocumentBytes, formatters)
.then(response => {
this.options.loadedApi = response.loaded;
this.options.parsedSwagger = response.parsed;
})
.catch(err => {
err.message = 'failed to parse document from bluemix.openApiServers ' + err.message;
throw err;
})
}
*/
}

writing() {
this.fs.copyTpl(this.templatePath('server'), this.destinationPath('server'), this.options);

/* TODO:
if (this.options.parsedSwagger) {
Object.keys(this.options.parsedSwagger.resources).forEach(function(resource) {
let context = {
'resource': resource,
'routes': this.options.parsedSwagger.resources[resource],
'basepath': this.options.parsedSwagger.basepath
}
this.fs.copyTpl(this.templatePath('fromswagger/routers/router.js'), this.destinationPath(`server/routers/${resource}.js`), context);
this.fs.copyTpl(this.templatePath('test/resource.js'), this.destinationPath(`test/${resource}.js`), context);
}.bind(this));
}
*/

this.fs.copyTpl(this.templatePath('test/test-server.js'), this.destinationPath('test/test-server.js'), this.options);
this.fs.copyTpl(this.templatePath('test/test-demo.js'), this.destinationPath('test/test-demo.js'), this.options);
this.fs.copyTpl(this.templatePath('_gitignore'), this.destinationPath('.gitignore'), this.options);
this.fs.copyTpl(this.templatePath('cli-config.yml'), this.destinationPath('cli-config.yml'), this.options);
this.fs.copyTpl(this.templatePath('Dockerfile'), this.destinationPath('Dockerfile'), this.options);
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('_package-lock.json'), this.destinationPath('package-lock.json'), this.options);
this.fs.copyTpl(this.templatePath('README.md'), this.destinationPath('README.md'), this.options);

if(this.options.spec && this.options.spec.applicationType === 'MS') {
this.fs.copy(this.templatePath('public/swagger-ui'), this.destinationPath('public/swagger-ui'));
this.fs.copyTpl(this.templatePath('public/swagger.yaml'), this.destinationPath('public/swagger.yaml'), this.options);
this.fs.delete(this.destinationPath('server/routers/public.js'));
} else {
this.fs.copy(this.templatePath('public/index.html'), this.destinationPath('public/index.html'));
this.fs.delete(this.destinationPath('server/routers/swagger.js'));
}

if(this.options.spec && this.options.spec.applicationType === 'BLANK') {
this.fs.delete(this.destinationPath('server/routers/health.js'));
}
}

_sanitizeAppName(name) {
name = name || 'appname';
return name.toLowerCase().replace(REGEX_LEADING_ALPHA, '').replace(REGEX_ALPHA_NUM, '');
}

// 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;
}

if (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;
}

try {
this.options[name] = typeof(this.options[name]) === "string" ?
JSON.parse(this.options[name]) : this.options[name];
return true;
} catch (e) {
logger.error(e);
throw name + " parameter is expected to be a valid stringified JSON object";
}
}
};
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]
}
1 change: 0 additions & 1 deletion node_modules/.bin/_mocha

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/acorn

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/coveralls

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/eslint

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/esparse

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/esvalidate

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/js-yaml

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/mkdirp

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/mocha

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/.bin/nyc

This file was deleted.

Loading