Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/rocket #69

Merged
merged 11 commits into from
May 16, 2017
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
44 changes: 26 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
# generator-ngx-app
# :rocket: ngx-rocket/generator-ngx-rocket

[![NPM version](https://img.shields.io/npm/v/generator-ngx-app.svg)](https://www.npmjs.com/package/generator-ngx-app)
[![Build status](https://img.shields.io/travis/angular-starter-kit/generator-ngx-app/master.svg)](https://travis-ci.org/angular-starter-kit/generator-ngx-app)
[![Downloads](https://img.shields.io/npm/dt/generator-ngx-app.svg)](https://npmjs.org/package/generator-ngx-app)
**:loudspeaker: We have moved! :loudspeaker:** As you may have noticed, this generator
[has moved](https://github.com/ngx-rocket/generator-ngx-rocket/issues/65) to the `ngx-rocket`
organization, and has been renamed from `generator-ngx-app` to `generator-ngx-rocket`, so update
your bookmarks/remotes! :rocket:

---

[![NPM version](https://img.shields.io/npm/v/generator-ngx-rocket.svg)](https://www.npmjs.com/package/generator-ngx-rocket)
[![Build status](https://img.shields.io/travis/ngx-rocket/generator-ngx-rocket/master.svg)](https://travis-ci.org/ngx-rocket/generator-ngx-rocket)
![Node version](https://img.shields.io/badge/node-%3E%3D6.0.0-brightgreen.svg)
[![Downloads](https://img.shields.io/npm/dt/generator-ngx-rocket.svg)](https://npmjs.org/package/generator-ngx-rocket)

Web project starter kit including modern tools and workflow based on
[angular-cli](https://github.com/angular/angular-cli), best practices from the community, a scalable base template and
a good learning base.

See generated project example [here](https://github.com/angular-starter-kit/ngx-starter-kit).
See generated project example [here](https://github.com/ngx-rocket/starter-kit).

### Benefits

Expand All @@ -24,12 +32,12 @@ See generated project example [here](https://github.com/angular-starter-kit/ngx-

1. Install required tools:
```bash
npm install -g yo generator-ngx-app
npm install -g yo generator-ngx-rocket
```

2. Create your application:
```bash
yo ngx-app
yo ngx-rocket
```

# Project structure
Expand Down Expand Up @@ -126,20 +134,20 @@ Development, build and quality processes are based on [angular-cli](https://gith

#### Coding guides

- [Angular](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/angular.md)
- [TypeScript](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/typescript.md)
- [Sass](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/sass.md)
- [HTML](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/html.md)
- [Unit tests](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/unit-tests.md)
- [End-to-end tests](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/coding-guides/e2e-tests.md)
- [Angular](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/angular.md)
- [TypeScript](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/typescript.md)
- [Sass](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/sass.md)
- [HTML](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/html.md)
- [Unit tests](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/unit-tests.md)
- [End-to-end tests](https://github.com/ngx-rocket/starter-kit/blob/master/docs/coding-guides/e2e-tests.md)

#### Other documentation

- [I18n guide](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/i18n.md)
- [Working behind a corporate proxy](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/corporate-proxy.md)
- [Updating dependencies and tools](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/updating.md)
- [Using a backend proxy for development](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/backend-proxy.md)
- [Browser routing](https://github.com/angular-starter-kit/ngx-starter-kit/blob/master/docs/routing.md)
- [I18n guide](https://github.com/ngx-rocket/starter-kit/blob/master/docs/i18n.md)
- [Working behind a corporate proxy](https://github.com/ngx-rocket/starter-kit/blob/master/docs/corporate-proxy.md)
- [Updating dependencies and tools](https://github.com/ngx-rocket/starter-kit/blob/master/docs/updating.md)
- [Using a backend proxy for development](https://github.com/ngx-rocket/starter-kit/blob/master/docs/backend-proxy.md)
- [Browser routing](https://github.com/ngx-rocket/starter-kit/blob/master/docs/routing.md)

# License

Expand Down
163 changes: 34 additions & 129 deletions generators/app/index.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
'use strict';

const _ = require('lodash');
const yosay = require('yosay');
const chalk = require('chalk');
const dir = require('node-dir');
const path = require('path');
const Insight = require('insight');
const Generator = require('yeoman-generator');
const Generator = require('@ngx-rocket/core');
const asciiLogo = require('@ngx-rocket/ascii-logo');

const options = require('./options.json');
const prompts = require('./prompts.json');
const pkg = require('../../package.json');

const excludeFiles = [
'.DS_Store',
'Thumbs.db'
];

const prefixRules = {
_mobile: (props) => props.target !== 'web',
_web: (props) => props.target !== 'mobile',
_bootstrap: (props) => props.ui === 'bootstrap',
_ionic: (props) => props.ui === 'ionic',
_auth: (props) => !!props.auth
};

module.exports = class extends Generator {

constructor(args, opts) {
super(args, opts);
class NgxGenerator extends Generator {

initializing() {
this.version = pkg.version;
this.insight = new Insight({ trackingCode: 'UA-93069862-1', pkg });

Expand All @@ -39,137 +21,48 @@ module.exports = class extends Generator {
required: false
});

// Use options from json
options.forEach((option) => {
this.option(option.name, {
type: global[option.type],
required: option.required,
desc: option.desc,
defaults: option.defaults
});
});
}

initializing() {
this.insight.optOut = !this.options['analytics'] || process.env.DISABLE_NGX_ANALYTICS;

// Updating
let fromVersion = null;

if (this.options['update']) {
this.props = this.config.get('props');
this.props = this.config.get('props') || {};
fromVersion = this.config.get('version');
}

if (this.props) {
let fromVersion = this.config.get('version');
if (fromVersion) {
if (fromVersion >= this.version) {
this.log(chalk.green('\nNothing to update, it\'s all good!\n'));
process.exit(0);
}

this.updating = true;
this.log(`\nUpdating ${chalk.green(this.props.appName)} project (${chalk.yellow(fromVersion)} -> ${chalk.yellow(this.version)})\n`);
this.log(`${chalk.yellow('Make sure you don\'t have uncommitted changes before overwriting files!')}`);
this.insight.track('generator', 'update', fromVersion, 'to', this.version);

} else if (!this.options['skip-welcome']) {
this.log(yosay(`${chalk.green('Welcome!')}\nLet\'s generate an awesome Angular app!`));
this.log(asciiLogo());
}

// Composition
const addonsOption = this.options['addons'];
const addons = addonsOption ? addonsOption.split(' ') : [];
addons.forEach(addon => this.composeWith(addon));

this.insight.track('generator', this.version);
this.insight.track('node', process.version);
this.insight.track('platform', process.platform);
this.insight.track('addons', addonsOption);
}

prompting() {
this.props = this.props || {};
let processProps = (props) => {
props.appName = this.props.appName || props.appName || this.options.appName;
props.projectName = _.kebabCase(props.appName);
_.extend(this.props, props);
};

if (this.options.automate) {
// Do no prompt, use json file instead
let props = require(path.resolve(this.options.automate));
processProps(props);
} else {
let namePrompt = _.find(prompts, { name: 'appName' });
namePrompt.default = this.appname;
namePrompt.when = () => !this.options.appName;
_.remove(prompts, (p) => this.props[p.name] !== undefined);

return this.prompt(prompts).then(processProps);
}
return super.prompting().then(() => this.shareProps(this.props));
}

preparing() {
return new Promise((resolve) => {
// TODO: update with chosen options
this.insight.track('generator', 'web', 'boostrap');

let filesPath = path.join(__dirname, 'templates');

dir.files(filesPath, (err, files) => {
if (err) throw err;

// Removes excluded files
_.remove(files, (file) => {
return !_.every(excludeFiles, (excludeFile) => {
return !_.includes(file, excludeFile);
});
});

this.files = _.map(files, (file) => {
let src = path.relative(filesPath, file);
let isTemplate = _.startsWith(path.basename(src), '_');
let hasFileCondition = _.startsWith(path.basename(src), '__');
let hasFolderCondition = _.startsWith(path.dirname(src), '_');
let dest = path.relative(hasFolderCondition ? path.dirname(src).split(path.sep)[0] : '.', src);

if (hasFileCondition) {
let fileName = path.basename(src).replace(/__.*?[.]/, '');
isTemplate = _.startsWith(fileName, '_');
dest = path.join(path.dirname(src), fileName);
}

if (isTemplate) {
dest = path.join(path.dirname(dest), path.basename(dest).slice(1));
}

return {
src: src,
dest: dest,
template: isTemplate,
hasFileCondition: hasFileCondition,
hasFolderCondition: hasFolderCondition
};
});

resolve();
});
});
}

writing() {
this.files.forEach((file) => {
let write = !file.hasFolderCondition || _.every(prefixRules, (rule, folder) => {
return !_.startsWith(path.dirname(file.src), folder) || rule(this.props);
});

write = write && (!file.hasFileCondition || _.every(prefixRules, (rule, prefix) => {
return !_.startsWith(path.basename(file.src), '_' + prefix) || rule(this.props);
}));

if (write) {
try {
if (file.template) {
this.fs.copyTpl(this.templatePath(file.src), this.destinationPath(file.dest), this);
} else {
this.fs.copy(this.templatePath(file.src), this.destinationPath(file.dest));
}
} catch (error) {
this.log(chalk.red(`\nTemplate processing error on file ${file.src}`));
throw error;
}
}
});
configuring() {
this.insight.track('generator', 'web', 'bootstrap');
}

install() {
Expand Down Expand Up @@ -199,6 +92,11 @@ module.exports = class extends Generator {
}

end() {
if (this.updating) {
this.log(`\nUpdated ${chalk.green(this.props.appName)} to ${chalk.yellow(this.version)} successfully!\n`);
return;
}

this.log('\nAll done! Get started with these tasks:');
this.log(`- $ ${chalk.green('npm start')}: start dev server with live reload on http://localhost:4200`);
this.log(`- $ ${chalk.green('npm run build')}: build app for production`);
Expand All @@ -208,4 +106,11 @@ module.exports = class extends Generator {
this.log(`- $ ${chalk.green('run docs')}: show docs and coding guides\n`);
}

};
}

module.exports = Generator.make({
baseDir: __dirname,
generator: NgxGenerator,
options: options,
prompts: prompts
});
14 changes: 7 additions & 7 deletions generators/app/options.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
[
{
"name": "skip-install",
"type": "Boolean",
"required": false,
"desc": "Skip npm install after project generation",
"defaults": false
},
{
"name": "skip-welcome",
"type": "Boolean",
Expand Down Expand Up @@ -33,5 +26,12 @@
"required": false,
"desc": "Automate prompt answers using the specified JSON file",
"defaults": ""
},
{
"name": "addons",
"type": "String",
"required": false,
"desc": "Use specified space-separated addons",
"defaults": ""
}
]
2 changes: 1 addition & 1 deletion generators/app/templates/_README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# <%= props.appName %>

This project was generated with [generator-ngx-app](https://github.com/angular-starter-kit/generator-ngx-app/)
This project was generated with [ngX-Rocket](https://github.com/ngx-rocket/generator-ngx-rocket/)
version <%= version %>

# Getting started
Expand Down
6 changes: 3 additions & 3 deletions generators/app/templates/e2e/_app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<% if (props.auth) { -%>
import { browser } from 'protractor';
<% } -%>
import { NgxStarterKitPage } from './app.po';
import { AppPage } from './app.po';

describe('app', () => {
let page: NgxStarterKitPage;
let page: AppPage;

beforeEach(() => {
page = new NgxStarterKitPage();
page = new AppPage();
});

<% if (props.auth) { -%>
Expand Down
3 changes: 2 additions & 1 deletion generators/app/templates/e2e/_app.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

import { browser, element, by } from 'protractor';

export class NgxStarterKitPage {
export class AppPage {
<% if (props.auth) { -%>
usernameField = element(by.css('[formControlName="username"]'));
passwordField = element(by.css('[formControlName="password"]'));
loginButton = element(by.css('button[type="submit"]'));

<% } -%>
navigateTo() {
return browser.get('/');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
aria-label="Toggle navigation" (click)="toggleMenu()" [attr.aria-expanded]="!menuHidden">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="https://github.com/angular-starter-kit" translate>APP_NAME</a>
<a class="navbar-brand" href="https://github.com/ngx-rocket" translate>APP_NAME</a>
<div id="navbar-menu" class="collapse navbar-collapse float-xs-none" [ngbCollapse]="menuHidden">
<div class="navbar-nav">
<a class="nav-item nav-link text-uppercase" routerLink="/home" routerLinkActive="active">
Expand Down
Loading