├── src
├── scaffold
│ ├── ssl
│ │ ├── router.js
│ │ └── server.js
│ ├── src
│ │ ├── app
│ │ │ ├── app.component.css
│ │ │ ├── app.component.scss
│ │ │ ├── app.component.html
│ │ │ ├── app.component.ts
│ │ │ ├── shared
│ │ │ │ └── components
│ │ │ │ │ ├── lazy
│ │ │ │ │ ├── lazy.component.html
│ │ │ │ │ ├── lazy.module.ts
│ │ │ │ │ ├── lazy.component.scss
│ │ │ │ │ ├── lazy.component.ts
│ │ │ │ │ └── lazy.component.css
│ │ │ │ │ └── home
│ │ │ │ │ ├── home.component.html
│ │ │ │ │ ├── home.module.ts
│ │ │ │ │ ├── home.component.scss
│ │ │ │ │ ├── home.component.ts
│ │ │ │ │ └── home.component.css
│ │ │ ├── app-routing.module.ts
│ │ │ └── app.module.ts
│ │ ├── style
│ │ │ ├── util
│ │ │ │ ├── _colors.scss
│ │ │ │ ├── _variables.scss
│ │ │ │ ├── _fonts.scss
│ │ │ │ ├── _mixins.scss
│ │ │ │ └── _normalize.scss
│ │ │ ├── style.scss
│ │ │ └── _app.scss
│ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ ├── assets
│ │ │ │ ├── angular.png
│ │ │ │ └── ng2-stealth.png
│ │ │ ├── system.import.js
│ │ │ ├── system.config.prod.js
│ │ │ ├── index.html
│ │ │ └── system.config.js
│ │ ├── tsconfig.jit.json
│ │ ├── tsconfig.dev.json
│ │ └── tsconfig.prod.json
│ ├── ivy
│ │ └── src
│ │ │ ├── app
│ │ │ ├── app.component.scss
│ │ │ ├── app.component.html
│ │ │ ├── app.module.ts
│ │ │ └── app.component.ts
│ │ │ ├── main.ts
│ │ │ ├── tsconfig.prod.json
│ │ │ ├── tsconfig.dev.json
│ │ │ └── public
│ │ │ ├── index.html
│ │ │ └── system.config.js
│ ├── lib
│ │ ├── index.ts
│ │ ├── src
│ │ │ └── components
│ │ │ │ └── default
│ │ │ │ ├── default.component.html
│ │ │ │ ├── default.component.css
│ │ │ │ ├── default.component.scss
│ │ │ │ ├── default.component.ts
│ │ │ │ └── default.module.ts
│ │ ├── config
│ │ │ ├── rollup.config.lib.js
│ │ │ ├── rollup.config.lib-es5.js
│ │ │ ├── rollup.config.lib-umd.js
│ │ │ ├── tsconfig.lib.es5.json
│ │ │ ├── tsconfig.lib.umd.json
│ │ │ ├── tsconfig.lib.fesm2015.json
│ │ │ ├── tsconfig.lib.esm5.json
│ │ │ └── tsconfig.lib.esm2015.json
│ │ ├── package.json
│ │ ├── tsconfig.lib.json
│ │ └── lib.config.json
│ ├── root
│ │ ├── README.md
│ │ ├── config
│ │ │ ├── server.config.prod.js
│ │ │ ├── server.config.dev.js
│ │ │ └── rollup.rxjs.js
│ │ ├── closure.externs.js
│ │ ├── postcss.config.js
│ │ ├── closure.rollup.conf
│ │ ├── .gitignore
│ │ ├── backend
│ │ │ ├── router.js
│ │ │ └── server.js
│ │ ├── rollup.config.js
│ │ ├── closure.conf
│ │ └── ngr.config.js
│ ├── pretty
│ │ ├── .prettierrc
│ │ └── tslint.json
│ └── standalone
│ │ ├── tsconfig.json
│ │ ├── protractor.config.js
│ │ ├── package.json
│ │ ├── karma-test-shim.js
│ │ └── karma.conf.js
├── generate
│ ├── index.js
│ └── lib.js
├── build
│ ├── index.js
│ ├── jit.js
│ ├── dev.js
│ ├── prod.js
│ └── lib.js
├── bundle
│ ├── rollup.js
│ └── closure.js
├── compile
│ ├── uglify.js
│ ├── babel.js
│ ├── tsc.js
│ └── ngc.js
├── config.js
├── style
│ ├── postcss.js
│ └── sass.js
├── watch.js
├── util.js
└── log.js
├── .gitignore
├── .editorconfig
├── package.json
├── index.js
└── README.md
/src/scaffold/ssl/router.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/app.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/src/style/util/_colors.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/src/style/util/_variables.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './src/components/default/default.module';
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | package-lock.json
4 | cli.config.json
5 | .idea
6 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello {{name}}
4 |
5 |
--------------------------------------------------------------------------------
/src/scaffold/lib/src/components/default/default.component.html:
--------------------------------------------------------------------------------
1 | A Bundled Component Is A Happy Component
2 |
--------------------------------------------------------------------------------
/src/scaffold/src/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveblue/angular2-rollup/HEAD/src/scaffold/src/public/favicon.ico
--------------------------------------------------------------------------------
/src/scaffold/src/public/assets/angular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveblue/angular2-rollup/HEAD/src/scaffold/src/public/assets/angular.png
--------------------------------------------------------------------------------
/src/scaffold/root/README.md:
--------------------------------------------------------------------------------
1 | # {{projectName}}
2 |
3 | This project was built with [angular-rollup](https://www.npmjs.com/package/angular-rollup).
4 |
--------------------------------------------------------------------------------
/src/scaffold/root/config/server.config.prod.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | origin: 'localhost',
3 | port: 4200
4 | };
5 |
6 | module.exports = config;
--------------------------------------------------------------------------------
/src/scaffold/src/public/assets/ng2-stealth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveblue/angular2-rollup/HEAD/src/scaffold/src/public/assets/ng2-stealth.png
--------------------------------------------------------------------------------
/src/scaffold/root/config/server.config.dev.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | origin: 'localhost',
3 | port: 4200
4 | };
5 |
6 | module.exports = config;
7 |
--------------------------------------------------------------------------------
/src/scaffold/lib/src/components/default/default.component.css:
--------------------------------------------------------------------------------
1 | :host {
2 | font-family: "Lato", sans-serif;
3 | background: red;
4 | color: white;
5 | padding: 20px;
6 | }
--------------------------------------------------------------------------------
/src/scaffold/lib/src/components/default/default.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | font-family: "Lato", sans-serif;
3 | background: red;
4 | color: white;
5 | padding: 20px;
6 | }
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/main.ts:
--------------------------------------------------------------------------------
1 | import { ɵrenderComponent as renderComponent } from '@angular/core';
2 | import { AppComponent } from './app/app.component';
3 |
4 | renderComponent(AppComponent);
--------------------------------------------------------------------------------
/src/scaffold/pretty/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "useTabs": false,
5 | "tabWidth": 2,
6 | "semi": true,
7 | "bracketSpacing": true
8 | }
9 |
--------------------------------------------------------------------------------
/src/scaffold/src/public/system.import.js:
--------------------------------------------------------------------------------
1 | System.import('system.config.prod.js').then(function () {
2 | Promise.all([
3 | System.import('bundle')
4 | ]);
5 | }).catch(console.error.bind(console));
6 |
--------------------------------------------------------------------------------
/src/scaffold/src/style/style.scss:
--------------------------------------------------------------------------------
1 | // Authored Dependencies
2 | @import "util/variables";
3 | @import "util/colors";
4 | @import "util/fonts";
5 | @import "util/mixins";
6 |
7 | // Application Styles
8 | @import "app";
9 |
--------------------------------------------------------------------------------
/src/scaffold/root/closure.externs.js:
--------------------------------------------------------------------------------
1 | /** @externs */
2 |
3 | var System = function(){};
4 | var Hammer = function(){};
5 | var global = function(){};
6 | var COMPILED = function(){};
7 | var ngDevMode = function(){};
8 | var process = function(){};
--------------------------------------------------------------------------------
/src/scaffold/src/style/util/_fonts.scss:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
4 | font-weight:400;
5 | }
6 |
--------------------------------------------------------------------------------
/src/scaffold/root/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = ctx => ({
2 | plugins: {
3 | 'postcss-discard-comments': ctx.env === 'prod' ? {} : false,
4 | 'autoprefixer': { remove: false },
5 | 'postcss-csso': ctx.env === 'prod' ? {} : false
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: 'app.component.html',
6 | styleUrls: ['app.component.css']
7 | })
8 | export class AppComponent {
9 | constructor() {}
10 | }
11 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./../out-tsc",
5 | "module": "es2015"
6 | },
7 | "angularCompilerOptions": {
8 | "enableIvy": true
9 | },
10 | "include": [
11 | "./../src/**/*.ts"
12 | ]
13 | }
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 |
3 | import { AppComponent } from './app.component';
4 |
5 | @NgModule({
6 | declarations: [
7 | AppComponent
8 | ],
9 | imports: [],
10 | providers: [],
11 | bootstrap: [AppComponent]
12 | })
13 | export class AppModule { }
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: 'app.component.html',
6 | styleUrls: ['app.component.css']
7 | })
8 | export class AppComponent {
9 | public name: string = 'Ivy!';
10 | constructor() {}
11 | }
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | charset = utf-8
9 | indent_style = space
10 | indent_size = 2
11 | end_of_line = lf
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/src/scaffold/src/public/system.config.prod.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 | System.defaultJSExtensions = true;
3 | System.config({
4 | 'map': {
5 | 'bundle': 'bundle.js',
6 | 'vendor': 'vendor.js'
7 | },
8 | 'meta': {
9 | 'bundle': {
10 | deps: []
11 | }
12 | }
13 | });
14 | })(this);
15 |
16 |
--------------------------------------------------------------------------------
/src/generate/index.js:
--------------------------------------------------------------------------------
1 | const cli = require('./../../cli.config.json');
2 | const config = require('./../config');
3 |
4 | class Generator {
5 |
6 | constructor() {
7 | this.outputPath = config.processRoot;
8 | this.name = process.argv[process.argv.indexOf(cli.program.generate) + 1];
9 | }
10 | }
11 |
12 | module.exports = Generator;
--------------------------------------------------------------------------------
/src/scaffold/lib/src/components/default/default.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'default',
5 | templateUrl: 'default.component.html',
6 | styleUrls: ['default.component.css']
7 | })
8 |
9 | export class DefaultComponent {
10 |
11 |
12 | constructor() {
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/scaffold/lib/config/rollup.config.lib.js:
--------------------------------------------------------------------------------
1 | // rollup.config.lib.js
2 |
3 | export default {
4 | input: 'out-tsc/es2015/{{folderName}}.js',
5 | output: {
6 | file: 'dist/{{projectName}}/fesm2015/{{folderName}}.js',
7 | format: 'es',
8 | sourcemap: false
9 | },
10 | onwarn: function ( message ) {
11 |
12 | return;
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/lazy/lazy.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/lib/config/rollup.config.lib-es5.js:
--------------------------------------------------------------------------------
1 | // rollup.config.lib-es5.js
2 |
3 | export default {
4 | input: 'out-tsc/es5/{{folderName}}.js',
5 | output: {
6 | file: 'dist/{{projectName}}/fesm5/{{folderName}}.js',
7 | format: 'es',
8 | sourcemap: true
9 | },
10 | onwarn: function ( message ) {
11 |
12 | return;
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/scaffold/lib/config/rollup.config.lib-umd.js:
--------------------------------------------------------------------------------
1 | // rollup.config.lib-umd.js
2 |
3 | export default {
4 | input: 'out-tsc/es5/{{folderName}}.js',
5 | output: {
6 | file: 'dist/{{projectName}}/bundles/{{folderName}}.umd.js',
7 | format: 'cjs',
8 | sourcemap: true
9 | },
10 | onwarn: function ( message ) {
11 |
12 | return;
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/home/home.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/tsconfig.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../tsconfig.json",
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "outDir": "./../dist/{{projectName}}",
6 | "target": "es5",
7 | "module": "commonjs"
8 | },
9 | "angularCompilerOptions": {
10 | "enableIvy": true
11 | },
12 | "include": [
13 | "./../src/**/*.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/scaffold/src/tsconfig.jit.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../tsconfig.json",
3 | "compileOnSave": false,
4 | "buildOnSave": false,
5 | "compilerOptions": {
6 | "outDir": "./../dist/{{projectName}}/src",
7 | "target": "es5",
8 | "module": "commonjs",
9 | "noImplicitAny": false,
10 | "removeComments": false
11 | },
12 | "include": [
13 | "./../src/**/*.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/src/scaffold/src/tsconfig.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../tsconfig.json",
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "outDir": "./../dist/{{projectName}}",
6 | "target": "es5",
7 | "module": "commonjs",
8 | "noImplicitAny": false
9 | },
10 | "angularCompilerOptions": {
11 | "skipMetadataEmit": true
12 | },
13 | "include": [
14 | "./../src/**/*.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/src/scaffold/lib/src/components/default/default.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { DefaultComponent } from './default.component';
4 |
5 | export * from './default.component';
6 |
7 | @NgModule({
8 | imports: [ CommonModule ],
9 | declarations: [ DefaultComponent ],
10 | exports: [ DefaultComponent ]
11 | })
12 |
13 | export class DefaultModule {}
14 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/home/home.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 | import { CommonModule } from '@angular/common';
4 |
5 | import { HomeComponent } from './home.component';
6 |
7 | @NgModule({
8 | imports: [ RouterModule,
9 | CommonModule ],
10 | declarations: [ HomeComponent ],
11 | exports: [ HomeComponent ]
12 | })
13 |
14 | export class HomeModule {}
15 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/lazy/lazy.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 | import { CommonModule } from '@angular/common';
4 |
5 | import { LazyComponent } from './lazy.component';
6 |
7 | @NgModule({
8 | imports: [ RouterModule,
9 | CommonModule ],
10 | declarations: [ LazyComponent ],
11 | exports: [ LazyComponent ]
12 | })
13 |
14 | export class LazyModule {}
15 |
--------------------------------------------------------------------------------
/src/scaffold/lib/config/tsconfig.lib.es5.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.lib.json",
3 | "compilerOptions": {
4 | "outDir": "{{relativePath}}out-tsc/es5",
5 | "module": "es2015",
6 | "target": "es5"
7 | },
8 | "angularCompilerOptions": {
9 | "strictMetadataEmit": true,
10 | "skipTemplateCodegen": true,
11 | "annotateForClosureCompiler": true,
12 | "flatModuleOutFile": "{{folderName}}.js",
13 | "flatModuleId": "{{projectName}}"
14 | }
15 | }
--------------------------------------------------------------------------------
/src/scaffold/lib/config/tsconfig.lib.umd.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.lib.json",
3 | "compilerOptions": {
4 | "outDir": "{{relativePath}}out-tsc/es5",
5 | "module": "es2015",
6 | "target": "es5"
7 | },
8 | "angularCompilerOptions": {
9 | "strictMetadataEmit": true,
10 | "skipTemplateCodegen": true,
11 | "annotateForClosureCompiler": true,
12 | "flatModuleOutFile": "{{folderName}}.js",
13 | "flatModuleId": "{{projectName}}"
14 | }
15 | }
--------------------------------------------------------------------------------
/src/scaffold/lib/config/tsconfig.lib.fesm2015.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.lib.json",
3 | "compilerOptions": {
4 | "outDir": "{{relativePath}}out-tsc/es2015",
5 | "target": "es2015",
6 | "module": "es2015"
7 | },
8 | "angularCompilerOptions": {
9 | "strictMetadataEmit": true,
10 | "skipTemplateCodegen": true,
11 | "annotateForClosureCompiler": true,
12 | "flatModuleOutFile": "{{folderName}}.js",
13 | "flatModuleId": "{{projectName}}"
14 | }
15 | }
--------------------------------------------------------------------------------
/src/scaffold/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { ModuleWithProviders } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { HomeComponent } from './shared/components/home/home.component';
5 | import { LazyComponent } from './shared/components/lazy/lazy.component';
6 |
7 | const routes: Routes = [
8 | { path: '', component: HomeComponent },
9 | { path: 'lazy', component: LazyComponent }
10 | ];
11 |
12 | export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
13 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/lazy/lazy.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | position: absolute;
3 | width: 100%;
4 | height: 100%;
5 | background: red;
6 | }
7 |
8 | .is--center {
9 | width: 256px;
10 | height: 256px;
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | transform: translateX(-50%) translateY(-50%);
15 | perspective: 1000px;
16 | .app__icon {
17 | width: 100%;
18 | height: 100%;
19 | img {
20 | width: 100%;
21 | height: 100%;
22 | }
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/home/home.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | height: 100%;
4 | background: black;
5 | }
6 |
7 | .is--center {
8 | width: 256px;
9 | height: 256px;
10 | position: absolute;
11 | top: 50%;
12 | left: 50%;
13 | transform: translateX(-50%) translateY(-50%);
14 | perspective: 1000px;
15 | .app__icon {
16 | width: 100%;
17 | height: 100%;
18 | img {
19 | width: 100%;
20 | height: 100%;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/scaffold/standalone/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "emitDecoratorMetadata": true,
4 | "experimentalDecorators": true,
5 | "moduleResolution": "node",
6 | "declaration": false,
7 | "sourceMap": true,
8 | "typeRoots": [
9 | "node_modules/@types"
10 | ],
11 | "types": [
12 | "node",
13 | "jasmine",
14 | "karma"
15 | ],
16 | "lib": [
17 | "es2017",
18 | "dom"
19 | ]
20 | }
21 | }
--------------------------------------------------------------------------------
/src/scaffold/lib/config/tsconfig.lib.esm5.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.lib.json",
3 | "compilerOptions": {
4 | "outDir": "{{relativePath}}out-tsc/esm5",
5 | "module": "es2015",
6 | "target": "es5"
7 | },
8 | "angularCompilerOptions": {
9 | "strictMetadataEmit": true,
10 | "skipTemplateCodegen": true,
11 | "annotateForClosureCompiler": true,
12 | "flatModuleOutFile": "{{folderName}}.js",
13 | "flatModuleId": "{{projectName}}"
14 | },
15 | "files": [
16 | "{{relativePath}}tmp/index.ts"
17 | ]
18 | }
--------------------------------------------------------------------------------
/src/scaffold/root/closure.rollup.conf:
--------------------------------------------------------------------------------
1 | --compilation_level=ADVANCED_OPTIMIZATIONS
2 | --language_in=ECMASCRIPT6
3 | --language_out=ECMASCRIPT5
4 | --variable_renaming_report=closure/variable_renaming_report
5 | --property_renaming_report=closure/property_renaming_report
6 | --create_source_map=%outname%.map
7 |
8 | --warning_level=QUIET
9 | --dependency_mode=STRICT
10 | --rewrite_polyfills=false
11 |
12 | --externs closure.externs.js
13 | --externs node_modules/zone.js/dist/zone_externs.js
14 |
15 | --js dist/{{projectName}}/bundle.es2015.js
16 |
17 | --entry_point=./dist/{{projectName}}/bundle.es2015.js
--------------------------------------------------------------------------------
/src/scaffold/lib/config/tsconfig.lib.esm2015.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.lib.json",
3 | "compilerOptions": {
4 | "outDir": "{{relativePath}}out-tsc/esm2015",
5 | "module": "es2015",
6 | "target": "es2015"
7 | },
8 | "angularCompilerOptions": {
9 | "strictMetadataEmit": true,
10 | "skipTemplateCodegen": true,
11 | "annotateForClosureCompiler": true,
12 | "flatModuleOutFile": "{{folderName}}.js",
13 | "flatModuleId": "{{projectName}}"
14 | },
15 | "files": [
16 | "{{relativePath}}tmp/index.ts"
17 | ]
18 | }
--------------------------------------------------------------------------------
/src/scaffold/src/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./../out-tsc",
5 | "target": "es2015",
6 | "module": "es2015",
7 | "stripInternal": true,
8 | "inlineSources": true,
9 | "skipLibCheck": true,
10 | "allowSyntheticDefaultImports": true,
11 | "noImplicitAny": false,
12 | "removeComments": true,
13 | "allowUnreachableCode": false
14 | },
15 | "angularCompilerOptions": {
16 | "annotationsAs": "static fields",
17 | "annotateForClosureCompiler": true,
18 | "skipMetadataEmit": false
19 | },
20 | "include": [
21 | "./../src/**/*.ts"
22 | ]
23 | }
--------------------------------------------------------------------------------
/src/scaffold/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{projectName}}",
3 | "version": "1.0.0",
4 | "description": "",
5 | "license": "MIT",
6 | "module": "./esm5/{{folderName}}.js",
7 | "es2015": "./fesm2015/{{folderName}}.js",
8 | "esm5": "./esm5/{{folderName}}.js",
9 | "esm2015": "./esm2015/{{folderName}}.js",
10 | "fesm5": "./fesm5/{{folderName}}.js",
11 | "fesm2015": "./fesm2015/{{folderName}}.js",
12 | "main": "./bundles/{{folderName}}.umd.js",
13 | "typings": "{{folderName}}.d.ts",
14 | "devDependencies": {
15 | "@angular/core": "^6.0.0",
16 | "@angular/compiler": "^6.0.0",
17 | "@angular/compiler-cli": "^6.0.0",
18 | "rollup": "^0.55.0",
19 | "rxjs": "^6.0.0",
20 | "typescript": "^2.7.2",
21 | "zone.js": "^0.8.26"
22 | }
23 | }
--------------------------------------------------------------------------------
/src/scaffold/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { BrowserModule } from '@angular/platform-browser';
4 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
5 | import { AppComponent } from './app.component';
6 | import { routing } from './app-routing.module';
7 | import { HomeModule } from './shared/components/home/home.module';
8 | import { LazyModule } from './shared/components/lazy/lazy.module';
9 |
10 | @NgModule({
11 | imports: [BrowserModule,
12 | BrowserAnimationsModule,
13 | CommonModule,
14 | HomeModule,
15 | LazyModule,
16 | routing],
17 | declarations: [AppComponent],
18 | bootstrap: [AppComponent]
19 | })
20 | export class AppModule {}
21 |
--------------------------------------------------------------------------------
/src/scaffold/lib/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "{{relativePath}}tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": "./src",
5 | "rootDir": "./{{relativePath}}tmp",
6 | "sourceMap": false,
7 | "declaration": true,
8 | "stripInternal": true,
9 | "allowSyntheticDefaultImports": true,
10 | "noImplicitAny": false,
11 | "removeComments": true,
12 | "allowUnreachableCode": false,
13 | "skipLibCheck": true
14 | },
15 | "angularCompilerOptions": {
16 | "strictMetadataEmit": true,
17 | "skipTemplateCodegen": true,
18 | "annotateForClosureCompiler": true,
19 | "flatModuleOutFile": "{{folderName}}.js",
20 | "flatModuleId": "{{projectName}}"
21 | },
22 | "files": [
23 | "./{{relativePath}}tmp/index.ts"
24 | ]
25 | }
--------------------------------------------------------------------------------
/src/scaffold/standalone/protractor.config.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | 'build/src/app/**/*.e2e-spec.js'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function () { }
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: 'tsconfig.jit.json'
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/src/scaffold/root/config/rollup.rxjs.js:
--------------------------------------------------------------------------------
1 | export default [{
2 | input: 'node_modules/rxjs/_esm2015/index.js',
3 | output: {
4 | file: 'node_modules/rxjs/_fesm2015/index.js',
5 | format: 'es'
6 | }
7 | },
8 | {
9 | input: 'node_modules/rxjs/_esm2015/operators/index.js',
10 | output: {
11 | file: 'node_modules/rxjs/_fesm2015/operators/index.js',
12 | format: 'es'
13 | }
14 | },
15 | {
16 | input: 'node_modules/rxjs/_esm2015/ajax/index.js',
17 | output: {
18 | file: 'node_modules/rxjs/_fesm2015/ajax/index.js',
19 | format: 'es'
20 | }
21 | },
22 | {
23 | input: 'node_modules/rxjs/_esm2015/testing/index.js',
24 | output: {
25 | file: 'node_modules/rxjs/_fesm2015/testing/index.js',
26 | format: 'es'
27 | }
28 | },
29 | {
30 | input: 'node_modules/rxjs/_esm2015/websocket/index.js',
31 | output: {
32 | file: 'node_modules/rxjs/_fesm2015/websocket/index.js',
33 | format: 'es'
34 | }
35 | }
36 | ];
--------------------------------------------------------------------------------
/src/scaffold/lib/lib.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": "{{projectPath}}",
3 | "dist": "dist/{{projectName}}",
4 | "filename": "{{folderName}}",
5 | "es2015": {
6 | "tsConfig": "tsconfig.lib.fesm2015.json",
7 | "rollupConfig": "rollup.config.lib.js",
8 | "outFile": "dist/{{projectName}}/fesm2015/{{folderName}}.js"
9 | },
10 | "es5": {
11 | "tsConfig": "tsconfig.lib.es5.json",
12 | "rollupConfig": "rollup.config.lib-es5.js",
13 | "outFile": "dist/{{projectName}}/fesm5/{{folderName}}.js"
14 | },
15 | "umd": {
16 | "tsConfig": "tsconfig.lib.umd.json",
17 | "rollupConfig": "rollup.config.lib-umd.js",
18 | "outFile": "dist/{{projectName}}/bundles/{{folderName}}.umd.js"
19 | },
20 | "esm5": {
21 | "tsConfig": "tsconfig.lib.esm5.json",
22 | "outFile": "dist/{{projectName}}/esm5/{{folderName}}.js"
23 | },
24 | "esm2015": {
25 | "tsConfig": "tsconfig.lib.esm2015.json",
26 | "outFile": "dist/{{projectName}}/esm2015/{{folderName}}.js"
27 | }
28 | }
--------------------------------------------------------------------------------
/src/build/index.js:
--------------------------------------------------------------------------------
1 | const EventEmitter = require('events');
2 | const moment = require('moment');
3 | const colors = require('colors');
4 | const log = require('./../log.js');
5 | const cli = require('./../../cli.config.json');
6 | const config = require('./../config');
7 | const path = require('path');
8 |
9 | class BuildEmitter extends EventEmitter {}
10 |
11 | class Build {
12 | constructor() {
13 |
14 | if (!config.projects) {
15 | log.break();
16 | log.error('NGR ERROR: ngr >= 2.0.0 requires projects schema in ngr.config.js');
17 | log.break();
18 | }
19 | this.outputPath = config.projects[config.project].architect.build.options.outputPath;
20 | this.startTime = moment(new Date());
21 | this.emitter = new BuildEmitter();
22 |
23 | if (!cli.program.webpack) {
24 | const args = cli.program.rawArgs.filter((str) => {
25 | return !str.includes('node');
26 | });
27 | // .map((str) => {
28 | // return path.basename(str);
29 | // });
30 | log.process('ngr ' + args.join(' '));
31 |
32 | }
33 | }
34 | }
35 |
36 | module.exports = Build;
37 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{projectName}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
34 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/scaffold/root/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Users Environment Variables
23 | .lock-wscript
24 |
25 | # OS generated files
26 | .DS_Store
27 | ehthumbs.db
28 | Icon?
29 | Thumbs.db
30 |
31 | # Node Files
32 | /node_modules
33 | /bower_components
34 |
35 | # Coverage
36 | /coverage/
37 |
38 | # Typing
39 | /src/typings/tsd/
40 | /typings/
41 | /tsd_typings/
42 |
43 | # Src
44 | .tmp
45 | /tmp
46 | /out-tsc
47 | /out-css
48 | /closure
49 | compiler.jar
50 | main.js
51 | main.js.map
52 | src/app/**/*.css
53 | src/app/app.component.css
54 |
55 | # Dist
56 | /build
57 | /closure
58 | /dist
59 |
60 | # Doc
61 | /doc
62 |
63 | # Tests
64 |
65 | _test-output/
66 |
67 | # IDE
68 | .idea/
69 | *.swp
70 | .vscode
71 | documentation/
72 |
73 |
--------------------------------------------------------------------------------
/src/bundle/rollup.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const exec = require('child_process').exec;
3 | const config = require('./../config');
4 | const log = require('./../log.js');
5 |
6 |
7 | class RollupBuilder {
8 |
9 | constructor() {
10 | this.isBundling = false;
11 | }
12 |
13 | bundle(rollupConfigPath) {
14 |
15 | return new Promise((res, rej) => {
16 |
17 | log.process('rollup');
18 | this.isBundling = true;
19 |
20 | exec(path.normalize(config.projectRoot + '/node_modules/.bin/rollup') +
21 | ' -c ' + rollupConfigPath, {silent: true}, (error, stdout, stderr) => {
22 | log.stop('rollup');
23 | if (stderr.includes('Error')) {
24 | if (rej) rej(error);
25 | this.isBundling = false;
26 | log.error(stderr);
27 |
28 | } else {
29 | this.isBundling = false;
30 | log.message(stderr);
31 | res();
32 | }
33 |
34 | });
35 | })
36 | }
37 |
38 | }
39 |
40 |
41 | module.exports = RollupBuilder;
--------------------------------------------------------------------------------
/src/scaffold/root/backend/router.js:
--------------------------------------------------------------------------------
1 | // router.js
2 |
3 | const express = require('express');
4 | const router = require('express').Router();
5 | const compression = require('compression');
6 | const config = require(process.cwd()+'/angular.json');
7 |
8 |
9 | module.exports = function(app) {
10 | 'use strict';
11 | let projectRoot = config.projects[config.defaultProject].architect.build.options.outputPath;
12 | // ROUTER CONFIG
13 |
14 |
15 | app.use(function(req, res, next) {
16 |
17 | // CAUTION: Wide open CORS!
18 | res.header('Access-Control-Allow-Origin', req.headers.origin);
19 | res.header('Access-Control-Allow-Credentials', 'true');
20 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
21 | res.header('Access-Control-Allow-Headers', 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type');
22 |
23 | if (req.method == 'OPTIONS' ) {
24 | res.send(200);
25 | }
26 | else {
27 | next();
28 | }
29 |
30 | });
31 |
32 |
33 | // ROUTES
34 |
35 | app.use(compression());
36 |
37 | app.use('/', express.static( process.cwd() + '/' + projectRoot ));
38 |
39 |
40 | app.get('*', function (req, res) {
41 | res.sendFile('index.html', { root: process.cwd() + '/' + projectRoot });
42 | });
43 |
44 |
45 |
46 | return router;
47 |
48 | };
49 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnDestroy } from '@angular/core';
2 | import { trigger, state, style, transition, animate } from '@angular/animations';
3 |
4 | @Component({
5 | selector: 'app-home',
6 | templateUrl: 'home.component.html',
7 | styleUrls: ['home.component.css'],
8 | animations: [
9 | trigger('intro', [
10 | state('void', style({
11 | opacity: '0.0',
12 | transform: 'translateZ(-1000px)'
13 | })),
14 | state('active', style({
15 | opacity: '1.0',
16 | transform: 'translateZ(0px)',
17 | perspective: '1000px'
18 | })),
19 | state('inactive', style({
20 | opacity: '0.0',
21 | transform: 'translateZ(-1000px)',
22 | perspective: '1000px'
23 | })),
24 | transition('active => void', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
25 | transition('void => active', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
26 | transition('inactive => active', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
27 | transition('active => inactive', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)'))
28 | ])
29 | ]
30 | })
31 |
32 | export class HomeComponent implements OnDestroy {
33 |
34 | stealthMode: string;
35 |
36 | constructor() {
37 |
38 | this.stealthMode = 'active';
39 |
40 | }
41 |
42 | ngOnDestroy() {
43 |
44 | this.stealthMode = 'inactive';
45 |
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/lazy/lazy.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnDestroy } from '@angular/core';
2 | import { trigger, state, style, transition, animate } from '@angular/animations';
3 |
4 | @Component({
5 | selector: 'app-lazy',
6 | templateUrl: 'lazy.component.html',
7 | styleUrls: ['lazy.component.css'],
8 | animations: [
9 | trigger('intro', [
10 | state('void', style({
11 | opacity: '0.0',
12 | transform: 'translateZ(-1000px)'
13 | })),
14 | state('active', style({
15 | opacity: '1.0',
16 | transform: 'translateZ(0px)',
17 | perspective: '1000px'
18 | })),
19 | state('inactive', style({
20 | opacity: '0.0',
21 | transform: 'translateZ(-1000px)',
22 | perspective: '1000px'
23 | })),
24 | transition('active => void', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
25 | transition('void => active', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
26 | transition('inactive => active', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)')),
27 | transition('active => inactive', animate('5000ms cubic-bezier(0.19, 1, 0.22, 1)'))
28 | ])
29 | ]
30 | })
31 |
32 | export class LazyComponent implements OnDestroy {
33 |
34 | angularMode: string;
35 |
36 | constructor() {
37 |
38 | this.angularMode = 'active';
39 |
40 | }
41 |
42 | ngOnDestroy() {
43 |
44 | this.angularMode = 'inactive';
45 |
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/compile/uglify.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const UglifyJS = require('uglify-js');
4 | const config = require('./../config');
5 | const log = require('./../log.js');
6 |
7 | class UglifyBuilder {
8 |
9 | constructor() { }
10 |
11 | optimize() {
12 |
13 | return new Promise((res, rej) => {
14 |
15 | log.process('uglify');
16 |
17 | let outputPath = config.projects[config.project].architect.build.options.outputPath;
18 |
19 | exec(path.normalize(config.projectRoot + '/node_modules/.bin/uglifyjs') +
20 | ' ' + path.join(outputPath, 'bundle.js') + ' -o ' + path.join(outputPath, 'bundle.js')+' ---compress --mangle --toplevel --verbose', { silent: true }, (error, stdout, stderr) => {
21 | log.stop('uglify');
22 | if (stderr.includes('Error')) {
23 | if (rej) rej(error);
24 | log.error(stderr);
25 |
26 | } else {
27 | log.message(stderr);
28 | res();
29 | }
30 |
31 | });
32 | })
33 | }
34 |
35 | minify(filePath) {
36 | fs.readFile(filePath, 'utf-8', (err, contents) => {
37 | let result = UglifyJS.minify(contents, { toplevel: true, mangle: true, compress: true });
38 | return fs.writeFileSync(filePath, result.code);
39 | });
40 | }
41 |
42 | }
43 |
44 |
45 | module.exports = UglifyBuilder;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-rollup",
3 | "version": "2.0.5",
4 | "description": "cli for building angular with closure compiler and rollup",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/steveblue/angular2-rollup.git"
12 | },
13 | "keywords": [
14 | "angular",
15 | "javascript",
16 | "framework",
17 | "cli"
18 | ],
19 | "author": "Steve Belovarich",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/steveblue/angular2-rollup/issues"
23 | },
24 | "homepage": "https://github.com/steveblue/angular2-rollup#readme",
25 | "dependencies": {
26 | "@angular-devkit/build-optimizer": "^0.6.8",
27 | "async": "^2.6.0",
28 | "chokidar": "^2.0.2",
29 | "colors": "^1.1.2",
30 | "commander": "^2.14.1",
31 | "detect-installed": "^2.0.4",
32 | "findup": "^0.1.5",
33 | "gzip-size": "^4.1.0",
34 | "html-minifier": "^3.5.11",
35 | "htmlprocessor": "^0.2.6",
36 | "js-string-escape": "^1.0.1",
37 | "magic-string": "^0.23.2",
38 | "moment": "^2.21.0",
39 | "node-sass": "^4.13.1",
40 | "ora": "^2.1.0",
41 | "prettier": "^1.14.2",
42 | "shelljs": "^0.8.1",
43 | "single-line-log": "^1.1.2",
44 | "uglify-js": "^3.4.0",
45 | "uuid": "^3.2.1"
46 | },
47 | "bin": {
48 | "ngr": "index.js"
49 | },
50 | "engines": {
51 | "node": ">8.0.0"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/scaffold/root/rollup.config.js:
--------------------------------------------------------------------------------
1 | // rollup.config.js
2 |
3 | import nodeResolve from 'rollup-plugin-node-resolve';
4 |
5 | class ResolveRxjs {
6 |
7 | resolveId(importee, importer) {
8 | if (importee.startsWith('rxjs')) {
9 | let pkg = importee.replace('rxjs', '');
10 | if (importee.includes('/')) {
11 | return `node_modules/rxjs/_fesm2015${pkg}/index.js`;
12 | } else {
13 | return `node_modules/rxjs/_fesm2015/${pkg}index.js`;
14 | }
15 | }
16 | }
17 | }
18 |
19 |
20 | class ResolveAngular {
21 |
22 | resolveId(importee, importer) {
23 | if (importee.startsWith('@angular')) {
24 | let pkg = importee.replace('@angular', '');
25 | if (importee.split('/').length > 2) {
26 | return `node_modules/${importee.split('/')[0]}/${importee.split('/')[1]}/fesm2015/${importee.split('/')[2]}.js`;
27 | } else {
28 | return `node_modules/${importee}/fesm2015${pkg}.js`;
29 | }
30 | }
31 | }
32 | }
33 |
34 |
35 | export default {
36 | input: 'out-tsc/src/main.js',
37 | treeshake: true,
38 | output: {
39 | file: 'dist/{{projectName}}/bundle.es2015.js',
40 | format: 'iife'
41 | },
42 | plugins: [
43 | new ResolveRxjs(),
44 | new ResolveAngular(),
45 | nodeResolve({
46 | mainFields: ['module', 'jsnext']
47 | })
48 | ],
49 | onwarn: function (message) {
50 |
51 | console.log(message);
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/home/home.component.css:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | height: 100%;
4 | background: black;
5 | }
6 |
7 | .is--center {
8 | width: 256px;
9 | height: 256px;
10 | position: absolute;
11 | top: 50%;
12 | left: 50%;
13 | -webkit-transform: translateX(-50%) translateY(-50%);
14 | transform: translateX(-50%) translateY(-50%);
15 | -webkit-perspective: 1000px;
16 | perspective: 1000px;
17 | }
18 |
19 | .is--center .app__icon {
20 | width: 100%;
21 | height: 100%;
22 | }
23 |
24 | .is--center .app__icon img {
25 | width: 100%;
26 | height: 100%;
27 | }
28 |
29 | /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImhvbWUuY29tcG9uZW50LmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFlBQVk7RUFDWixhQUFhO0VBQ2Isa0JBQWtCO0NBQ25COztBQUVEO0VBQ0UsYUFBYTtFQUNiLGNBQWM7RUFDZCxtQkFBbUI7RUFDbkIsU0FBUztFQUNULFVBQVU7RUFDVixxREFBNkM7VUFBN0MsNkNBQTZDO0VBQzdDLDRCQUFvQjtVQUFwQixvQkFBb0I7Q0FDckI7O0FBRUQ7RUFDRSxZQUFZO0VBQ1osYUFBYTtDQUNkOztBQUVEO0VBQ0UsWUFBWTtFQUNaLGFBQWE7Q0FDZCIsImZpbGUiOiJob21lLmNvbXBvbmVudC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIGJhY2tncm91bmQ6IGJsYWNrO1xufVxuXG4uaXMtLWNlbnRlciB7XG4gIHdpZHRoOiAyNTZweDtcbiAgaGVpZ2h0OiAyNTZweDtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDUwJTtcbiAgbGVmdDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSkgdHJhbnNsYXRlWSgtNTAlKTtcbiAgcGVyc3BlY3RpdmU6IDEwMDBweDtcbn1cblxuLmlzLS1jZW50ZXIgLmFwcF9faWNvbiB7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG59XG5cbi5pcy0tY2VudGVyIC5hcHBfX2ljb24gaW1nIHtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcbn1cbiJdfQ== */
--------------------------------------------------------------------------------
/src/scaffold/src/app/shared/components/lazy/lazy.component.css:
--------------------------------------------------------------------------------
1 | :host {
2 | position: absolute;
3 | width: 100%;
4 | height: 100%;
5 | background: red;
6 | }
7 |
8 | .is--center {
9 | width: 256px;
10 | height: 256px;
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | -webkit-transform: translateX(-50%) translateY(-50%);
15 | transform: translateX(-50%) translateY(-50%);
16 | -webkit-perspective: 1000px;
17 | perspective: 1000px;
18 | }
19 |
20 | .is--center .app__icon {
21 | width: 100%;
22 | height: 100%;
23 | }
24 |
25 | .is--center .app__icon img {
26 | width: 100%;
27 | height: 100%;
28 | }
29 |
30 | /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxhenkuY29tcG9uZW50LmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLG1CQUFtQjtFQUNuQixZQUFZO0VBQ1osYUFBYTtFQUNiLGdCQUFnQjtDQUNqQjs7QUFFRDtFQUNFLGFBQWE7RUFDYixjQUFjO0VBQ2QsbUJBQW1CO0VBQ25CLFNBQVM7RUFDVCxVQUFVO0VBQ1YscURBQTZDO1VBQTdDLDZDQUE2QztFQUM3Qyw0QkFBb0I7VUFBcEIsb0JBQW9CO0NBQ3JCOztBQUVEO0VBQ0UsWUFBWTtFQUNaLGFBQWE7Q0FDZDs7QUFFRDtFQUNFLFlBQVk7RUFDWixhQUFhO0NBQ2QiLCJmaWxlIjoibGF6eS5jb21wb25lbnQuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIGJhY2tncm91bmQ6IHJlZDtcbn1cblxuLmlzLS1jZW50ZXIge1xuICB3aWR0aDogMjU2cHg7XG4gIGhlaWdodDogMjU2cHg7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiA1MCU7XG4gIGxlZnQ6IDUwJTtcbiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpIHRyYW5zbGF0ZVkoLTUwJSk7XG4gIHBlcnNwZWN0aXZlOiAxMDAwcHg7XG59XG5cbi5pcy0tY2VudGVyIC5hcHBfX2ljb24ge1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4uaXMtLWNlbnRlciAuYXBwX19pY29uIGltZyB7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG59XG4iXX0= */
--------------------------------------------------------------------------------
/src/scaffold/src/style/_app.scss:
--------------------------------------------------------------------------------
1 | body {
2 | background: #000000;
3 | color: #fdfdfd;
4 | font-size: 16px;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 | a:link, a:visited {
12 | text-decoration: none;
13 | }
14 |
15 | .loading__icon {
16 | display: block;
17 | position: absolute;
18 | border-radius: 50%;
19 | border-style: solid;
20 | border-color: #444 #fff #fff;
21 | animation: spin 1.5s cubic-bezier(0.66, 1, 0.66, 1) infinite;
22 | opacity: 0.5;
23 | transform: translate(-50%, -50%) rotate(0deg);
24 | backface-visibility: none;
25 | &.is--center {
26 | top: 50%;
27 | left: 50%;
28 | }
29 | &.is--left {
30 | top: 50%;
31 | left: 0%;
32 | }
33 | &.is--right {
34 | top: 50%;
35 | right: 0%;
36 | }
37 | &.is--large {
38 | border-width: 8px;
39 | width: 64px;
40 | height: 64px;
41 | }
42 | &.is--medium {
43 | border-width: 4px;
44 | width: 36px;
45 | height: 36px;
46 | }
47 | &.is--small {
48 | border-width: 2px;
49 | width: 18px;
50 | height: 18px;
51 | }
52 | }
53 |
54 | @keyframes spin {
55 | 0% { transform: translate(-50%, -50%) rotate(0deg); }
56 | 100% { transform: translate(-50%, -50%) rotate(359deg); }
57 | }
58 |
59 | @media only screen
60 | and (min-device-width : 375px)
61 | and (max-device-width : 667px) {
62 |
63 | .loading__icon {
64 |
65 | &.is--small {
66 | margin-left: -10px;
67 | margin-top:-6px;
68 | }
69 |
70 | }
71 |
72 | }
73 |
74 |
75 | @media only screen
76 | and (min-device-width : 414px)
77 | and (max-device-width : 736px) {
78 |
79 | .loading__icon {
80 |
81 | &.is--small {
82 | margin-left: -10px;
83 | margin-top:-6px;
84 | }
85 |
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/scaffold/root/backend/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // server.js
3 |
4 | const express = require('express');
5 | const http = require('http');
6 | const fs = require('fs');
7 | const app = express();
8 | const config = require(process.cwd()+'/angular.json');
9 | const serverConfig = {
10 | dev: require(process.cwd()+'/config/server.config.dev.js'),
11 | prod: require(process.cwd()+'/config/server.config.prod.js')
12 | };
13 |
14 | let projectRoot = config.projects[config.defaultProject].architect.build.options.outputPath;
15 | let env = process.env.NODE_ENV || 'dev';
16 | const port = serverConfig[env].port || process.env.PORT;
17 | const host = serverConfig[env].origin;
18 | let canWatch = false;
19 | let server;
20 |
21 | process.argv.forEach(function(arg){
22 |
23 | if (arg.includes('watch')) {
24 | canWatch = arg.split('=')[1].trim() === 'true' ? true : false;
25 | }
26 |
27 | });
28 |
29 |
30 | // Livereload Server Start
31 |
32 | let live = function() {
33 | let livereload = require('livereload');
34 | let liveserver = livereload.createServer({
35 | port: 35729
36 | });
37 | liveserver.watch([process.cwd() + '/'+projectRoot+'/assets',
38 | process.cwd() + '/'+projectRoot+'/src',
39 | process.cwd() + '/'+projectRoot+'/style',
40 | process.cwd() + '/'+projectRoot+'/*.html',
41 | process.cwd() + '/'+projectRoot+'/*.js',
42 | process.cwd() + '/'+projectRoot+'/*.css']);
43 | console.log('Livereload available at '+host+':'+35729);
44 | };
45 |
46 | // Create Server
47 |
48 | server = http.createServer(app);
49 |
50 | if (canWatch === true) {
51 |
52 | live();
53 |
54 | }
55 |
56 |
57 | // Express Middleware
58 |
59 |
60 |
61 | // Load Modules
62 |
63 | const routes = require('./router')(app);
64 |
65 | // Server Start
66 |
67 | server.listen(port);
68 |
69 | console.log('Express available at '+host+':'+port);
70 |
71 |
72 | module.exports = app;
73 |
--------------------------------------------------------------------------------
/src/scaffold/src/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{projectName}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/scaffold/root/closure.conf:
--------------------------------------------------------------------------------
1 | --compilation_level=ADVANCED_OPTIMIZATIONS
2 | --language_in=ECMASCRIPT6
3 | --language_out=ECMASCRIPT5
4 | --variable_renaming_report=closure/variable_renaming_report
5 | --property_renaming_report=closure/property_renaming_report
6 | --create_source_map=%outname%.map
7 |
8 | --warning_level=QUIET
9 | --dependency_mode=STRICT
10 | --rewrite_polyfills=false
11 | --module_resolution=NODE
12 |
13 | --externs closure.externs.js
14 | --externs node_modules/zone.js/dist/zone_externs.js
15 | --externs node_modules/@angular/core/src/testability/testability.externs.js
16 |
17 | --js node_modules/rxjs/package.json
18 | --js node_modules/rxjs/_fesm2015/index.js
19 |
20 | --js node_modules/rxjs/operators/package.json
21 | --js node_modules/rxjs/_fesm2015/operators/index.js
22 |
23 | --js node_modules/@angular/core/package.json
24 | --js node_modules/@angular/core/fesm2015/core.js
25 |
26 | --js node_modules/@angular/common/package.json
27 | --js node_modules/@angular/common/fesm2015/common.js
28 |
29 | --js node_modules/@angular/platform-browser/package.json
30 | --js node_modules/@angular/platform-browser/fesm2015/platform-browser.js
31 |
32 | --js node_modules/@angular/forms/package.json
33 | --js node_modules/@angular/forms/fesm2015/forms.js
34 |
35 | --js node_modules/@angular/common/http/package.json
36 | --js node_modules/@angular/common/fesm2015/http.js
37 |
38 | --js node_modules/@angular/router/package.json
39 | --js node_modules/@angular/router/fesm2015/router.js
40 |
41 | --js node_modules/@angular/animations/package.json
42 | --js node_modules/@angular/animations/fesm2015/animations.js
43 |
44 | --js node_modules/@angular/animations/browser/package.json
45 | --js node_modules/@angular/animations/fesm2015/browser.js
46 |
47 | --js node_modules/@angular/platform-browser/animations/package.json
48 | --js node_modules/@angular/platform-browser/fesm2015/animations.js
49 |
50 | --js out-tsc/**.js
51 |
52 | --package_json_entry_names es2015
53 |
54 | --entry_point=./out-tsc/src/main.js
--------------------------------------------------------------------------------
/src/scaffold/standalone/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{projectName}}",
3 | "version": "1.0.0",
4 | "license": "MIT",
5 | "description": "",
6 | "repository": "",
7 | "contributors": [],
8 | "scripts": {
9 | "ngr": "ngr",
10 | "ngr:prod": "ngr build prod",
11 | "serve": "node backend/server.js"
12 | },
13 | "dependencies": {
14 | "@angular/animations": "~7.0.0",
15 | "@angular/common": "~7.0.0",
16 | "@angular/compiler": "~7.0.0",
17 | "@angular/core": "~7.0.0",
18 | "@angular/forms": "~7.0.0",
19 | "@angular/platform-browser": "~7.0.0",
20 | "@angular/platform-browser-dynamic": "~7.0.0",
21 | "@angular/router": "~7.0.0",
22 | "angular-polyfills": "^1.0.1",
23 | "classlist.js": "^1.1.20150312",
24 | "compression": "^1.7.4",
25 | "console-polyfill": "^0.3.0",
26 | "core-js": "^2.4.1",
27 | "express": "^4.17.0",
28 | "ie9-oninput-polyfill": "^1.1.1",
29 | "reflect-metadata": "^0.1.13",
30 | "rxjs": "^6.0.0",
31 | "systemjs": "^0.21.4",
32 | "web-animations-js": "^2.3.2",
33 | "zone.js": "^0.8.26"
34 | },
35 | "devDependencies": {
36 | "@angular/compiler-cli": "~7.0.0",
37 | "@angular/language-service": "~7.0.0",
38 | "autoprefixer": "^8.6.3",
39 | "codelyzer": "^4.0.1",
40 | "google-closure-compiler": "20190618.0.0",
41 | "livereload": "^0.8.0",
42 | "node-sass": "^4.12.0",
43 | "postcss": "^7.0.0",
44 | "postcss-cli": "^6.0.0",
45 | "postcss-csso": "^3.0.0",
46 | "postcss-discard-comments": "^4.0.0",
47 | "postcss-prettify": "^0.3.4",
48 | "protractor": "^5.1.2",
49 | "rollup": "^1.0.0",
50 | "rollup-plugin-node-resolve": "^5.2.0",
51 | "shelljs": "^0.8.3",
52 | "ts-node": "^8.3.0",
53 | "tsickle": "0.35.0",
54 | "tslint": "^5.18.0",
55 | "typescript": "3.1.3"
56 | },
57 | "engines": {
58 | "node": ">8.11.0"
59 | }
60 | }
--------------------------------------------------------------------------------
/src/scaffold/src/public/system.config.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 |
3 | System.config({
4 | paths: {
5 | // paths serve as alias
6 | 'npm:': 'node_modules/',
7 | 'lib:': 'lib/'
8 | },
9 | // map tells the System loader where to look for things
10 | map: {
11 | // our app is within the app folder
12 | app: '.',
13 | // angular bundles
14 | '@angular/animations': 'lib:@angular/animations/bundles/animations.umd.js',
15 | '@angular/animations/browser': 'lib:@angular/animations/bundles/animations-browser.umd.js',
16 | '@angular/platform-browser/animations': 'lib:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
17 | '@angular/core': 'lib:@angular/core/bundles/core.umd.js',
18 | '@angular/common': 'lib:@angular/common/bundles/common.umd.js',
19 | '@angular/compiler': 'lib:@angular/compiler/bundles/compiler.umd.js',
20 | '@angular/platform-browser': 'lib:@angular/platform-browser/bundles/platform-browser.umd.js',
21 | '@angular/platform-browser-dynamic': 'lib:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
22 | '@angular/common/http': 'lib:@angular/common/bundles/common-http.umd.js',
23 | '@angular/http': 'lib:@angular/http/bundles/http.umd.js',
24 | '@angular/router': 'lib:@angular/router/bundles/router.umd.js',
25 | '@angular/forms': 'lib:@angular/forms/bundles/forms.umd.js',
26 | // other libraries
27 | 'rxjs': 'lib:rxjs',
28 | 'tslib': 'lib:tslib/tslib.js'
29 | },
30 | // packages tells the System loader how to load when no filename and/or no extension
31 | packages: {
32 | 'app': { main: './main.js', defaultExtension: 'js' },
33 | 'rxjs/ajax': { main: 'index.js', defaultExtension: 'js' },
34 | 'rxjs/operators': { main: 'index.js', defaultExtension: 'js' },
35 | 'rxjs/testing': { main: 'index.js', defaultExtension: 'js' },
36 | 'rxjs/websocket': { main: 'index.js', defaultExtension: 'js' },
37 | 'rxjs': { main: 'index.js', defaultExtension: 'js' }
38 | }
39 | });
40 |
41 | })(this);
42 |
--------------------------------------------------------------------------------
/src/scaffold/ivy/src/public/system.config.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 |
3 | System.config({
4 | paths: {
5 | // paths serve as alias
6 | 'npm:': 'node_modules/',
7 | 'lib:': 'lib/'
8 | },
9 | // map tells the System loader where to look for things
10 | map: {
11 | // our app is within the app folder
12 | app: '.',
13 | // angular bundles
14 | '@angular/animations': 'lib:@angular/animations/bundles/animations.umd.js',
15 | '@angular/animations/browser': 'lib:@angular/animations/bundles/animations-browser.umd.js',
16 | '@angular/platform-browser/animations': 'lib:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
17 | '@angular/core': 'lib:@angular/core/bundles/core.umd.js',
18 | '@angular/common': 'lib:@angular/common/bundles/common.umd.js',
19 | '@angular/compiler': 'lib:@angular/compiler/bundles/compiler.umd.js',
20 | '@angular/platform-browser': 'lib:@angular/platform-browser/bundles/platform-browser.umd.js',
21 | '@angular/platform-browser-dynamic': 'lib:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
22 | '@angular/common/http': 'lib:@angular/common/bundles/common-http.umd.js',
23 | '@angular/http': 'lib:@angular/http/bundles/http.umd.js',
24 | '@angular/router': 'lib:@angular/router/bundles/router.umd.js',
25 | '@angular/forms': 'lib:@angular/forms/bundles/forms.umd.js',
26 | // other libraries
27 | 'rxjs': 'lib:rxjs',
28 | 'tslib': 'lib:tslib/tslib.js'
29 | },
30 | // packages tells the System loader how to load when no filename and/or no extension
31 | packages: {
32 | 'app': { main: './src/main.js', defaultExtension: 'js' },
33 | 'rxjs/ajax': { main: 'index.js', defaultExtension: 'js' },
34 | 'rxjs/operators': { main: 'index.js', defaultExtension: 'js' },
35 | 'rxjs/testing': { main: 'index.js', defaultExtension: 'js' },
36 | 'rxjs/websocket': { main: 'index.js', defaultExtension: 'js' },
37 | 'rxjs': { main: 'index.js', defaultExtension: 'js' }
38 | }
39 | });
40 |
41 | })(this);
42 |
--------------------------------------------------------------------------------
/src/scaffold/pretty/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": ["node_modules/codelyzer"],
3 | "rules": {
4 | "arrow-return-shorthand": true,
5 | "callable-types": true,
6 | "class-name": true,
7 | "comment-format": [true, "check-space"],
8 | "curly": true,
9 | "deprecation": {
10 | "severity": "warn"
11 | },
12 | "eofline": true,
13 | "forin": true,
14 | "import-blacklist": [true, "rxjs/Rx"],
15 | "import-spacing": true,
16 | "indent": [true, "spaces"],
17 | "interface-over-type-literal": true,
18 | "label-position": true,
19 | "member-access": false,
20 | "member-ordering": [
21 | true,
22 | {
23 | "order": ["static-field", "instance-field", "static-method", "instance-method"]
24 | }
25 | ],
26 | "no-arg": true,
27 | "no-bitwise": false,
28 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
29 | "no-construct": true,
30 | "no-debugger": true,
31 | "no-duplicate-super": true,
32 | "no-empty": false,
33 | "no-empty-interface": true,
34 | "no-eval": true,
35 | "no-inferrable-types": [true, "ignore-params"],
36 | "no-misused-new": true,
37 | "no-non-null-assertion": true,
38 | "no-shadowed-variable": true,
39 | "no-string-literal": false,
40 | "no-string-throw": true,
41 | "no-switch-case-fall-through": true,
42 | "no-unnecessary-initializer": true,
43 | "no-unused-expression": true,
44 | "no-use-before-declare": true,
45 | "no-var-keyword": true,
46 | "object-literal-sort-keys": false,
47 | "prefer-const": true,
48 | "radix": true,
49 | "unified-signatures": true,
50 | "variable-name": false,
51 | "no-output-on-prefix": true,
52 | "use-input-property-decorator": true,
53 | "use-output-property-decorator": true,
54 | "use-host-property-decorator": true,
55 | "no-input-rename": true,
56 | "no-output-rename": true,
57 | "use-life-cycle-interface": true,
58 | "use-pipe-transform-interface": true,
59 | "component-class-suffix": true,
60 | "directive-class-suffix": true
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/scaffold/ssl/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | // server.js
3 |
4 | const express = require('express');
5 | const https = require('https');
6 | const path = require('path');
7 | const fs = require('fs');
8 | const app = express();
9 | const config = require(process.cwd() + '/angular.json');
10 | const serverConfig = {
11 | dev: require(process.cwd() + '/config/server.config.dev.js'),
12 | prod: require(process.cwd() + '/config/server.config.prod.js')
13 | };
14 | const sslOptions = {
15 | key: fs.readFileSync(path.join(__dirname, 'key.pem')),
16 | cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
17 | requestCert: false,
18 | rejectUnauthorized: false
19 | };
20 |
21 | let projectRoot = config.projects[config.defaultProject].architect.build.options.outputPath;
22 | let env = process.env.NODE_ENV || 'dev';
23 | const port = serverConfig[env].port || process.env.PORT;
24 | const host = serverConfig[env].origin;
25 | let canWatch = false;
26 | let server;
27 |
28 | process.argv.forEach(function(arg) {
29 | if (arg.includes('watch')) {
30 | canWatch = arg.split('=')[1].trim() === 'true' ? true : false;
31 | }
32 | });
33 |
34 | // Create Server
35 |
36 | server = https.createServer(sslOptions, app);
37 |
38 | // Livereload Server Start
39 |
40 | let live = function() {
41 | let livereload = require('livereload');
42 | let liveserver = livereload.createServer({
43 | port: 35729,
44 | https: {
45 | key: fs.readFileSync(path.join(__dirname, 'key.pem')),
46 | cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
47 | }
48 | });
49 | liveserver.watch([
50 | process.cwd() + '/' + projectRoot + '/assets',
51 | process.cwd() + '/' + projectRoot + '/src',
52 | process.cwd() + '/' + projectRoot + '/style',
53 | process.cwd() + '/' + projectRoot + '/*.html',
54 | process.cwd() + '/' + projectRoot + '/*.js',
55 | process.cwd() + '/' + projectRoot + '/*.css'
56 | ]);
57 | console.log('Livereload available at ' + host + ':' + 35729);
58 | };
59 |
60 | if (canWatch === true) {
61 | live();
62 | }
63 |
64 | // Express Middleware
65 |
66 | // Load Modules
67 |
68 | const routes = require('./router')(app);
69 |
70 | // Server Start
71 |
72 | server.listen(port, () => {
73 | console.log('SSL connection available at ' + host + ':' + port);
74 | });
75 |
76 | module.exports = app;
77 |
--------------------------------------------------------------------------------
/src/bundle/closure.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const exec = require('child_process').exec;
3 | const util = require('./../util.js');
4 | const log = require('./../log.js');
5 | const config = require('./../config');
6 | const cli = require('./../../cli.config.json');
7 |
8 | class ClosureBuilder {
9 |
10 | constructor() {
11 | this.jarPath = util.hasConfigProperty('jarPath', config.prodOptions) ? config.prodOptions.jarPath : path.resolve('node_modules', 'google-closure-compiler-java', 'compiler.jar');
12 | this.warningLevel = util.hasConfigProperty('warningLevel', config.prodOptions) ? config.prodOptions.warningLevel : 'QUIET';
13 | this.confPath = util.hasConfigProperty('confPath', config.prodOptions) ? config.prodOptions.confPath : path.normalize('closure.conf');
14 | this.outFile = util.hasConfigProperty('outBundle', config.prodOptions) ? config.prodOptions.outBundle : './' + config.build + '/bundle.js';
15 | this.manifestPath = util.hasConfigProperty('manifestPath', config.prodOptions) ? config.prodOptions.manifestPath : path.normalize('closure/manifest.MF');
16 | }
17 |
18 | bundle() {
19 | return new Promise((res) => {
20 |
21 | if (cli.program.rollup) {
22 | this.confPath = path.normalize('closure.rollup.conf')
23 | }
24 |
25 | exec(`java -jar ${this.jarPath} --warning_level=${this.warningLevel} --flagfile ${this.confPath} --js_output_file ${this.outFile} --output_manifest=${this.manifestPath}`,
26 | { silent: true },
27 | (error, stdout, stderr) => {
28 | log.stop('closure compiler');
29 | if (stdout.includes('ERROR')) {
30 | error.split(/\n\n/g).forEach((str) => {
31 | log.formatClosureError(str);
32 | });
33 | }
34 | else if (stderr.includes('ERROR')) {
35 | stderr.split(/\n\n/g).forEach((str) => {
36 | log.formatClosureError(str);
37 | });
38 | }
39 | else {
40 | log.success('Optimization complete.', ['closure']);
41 | if (res) {
42 | res('done');
43 | }
44 | }
45 |
46 | });
47 | })
48 | }
49 |
50 | }
51 |
52 |
53 | module.exports = ClosureBuilder;
54 |
--------------------------------------------------------------------------------
/src/scaffold/standalone/karma-test-shim.js:
--------------------------------------------------------------------------------
1 | // #docregion
2 | // /*global jasmine, __karma__, window*/
3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
4 |
5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not.
6 | // Error.stackTraceLimit = Infinity; //
7 |
8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
9 |
10 | var builtPath = '/base/build/src/app/';
11 |
12 | __karma__.loaded = function () { };
13 |
14 | function isJsFile(path) {
15 | return path.slice(-3) == '.js';
16 | }
17 |
18 | function isSpecFile(path) {
19 | return /\.spec\.(.*\.)?js$/.test(path);
20 | }
21 |
22 | function isBuiltFile(path) {
23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
24 | }
25 |
26 | var allSpecFiles = Object.keys(window.__karma__.files)
27 | .filter(isSpecFile)
28 | .filter(isBuiltFile);
29 |
30 | System.config({
31 | baseURL: '/base/build/',
32 | // Extend usual application package list with test folder
33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } },
34 |
35 | // Assume npm: is set in `paths` in systemjs.config
36 | // Map the angular testing umd bundles
37 | map: {
38 | 'app': '/build',
39 | '@angular/core/testing': 'lib/@angular/core/bundles/core-testing.umd.js',
40 | '@angular/common/testing': 'lib/@angular/common/bundles/common-testing.umd.js',
41 | '@angular/compiler/testing': 'lib/@angular/compiler/bundles/compiler-testing.umd.js',
42 | '@angular/platform-browser/testing': 'lib/@angular/platform-browser/bundles/platform-browser-testing.umd.js',
43 | '@angular/platform-browser-dynamic/testing': 'lib/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
44 | '@angular/http/testing': 'lib/@angular/http/bundles/http-testing.umd.js',
45 | '@angular/router/testing': 'lib/@angular/router/bundles/router-testing.umd.js',
46 | '@angular/forms/testing': 'lib/@angular/forms/bundles/forms-testing.umd.js',
47 | 'rxjs': 'node_modules/rxjs'
48 | },
49 | });
50 |
51 | System.import('/base/build/system.config.js')
52 | .then(initTestBed)
53 | .then(initTesting);
54 |
55 |
56 | function initTestBed() {
57 | return Promise.all([
58 | System.import('/base/build/lib/@angular/core/bundles/core-testing.umd.js'),
59 | System.import('/base/build/lib/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js')
60 | ])
61 |
62 | .then(function (providers) {
63 | var coreTesting = providers[0];
64 | var browserTesting = providers[1];
65 |
66 | coreTesting.TestBed.initTestEnvironment(
67 | browserTesting.BrowserDynamicTestingModule,
68 | browserTesting.platformBrowserDynamicTesting());
69 | })
70 | }
71 |
72 | // Import all spec files and start karma
73 | function initTesting() {
74 | return Promise.all(
75 | allSpecFiles.map(function (moduleName) {
76 | return System.import(moduleName);
77 | })
78 | )
79 | .then(__karma__.start, __karma__.error);
80 | }
81 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 |
2 | const findup = require('findup');
3 | const path = require('path');
4 | const fs = require('fs');
5 | const log = require('./log');
6 | const processRoot = path.join(path.dirname(process.cwd()), path.basename(process.cwd()));
7 | const cliRoot = findup.sync(__dirname, 'package.json');
8 | let projectRoot = require(path.join(cliRoot, 'cli.config.json')).projectRoot;
9 |
10 | class Config {
11 | constructor() {
12 |
13 | let config = new Object();
14 |
15 | if (fs.existsSync(projectRoot + '/ngr.config.js')) {
16 | config = require(projectRoot + '/ngr.config.js');
17 | } else { // for processes not in the root
18 |
19 | try{
20 | projectRoot = findup.sync(projectRoot, 'ngr.config.js');
21 | config = require(projectRoot + '/ngr.config.js');
22 | } catch(e){
23 | log.break();
24 | log.error('ngr command requires to be run in an Angular project scaffolded with angular-rollup');
25 | log.break();
26 | log.break();
27 | process.exit(1);
28 | }
29 |
30 | }
31 |
32 | if (fs.existsSync(projectRoot + '/angular.json')) {
33 |
34 | let angularConfig = require(projectRoot + '/angular.json');
35 | let ngrConfig = require(projectRoot + '/ngr.config.js');
36 |
37 | config.angular = angularConfig;
38 | // if next argument after build is not an option, assume argument is the project name
39 | if (process.argv.indexOf('build') !== -1 &&
40 | process.argv[process.argv.indexOf('build') + 2] &&
41 | process.argv[process.argv.indexOf('build') + 2].includes('--') === false) {
42 |
43 | config.project = process.argv[process.argv.indexOf('build') + 2];
44 | config.src = path.join(ngrConfig.projects[config.project].root, ngrConfig.projects[config.project].sourceRoot);
45 | config.build = ngrConfig.projects[config.project].architect.build.options.outputPath;
46 | config.style = {
47 | files : ngrConfig.projects[config.project].architect.build.options.styles
48 | }
49 |
50 |
51 | } else {
52 |
53 | // use default project name
54 | config.project = ngrConfig.defaultProject;
55 | config.src = path.join(ngrConfig.projects[config.project].root, ngrConfig.projects[config.project].sourceRoot);
56 | config.build = ngrConfig.projects[config.project].architect.build.options.outputPath;
57 | config.style = {
58 | files: ngrConfig.projects[config.project].architect.build.options.styles
59 | }
60 |
61 | }
62 |
63 |
64 | }
65 |
66 | config.processRoot = processRoot;
67 | config.projectRoot = projectRoot;
68 | config.cliRoot = cliRoot;
69 |
70 | return config;
71 |
72 | }
73 | }
74 |
75 | module.exports = new Config();
--------------------------------------------------------------------------------
/src/compile/babel.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const exec = require('child_process').exec;
4 | const util = require('./../util.js');
5 | const log = require('./../log.js');
6 | const config = require('./../config');
7 | const cli = require('./../../cli.config.json');
8 |
9 | class BabelBuilder {
10 |
11 | constructor() { }
12 |
13 | compileUMD(outFile) {
14 | return new Promise((res, rej) => {
15 |
16 | let transpile = exec(path.normalize(config.processRoot + '/node_modules/.bin/babel') +
17 | ' --source-maps' +
18 | ' --presets=es2015-rollup ' +
19 | ' --plugins=transform-es2015-modules-commonjs ' +
20 | ' --module umd ' +
21 | path.normalize(outFile) +
22 | ' --out-file ' + path.normalize(outFile), (code, output, error) => {
23 |
24 | let fetchHelpers = exec(path.normalize(config.processRoot + '/node_modules/.bin/babel-external-helpers') +
25 | ' --output-type global ', { silent: true }, (code, output, error) => {
26 |
27 | fs.readFile(path.normalize(outFile), 'utf8', (err, contents) => {
28 | if (err) rej(err);
29 | if (!err) {
30 | contents = contents.replace("'use strict';", "'use strict';" + "\n" + output);
31 | fs.writeFile(path.normalize(outFile), contents, 'utf-8', () => { });
32 | }
33 | });
34 | });
35 |
36 | log.alert('babel', 'transpiled', path.normalize(outFile));
37 | res(outFile);
38 |
39 | });
40 |
41 |
42 | });
43 | }
44 |
45 | compileES5(outFile) {
46 | return new Promise((res, rej) => {
47 |
48 |
49 | let transpile = exec(path.normalize(config.processRoot + '/node_modules/.bin/babel') +
50 | ' --source-maps' +
51 | ' --presets=es2015-rollup ' + (outFile) +
52 | ' --out-file ' + (outFile), (code, output, error) => {
53 |
54 | let fetchHelpers = exec(path.normalize(config.processRoot + '/node_modules/.bin/babel-external-helpers') +
55 | ' --output-type global ', { silent: true }, (code, output, error) => {
56 |
57 | fs.readFile(path.normalize(outFile), 'utf8', (err, contents) => {
58 | if (!err) {
59 | contents = output + '\n' + contents;
60 | fs.writeFile(path.normalize(outFile), contents, 'utf-8', () => { });
61 | }
62 | });
63 | });
64 |
65 | log.alert('babel', 'transpiled', path.normalize(outFile));
66 | res(outFile);
67 |
68 | });
69 |
70 | });
71 | }
72 |
73 | }
74 |
75 |
76 | module.exports = BabelBuilder;
77 |
--------------------------------------------------------------------------------
/src/scaffold/standalone/karma.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = function (config) {
4 | config.set({
5 |
6 | basePath: './',
7 |
8 | frameworks: ['jasmine'],
9 |
10 | plugins: [
11 | require('karma-jasmine'),
12 | require('karma-chrome-launcher'),
13 | require('karma-jasmine-html-reporter'),
14 | require('karma-coverage'),
15 | require('karma-remap-coverage')
16 | ],
17 | client: {
18 | clearContext: false
19 | },
20 |
21 |
22 | remapCoverageReporter: {
23 | 'text-summary': null, // to show summary in console
24 | html: './coverage/html',
25 | cobertura: './coverage/cobertura.xml'
26 | },
27 |
28 | files: [
29 | // Polyfills.
30 | 'node_modules/core-js/client/shim.min.js',
31 |
32 | 'node_modules/reflect-metadata/Reflect.js',
33 |
34 | // System.js for module loading
35 | 'node_modules/systemjs/dist/system.src.js',
36 |
37 | // Zone.js dependencies
38 | 'node_modules/zone.js/dist/zone.js',
39 | 'node_modules/zone.js/dist/long-stack-trace-zone.js',
40 | 'node_modules/zone.js/dist/proxy.js',
41 | 'node_modules/zone.js/dist/sync-test.js',
42 | 'node_modules/zone.js/dist/jasmine-patch.js',
43 | 'node_modules/zone.js/dist/async-test.js',
44 | 'node_modules/zone.js/dist/fake-async-test.js',
45 |
46 | // RxJs.
47 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
48 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
49 |
50 |
51 | { pattern: 'karma-test-shim.js', included: true, watched: true },
52 |
53 | // paths loaded via module imports
54 | // Angular itself
55 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: true },
56 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: true },
57 |
58 | // Our built application code
59 | { pattern: 'build/**/*.js', included: false, watched: true },
60 |
61 | // paths loaded via Angular's component compiler
62 | // (these paths need to be rewritten, see proxies section)
63 | { pattern: 'build/**/*.html', included: false, watched: true },
64 | { pattern: 'build/**/*.css', included: false, watched: true },
65 |
66 | // paths to support debugging with source maps in dev tools
67 | { pattern: 'src/**/*.ts', included: false, watched: true },
68 | //{pattern: 'build/**/*.js.map', included: false, watched: false}
69 | ],
70 |
71 | // proxied base paths
72 | proxies: {
73 | // required for component assests fetched by Angular's compiler
74 | "/app/": "/build/src/"
75 | },
76 |
77 | preprocessors: {
78 | 'build/src/app/shared/lib/**/*.component.js': ['coverage']
79 | },
80 |
81 | coverageReporter: {
82 | type: 'in-memory'
83 | },
84 |
85 | reporters: ['progress', 'kjhtml', 'coverage', 'remap-coverage'],
86 | port: 9876,
87 | colors: true,
88 | logLevel: config.LOG_INFO,
89 | autoWatch: true,
90 | browsers: ['Chrome'],
91 | singleRun: false
92 | })
93 | }
94 |
--------------------------------------------------------------------------------
/src/style/postcss.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 | const exec = require('child_process').exec;
3 | const path = require('path');
4 | const fs = require('fs');
5 | const log = require('./../log.js');
6 | const config = require('./../config');
7 | const cli = require('./../../cli.config.json');
8 |
9 | class PostCSS {
10 |
11 | constructor(cssConfig) {
12 | this.cssConfig = cssConfig;
13 | }
14 |
15 | batch(fileList) {
16 |
17 | return new Promise((res) => {
18 |
19 | try {
20 |
21 | const files = fileList.map((filePath) => {
22 | return this.file(filePath);
23 | });
24 |
25 | Promise.all(files).then((css) => {
26 | res(css);
27 | });
28 |
29 | }
30 | catch (err) {
31 | err.service = 'postcss';
32 | log.error(err);
33 |
34 | }
35 |
36 | });
37 |
38 | }
39 |
40 | file(filePath) {
41 |
42 | // if (filePath.includes('out-css')) { // fixes issue with filePath in --watch
43 | // filePath = filePath.replace('out-css/', '').replace('out-css\\', '');
44 | // }
45 |
46 |
47 | return new Promise((res) => {
48 |
49 | const globalBaseNames = config.projects[config.project].architect.build.options.styles.map((stylePath) => {
50 | return path.dirname(stylePath);
51 | }).filter((value, index, self) => {
52 | return self.indexOf(value) === index;
53 | });
54 |
55 | const isGlobal = new RegExp(globalBaseNames.join('|')).test(filePath);
56 |
57 | let outFile = filePath;
58 |
59 | if (isGlobal) {
60 |
61 | globalBaseNames.forEach((baseName) => {
62 | if (outFile.includes(baseName)) {
63 | outFile = path.join(this.cssConfig.dist, outFile).replace('src/', '').replace('src\\', '');
64 | }
65 | })
66 |
67 | }
68 |
69 | // outFile = outFile.replace('scss', 'css');
70 |
71 | if (!fs.existsSync(path.normalize(outFile.substring(0, outFile.replace(/\\/g, "/").lastIndexOf("/"))))) {
72 | mkdir('-p', path.normalize(outFile.substring(0, outFile.replace(/\\/g, "/").lastIndexOf("/"))));
73 | }
74 |
75 | exec(path.normalize(path.join(config.projectRoot, 'node_modules/.bin/postcss')) +
76 | ' ' + outFile +
77 | (this.cssConfig.sourceMap === false ? ' --no-map' : '') +
78 | ' --env ' + (cli.env) +
79 | ' --output ' + outFile,
80 | { silent: true }, (error, stdout, stderr) => {
81 |
82 | if (stderr) {
83 | //stderr.service = 'postcss';
84 | log.error(stderr);
85 | }
86 |
87 | if (res) {
88 | res(filePath, outFile);
89 | }
90 |
91 | });
92 |
93 | });
94 |
95 | }
96 |
97 | }
98 |
99 |
100 | module.exports = PostCSS;
101 |
--------------------------------------------------------------------------------
/src/watch.js:
--------------------------------------------------------------------------------
1 |
2 | const findup = require('findup');
3 | const path = require('path');
4 | const utils = require('./util');
5 | const chokidar = require('chokidar');
6 | const SassBuilder = require('./style/sass.js');
7 | const PostCSSBuilder = require('./style/postcss.js');
8 | const TSBuilder = require('./compile/tsc.js');
9 | const config = require('./config');
10 | const util = require('./util');
11 | const log = require('./log');
12 | const cli = require('./../cli.config.json');
13 |
14 | let = lastPath = '';
15 |
16 | class Watcher {
17 | constructor() {
18 |
19 | const sassBuilder = new SassBuilder({ dist: config.build });
20 | const postcssBuilder = new PostCSSBuilder({ dist: config.build, sourceMap: (cli.build === 'dev') ? false : true });
21 | const jitBuilder = new TSBuilder();
22 | const watcher = chokidar.watch([config.src], {
23 | ignored: /[\/\\]\./,
24 | persistent: true
25 | }).on('change', filePath => {
26 |
27 | if (filePath.includes('out-css')) {
28 | return;
29 | }
30 |
31 | if (cli.program.verbose) log.message(filePath + ' changed');
32 |
33 | if (filePath.includes(path.join(config.src, 'public'))) {
34 | this.updatePublic(filePath);
35 | }
36 | else if (filePath.indexOf('.scss') > -1) {
37 |
38 | (async () => {
39 |
40 | const sass = await sassBuilder.file(filePath);
41 |
42 | if (Array.isArray(sass)) {
43 | const postcss = await postcssBuilder.batch(sass);
44 | log.cancelError('sass');
45 | log.cancelError('postcss');
46 | // log.success('libsass and postcss compiled', ['sass', 'postcss']);
47 | } else {
48 | const postcss = await postcssBuilder.file(sass);
49 | log.cancelError('sass');
50 | log.cancelError('postcss');
51 | //log.success('libsass and postcss compiled', ['sass', 'postcss']);
52 | }
53 |
54 |
55 | })();
56 | }
57 | else if (filePath.indexOf('.ts') > -1 && cli.build === 'jit') {
58 | jitBuilder.compile(path.join('src', 'tsconfig.' + cli.build + '.json'));
59 | }
60 | else if (filePath.indexOf('.html') > -1 && cli.build === 'jit') {
61 | util.copyFile(filePath, path.join(config.build, filePath));
62 | }
63 |
64 | if (util.hasHook('watch') && config.projects[config.project].architect.build.hooks[cli.build].watch.src) {
65 | config.projects[config.project].architect.build.hooks[cli.build].watch.src(filePath);
66 | }
67 |
68 | }).on('unlink', filePath => log.warn(filePath, 'has been removed'))
69 | .on('error', error => log.warn('ERROR:', error));
70 | //.on('ready', error => log.message('listening for changes'));
71 |
72 | return watcher;
73 |
74 | }
75 |
76 | updatePublic(filePath) {
77 |
78 | if (filePath.includes(path.join(config.src, 'public', 'index.html'))) {
79 | util.formatIndex(path.normalize(config.src + '/public/index.html'));
80 | } else {
81 | util.copyFile(filePath, path.join(config.build, filePath.replace(path.normalize('src/public/'), '')));
82 | }
83 |
84 | }
85 | }
86 |
87 | module.exports = Watcher;
88 |
--------------------------------------------------------------------------------
/src/generate/lib.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 | const fs = require('fs');
3 | const path = require('path');
4 | const log = require('./../log');
5 | const util = require('./../util');
6 | const cli = require('./../../cli.config.json');
7 | const config = require('./../config');
8 | const Scaffold = require('./../scaffold/index');
9 | const Generator = require('./index');
10 |
11 | class LibraryGenerator extends Generator {
12 |
13 | constructor() {
14 | super();
15 | this.folderName = this.name.includes('/') ? this.name.split('/')[1] : this.name;
16 | this.addProjectToConfig = new Scaffold().addProjectToConfig;
17 | }
18 |
19 | copy() {
20 | util.copyDir(path.join(config.cliRoot, 'src', 'scaffold', 'lib'), path.join(this.outputPath, this.name));
21 | }
22 |
23 | list(directoryPath) {
24 |
25 | ls(directoryPath).forEach((file) => {
26 | let depth = this.directoryDepth;
27 | if (this.name.includes('/')) {
28 | depth = depth + 1;
29 | }
30 | if (fs.statSync(path.join(directoryPath, file)).isFile()) {
31 | if (!path.join(directoryPath, file).includes('tsconfig.lib.json')) {
32 | depth = depth + 1;
33 | }
34 | this.replacePathInFile(path.join(directoryPath, file), depth);
35 | this.replaceFolderNameInFile(path.join(directoryPath, file));
36 | this.replaceNameInFile(path.join(directoryPath, file));
37 | this.replaceProjectPathInFile(path.join(directoryPath, file));
38 | }
39 | else if (fs.statSync(path.join(directoryPath, file)).isDirectory()) {
40 | this.list(path.join(directoryPath, file));
41 | }
42 | });
43 | }
44 |
45 | replacePathInFile(filePath, depth) {
46 | let relativePath = '';
47 | for (let i = 0; i < depth; i++) {
48 | relativePath += '../';
49 | }
50 | sed('-i', /{{relativePath}}/g, relativePath, path.normalize(filePath));
51 | }
52 |
53 | replaceFolderNameInFile(filePath) {
54 | sed('-i', /{{folderName}}/g, this.folderName, path.normalize(filePath));
55 | }
56 |
57 | replaceNameInFile(filePath) {
58 | sed('-i', /{{projectName}}/g, this.name, path.normalize(filePath));
59 | }
60 |
61 | replaceProjectPathInFile(filePath) {
62 | sed('-i', /{{projectPath}}/g, this.srcPath, path.normalize(filePath));
63 | }
64 |
65 | getFileDirectoryDepth(filePath) {
66 | let directoryCount = 0;
67 | if (this.outputPath.match(/\//g)) {
68 | directoryCount = filePath.match(/\//g).length;
69 | }
70 | if (this.outputPath.match(/\\/g)) {
71 | directoryCount = filePath.replace(':\\\\', '\\').match(/\\/g).length;
72 | }
73 | return directoryCount;
74 | }
75 |
76 | init() {
77 |
78 | log.message(config.projectRoot + ' '+ this.outputPath);
79 | this.srcPath = this.outputPath.replace(config.projectRoot, '').slice(1).replace(/\\/gi, '/') + '/'+ this.name;
80 |
81 | this.directoryDepth = this.getFileDirectoryDepth(this.outputPath) -
82 | this.getFileDirectoryDepth(config.projectRoot) + 1;
83 |
84 | mkdir('-p', path.join(this.outputPath, this.name));
85 | this.copy();
86 | this.list(path.join(this.outputPath, this.name));
87 | this.addProjectToConfig(this.name, {
88 | root: this.srcPath,
89 | projectType: 'library',
90 | configFile: 'lib.config.json'
91 | });
92 | log.spinner.stop();
93 |
94 | }
95 |
96 | }
97 |
98 | module.exports = LibraryGenerator;
--------------------------------------------------------------------------------
/src/scaffold/root/ngr.config.js:
--------------------------------------------------------------------------------
1 | const spawn = require('child_process').spawn;
2 | const fs = require('fs');
3 |
4 | module.exports = {
5 | defaultProject: '{{projectName}}',
6 | projects: {
7 | '{{projectName}}': {
8 | root: '',
9 | sourceRoot: 'src',
10 | projectType: 'application',
11 | configFile: '',
12 | architect: {
13 | build: {
14 | builder: 'angular-rollup',
15 | options: {
16 | outputPath: 'dist/{{projectName}}',
17 | styles: ['src/style/style.scss'],
18 | stylePreprocessorOptions: {
19 | includePaths: ['src/style'],
20 | outputStyle: 'expanded',
21 | sourceComments: true
22 | },
23 | lib: {
24 | dev: [
25 | "core-js/client/shim.min.js",
26 | "core-js/client/shim.min.js.map",
27 | "zone.js/dist/zone.min.js",
28 | "web-animations-js/web-animations.min.js",
29 | "web-animations-js/web-animations.min.js.map",
30 | "ie9-oninput-polyfill/ie9-oninput-polyfill.js",
31 | "angular-polyfills/dist/blob.js",
32 | "angular-polyfills/dist/classList.js",
33 | "angular-polyfills/dist/formdata.js",
34 | "angular-polyfills/dist/intl.js",
35 | "angular-polyfills/dist/typedarray.js",
36 | "console-polyfill/index.js",
37 | "systemjs/dist/system.js",
38 | "systemjs/dist/system.js.map",
39 | "reflect-metadata/Reflect.js",
40 | "tslib/tslib.js",
41 | "@angular",
42 | "rxjs"
43 | ],
44 | prod: [
45 | "core-js/client/shim.min.js",
46 | "zone.js/dist/zone.min.js",
47 | "web-animations-js/web-animations.min.js",
48 | "ie9-oninput-polyfill/ie9-oninput-polyfill.js",
49 | "angular-polyfills/dist/blob.js",
50 | "angular-polyfills/dist/classList.js",
51 | "angular-polyfills/dist/formdata.js",
52 | "angular-polyfills/dist/intl.js",
53 | "angular-polyfills/dist/typedarray.js",
54 | "console-polyfill/index.js",
55 | "systemjs/dist/system.js"
56 | ],
57 | src: "node_modules",
58 | dist: "dist/{{projectName}}/lib"
59 | }
60 |
61 | },
62 | hooks: {
63 | prod: {
64 | pre: () => {
65 | return new Promise((res) => {
66 | // put togic in here for before the production build
67 | res();
68 | });
69 | },
70 | post: () => {
71 | return new Promise((res) => {
72 | // put togic in here for after the production build
73 | res();
74 | });
75 | }
76 | }
77 | }
78 | }
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/scaffold/src/style/util/_mixins.scss:
--------------------------------------------------------------------------------
1 | //-----------------------------------------
2 | // Responsive
3 | //-----------------------------------------
4 |
5 | $sm-breakpoint: 0px;
6 | $md-breakpoint: 768px;
7 | $lg-breakpoint: 1025px;
8 | $xl-breakpoint: 1441px;
9 |
10 |
11 | //-----------------------------------------
12 | // Media Queries
13 | //-----------------------------------------
14 |
15 | // Use these mixins to ensure similar media queries are used throughout the project, mqpacker will collapse all instances into one block
16 |
17 | @mixin media-sm {
18 | @media (max-width: #{$md-breakpoint - 1px}) {
19 | @content;
20 | }
21 | }
22 |
23 | @mixin media-md {
24 | @media (min-width: #{$md-breakpoint}) and (max-width: #{$lg-breakpoint - 1px}) {
25 | @content;
26 | }
27 | }
28 |
29 | @mixin media-lg {
30 | @media (min-width: #{$lg-breakpoint}) and (max-width: #{$xl-breakpoint - 1px}) {
31 | @content;
32 | }
33 | }
34 |
35 | @mixin media-xl {
36 | @media (min-width: #{$xl-breakpoint} ) {
37 | @content;
38 | }
39 | }
40 |
41 |
42 |
43 | //-----------------------------------------
44 | // Font Weight
45 | //-----------------------------------------
46 | @mixin font-weight($weight) {
47 | font-weight: $weight;
48 | }
49 |
50 | // font anti-aliasing
51 | %anti-aliasing {
52 | -webkit-font-smoothing: antialiased;
53 | -moz-osx-font-smoothing: grayscale;
54 | }
55 |
56 |
57 | //-----------------------------------------
58 | // Font Size
59 | //-----------------------------------------
60 |
61 | /**
62 | * Convert font-size from px to rem with px fallback
63 | *
64 | * @param $size - the value in pixel you want to convert
65 | *
66 | * e.g. p {@include fontSize(12px);}
67 | *
68 | */
69 |
70 | // Function for converting a px based font-size to rem.
71 | @function calculate-rem($size) {
72 | $remSize: $size / 16px;
73 | //Default font size on html element is 100%, equivalent to 16px;
74 | @return #{$remSize}rem;
75 | }
76 |
77 | // Mixin that will include the fall back px declaration as well as the calculated rem value.
78 | @mixin font-size($size) {
79 | font-size: $size;
80 | font-size: calculate-rem($size);
81 | }
82 |
83 |
84 | //-----------------------------------------
85 | // Cross Browser CSS Transforms
86 | //-----------------------------------------
87 |
88 |
89 | @function str-replace($string, $search, $replace: '') {
90 | $index: str-index($string, $search);
91 | @if $index {
92 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
93 | }
94 | @return $string;
95 | }
96 |
97 | @mixin transform2($trans...) {
98 | $fallback: unquote(str-replace(str-replace("#{$trans}", '3d', ''), ', 0)', ')'));
99 | -ms-transform: $fallback;
100 |
101 | $prefixes: (ms, moz, o, webkit);
102 | @each $prefix in $prefixes {
103 | #{'-' + $prefix + '-transform'}: $trans;
104 | }
105 |
106 | transform: $trans;
107 | }
108 |
109 |
110 | //-----------------------------------------
111 | // Layout
112 | //-----------------------------------------
113 | @mixin vertical-align {
114 | position: relative;
115 | top: 50%;
116 | -webkit-transform: translateY(-50%);
117 | -ms-transform: translateY(-50%);
118 | transform: translateY(-50%);
119 | }
120 |
121 | @mixin horizontal-align {
122 | position: relative;
123 | left: 50%;
124 | -webkit-transform: translateX(-50%);
125 | -ms-transform: translateX(-50%);
126 | transform: translateX(-50%);
127 | }
128 |
129 | //-----------------------------------------
130 | // clearfix
131 | //-----------------------------------------
132 |
133 |
134 | @mixin clearfix {
135 | &:after {
136 | content: "";
137 | display: table;
138 | clear: both;
139 | }
140 | }
141 |
142 | //-----------------------------------------
143 | // Reset
144 | //-----------------------------------------
145 |
146 | @mixin ul-reset() {
147 | padding: 0;
148 | margin: 0;
149 | list-style: none;
150 | -webkit-margin-start: 0px;
151 | -webkit-margin-end: 0px;
152 | -webkit-padding-start: 0px;
153 | -webkit-margin-before: 0px;
154 | -webkit-margin-after: 0px;
155 |
156 | }
157 |
158 |
--------------------------------------------------------------------------------
/src/compile/tsc.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const exec = require('child_process').exec;
4 | const util = require('./../util.js');
5 | const log = require('./../log.js');
6 | const config = require('./../config');
7 | const cli = require('./../../cli.config.json');
8 |
9 | class TSBuilder {
10 |
11 | constructor() {}
12 |
13 | compile(tsConfigPath) {
14 |
15 | return new Promise((res) => {
16 |
17 | let hasCompiled = false;
18 | log.process('typescript');
19 |
20 | let tsc = exec(path.normalize(path.resolve('node_modules', '.bin', 'tsc') +
21 | ' -p ' + tsConfigPath), {}, function (error, stdout, stderr) {
22 | log.stop('typescript');
23 | if (error) {
24 | log.warn(stdout);
25 | } else {
26 | log.message('Compilation complete.', ['TypeScript']);
27 | res('done');
28 | }
29 | });
30 |
31 | });
32 | }
33 |
34 |
35 | compileToCommonJS(filePath, outFile) {
36 |
37 | const tscPath = path.join(config.projectRoot, 'node_modules', '.bin', 'tsc');
38 | return new Promise((res) => {
39 |
40 | if(!outFile) outFile = filePath.replace('.ts', '.js');
41 |
42 | log.process('typescript');
43 |
44 | exec(`${tscPath} ${filePath} --outFile ${outFile} --target es5 --module commonjs --emitDecoratorMetadata true --experimentalDecorators true --sourceMap true --moduleResolution node --typeRoots node --lib dom,es2017`,
45 | { silent: true },
46 | (error) => {
47 | log.stop('typescript');
48 | if (error.killed) {
49 | log.error(error);
50 | } else {
51 | res();
52 | }
53 | });
54 |
55 | });
56 | }
57 |
58 | compileMain() {
59 |
60 | return new Promise((res, rej) => {
61 |
62 | const outFile = path.join(config.projectRoot, config.build, 'src', 'main.ts');
63 | const tscPath = path.join(config.projectRoot, 'node_modules', '.bin', 'tsc');
64 |
65 | fs.readFile(path.join(config.projectRoot, 'src', 'main.ts'), 'utf8', (err, contents) => {
66 |
67 | if (!err) {
68 | contents = contents.replace("./out-tsc/" + config.src + "/app/app.module.ngfactory", config.src + "/app/app.module");
69 | contents = contents.replace("import { enableProdMode } from '@angular/core';", '');
70 | contents = contents.replace("enableProdMode();", "");
71 | contents = contents.replace(/platformBrowser/g, "platformBrowserDynamic");
72 | contents = contents.replace(/AppModuleNgFactory/g, "AppModule");
73 | contents = contents.replace("@angular/platform-browser", "@angular/platform-browser-dynamic");
74 | contents = contents.replace("bootstrapModuleFactory", "bootstrapModule");
75 | fs.writeFile(outFile, contents, (err) => {
76 | if (!err) {
77 |
78 | let transpile = exec(`${tscPath} ${outFile} --target es5 --module commonjs --emitDecoratorMetadata true --experimentalDecorators true --sourceMap true --moduleResolution node --typeRoots node --lib dom,es2017`,
79 | { silent: true },
80 | (error, stdout, stderr) => {
81 | rm(outFile);
82 | if(error.killed) {
83 | log.error(error);
84 | } else {
85 | res();
86 | }
87 | });
88 | } else {
89 | rej(err);
90 | }
91 | });
92 | } else {
93 | rej(err);
94 | }
95 |
96 | });
97 |
98 | });
99 | }
100 |
101 |
102 |
103 | }
104 |
105 |
106 | module.exports = TSBuilder;
107 |
--------------------------------------------------------------------------------
/src/build/jit.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 | const path = require('path');
3 | const fs = require('fs');
4 | const chokidar = require('chokidar');
5 | const Build = require('./index.js');
6 | const SassBuilder = require('./../style/sass.js');
7 | const PostCSSBuilder = require('./../style/postcss.js');
8 | const TSBuilder = require('./../compile/tsc.js');
9 | const Watcher = require('./../watch.js');
10 | const util = require('./../util.js');
11 | const log = require('./../log.js');
12 | const config = require('./../config');
13 | const cli = require('./../../cli.config.json');
14 |
15 | class JitBuild extends Build {
16 |
17 | constructor() {
18 | super();
19 | }
20 |
21 | init() {
22 | this.pre();
23 | }
24 |
25 |
26 | build() {
27 |
28 | const env = 'dev';
29 | const sassBuilder = new SassBuilder({ dist: config.build });
30 | const postcssBuilder = new PostCSSBuilder({ dist: config.build, sourceMap: true });
31 | const jitBuilder = new TSBuilder();
32 | const libCheck = config.projects[config.project].architect.build.options.lib && config.projects[config.project].architect.build.options.lib[cli.env];
33 |
34 | (async () => {
35 | const lib = await util.copyLib(libCheck ? config.projects[config.project].architect.build.options.lib[cli.env] : config.lib['dev'],
36 | libCheck ? config.projects[config.project].architect.build.options.lib.src : config.lib.src,
37 | libCheck ? config.projects[config.project].architect.build.options.lib.dist : config.lib.dist);
38 | })();
39 |
40 | (async () => {
41 | const html = await util.copyBatch(ls(path.normalize(config.src + '/app/**/*.html')), config.build);
42 | const publicDir = await util.copyDir(path.normalize(config.src + '/public'), config.build);
43 | const template = await util.formatIndex(path.normalize(config.src + '/public/index.html'));
44 | })();
45 |
46 | (async () => {
47 | const sass = await sassBuilder.batch(ls(path.normalize(config.src + '/**/*.scss')));
48 | const postcss = await postcssBuilder.batch(sass);
49 | const src = await jitBuilder.compile(path.join('src', 'tsconfig.' + cli.build + '.json'));
50 | this.post();
51 | })();
52 |
53 | //if (!fs.existsSync(path.join(config.build, 'main.js'))) {
54 | (async () => {
55 | const main = await jitBuilder.compileMain().then((res) => {
56 | log.message('compiled main.js');
57 | });
58 | })();
59 | //}
60 |
61 | }
62 |
63 | pre() {
64 |
65 | if (cli.program.clean === true) {
66 | util.cleanBuild();
67 | }
68 |
69 | if (util.hasHook('pre')) {
70 |
71 | config.projects[config.project].architect.build.hooks[cli.env].pre(process.argv).then(() => {
72 | this.build();
73 | });
74 |
75 | } else {
76 |
77 | this.build();
78 |
79 | }
80 |
81 | this.emitter.emit('hook', {
82 | payload: {
83 | step: 'pre'
84 | }
85 | });
86 |
87 | }
88 |
89 | post() {
90 |
91 | if (cli.program.env) {
92 | cp(path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.program.env + '.js'), path.join(this.outputPath, 'src', 'environments', 'environment.js'));
93 | cp(path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.program.env + '.js.map'), path.join(this.outputPath, 'src', 'environments', 'environment.js.map'));
94 | cp(path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.program.env + '.ngsummary.json'), path.join(this.outputPath, 'src', 'environments', 'environment.ngsummary.json'));
95 | }
96 |
97 | if (util.hasHook('post')) config.projects[config.project].architect.build.hooks[cli.env].post(process.argv);
98 |
99 | if (cli.program.watch === true) {
100 | const watcher = new Watcher();
101 | }
102 |
103 | if (cli.program.watch === true && util.hasHook('watch') && config.projects[config.project].architect.build.hooks[cli.env].watch.dist) {
104 |
105 | const distWatcher = chokidar.watch([this.outputPath], {
106 | ignored: /[\/\\]\./,
107 | persistent: true
108 | }).on('change', filePath => {
109 |
110 | config.projects[config.project].architect.build.hooks[cli.env].watch.dist(filePath);
111 |
112 | });
113 |
114 | }
115 |
116 | if (!util.hasArg('watch')) {
117 | log.break();
118 | ls(this.outputPath).forEach((file) => {
119 | log.logFileStats(path.join(this.outputPath, file));
120 | });
121 | }
122 |
123 | if (util.hasArg('serve')) {
124 | util.serve(cli.program.watch);
125 | }
126 |
127 | this.emitter.emit('hook', {
128 | payload: {
129 | step: 'post'
130 | }
131 | });
132 |
133 |
134 | }
135 |
136 | }
137 |
138 | module.exports = JitBuild;
--------------------------------------------------------------------------------
/src/style/sass.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 |
3 | const sass = require('node-sass');
4 | const path = require('path');
5 | const fs = require('fs');
6 | const util = require('./../util.js');
7 | const log = require('./../log.js');
8 | const config = require('./../config');
9 | const cli = require('./../../cli.config.json');
10 |
11 | class Sass {
12 | constructor(sassConfig) {
13 | this.sassConfig = sassConfig;
14 | }
15 |
16 | batch(fileList) {
17 |
18 | if (!fs.existsSync(path.join(this.sassConfig.dist, 'style'))) {
19 | // TODO: figure out best way to handle use case without any global style
20 | mkdir('-p', path.join(this.sassConfig.dist, 'style'));
21 | }
22 |
23 | return new Promise(res => {
24 | try {
25 |
26 | const styles = config.projects[config.project].architect.build.options.styles;
27 | const globalFiles = styles.map((stylePath) => {
28 | return this.file(stylePath);
29 | });
30 |
31 | const files = fileList.filter((filePath, index) => {
32 | return (filePath && filePath.replace(/^.*[\\\/]/, '')[0] !== '_' &&
33 | styles.indexOf(filePath) === -1);
34 | }).map((filePath) => {
35 | return this.file(filePath)
36 | });
37 |
38 | Promise.all(files.concat(globalFiles)).then((css) => {
39 | res(css);
40 | });
41 |
42 | } catch (err) {
43 | err.service = 'sass';
44 | log.error(err);
45 | }
46 | });
47 | }
48 |
49 | file(filePath) {
50 |
51 | let env;
52 |
53 | if (cli.env === 'jit') {
54 | env = 'dev';
55 | } else {
56 | env = cli.env;
57 | }
58 |
59 | const srcPath = util.getFilePath(filePath);
60 | const filename = util.getFileName(filePath);
61 | const styles = config.projects[config.project].architect.build.options.styles;
62 | const globalBaseNames = styles.map((stylePath) => {
63 | return path.dirname(stylePath);
64 | }).filter((value, index, self) => {
65 | return self.indexOf(value) === index;
66 | });
67 | // determine if file is global or not, swap .scss to .css in filename
68 | const isGlobal = new RegExp(globalBaseNames.join('|')).test(filePath);
69 | let outFile = filePath;
70 |
71 | if (isGlobal) {
72 |
73 | globalBaseNames.forEach((baseName) => {
74 | if (outFile.includes(config.src)) {
75 | outFile = path.normalize(outFile.replace(config.src, this.sassConfig.dist));
76 | }
77 | })
78 |
79 | }
80 |
81 | let outFilePath = util.getFilePath(outFile);
82 |
83 |
84 | if (cli.env === 'dev' || cli.env === 'prod' || cli.env === 'lib') {
85 | outFilePath = util.getFilePath(outFile);
86 | }
87 | if (cli.env === 'jit' && srcPath.indexOf(config.src + '/style') === -1) {
88 | outFilePath = util.getFilePath(path.join(this.sassConfig.dist, outFile));
89 | }
90 |
91 | outFile = path.join(outFilePath, filename.replace('scss', 'css'));
92 |
93 | // this file is global w/ underscore and should not be compiled, compile global files instead
94 |
95 | if (isGlobal && filename[0] === '_') {
96 | return Promise.all(
97 | styles.map(filePath => {
98 | return this.file(filePath);
99 | })
100 | );
101 | }
102 |
103 | // TODO: figure out better way to transform paths based on needs
104 |
105 | // if (cli.program.build === 'prod' &&
106 | // isGlobal === false) {
107 | // outFilePath = path.join('out-tsc', outFilePath);
108 | // outFile = path.join('out-tsc', outFile);
109 | // }
110 |
111 | if (cli.program.build === 'lib' &&
112 | isGlobal === true) {
113 | outFilePath = path.join(this.sassConfig.dist, outFilePath.replace('src/', '').replace('src\\', ''));
114 | outFile = path.join(outFilePath, path.basename(outFile));
115 | }
116 |
117 |
118 | return new Promise(res => {
119 |
120 | const renderConfig = config.projects[config.project].architect.build.options.stylePreprocessorOptions;
121 | renderConfig.file = filePath;
122 | renderConfig.outFile = outFile;
123 |
124 | if (fs.existsSync(outFilePath) == false) {
125 | mkdir('-p', outFilePath);
126 | }
127 |
128 | if (env === 'dev') {
129 | renderConfig.sourceComments = true;
130 | }
131 |
132 | if (this.sassConfig.sourceMap) {
133 | renderConfig.sourceMap = this.sassConfig.sourceMap;
134 | }
135 |
136 | sass.render(renderConfig, (error, result) => {
137 | if (error) {
138 | log.line();
139 | error.service = 'sass';
140 | log.error(error);
141 | } else {
142 | fs.writeFile(outFile, result.css, err => {
143 | if (err) {
144 | log.line();
145 | err.service = 'sass';
146 | log.error(err);
147 | }
148 | if (res) {
149 | res(outFile);
150 | }
151 | });
152 | }
153 | });
154 | });
155 | }
156 | }
157 |
158 | module.exports = Sass;
159 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | require('shelljs/global');
4 | const findup = require('findup');
5 | const fs = require('fs');
6 | const path = require('path');
7 | const colors = require('colors');
8 | const program = require('commander');
9 | const cliRoot = findup.sync(__dirname, 'package.json');
10 | const processRoot = path.join(path.dirname(process.cwd()), path.basename(process.cwd()));
11 | const package = require(__dirname + '/package.json');
12 |
13 | if (process.argv.indexOf('scaffold') > -1) {
14 | process.argv.push('--verbose');
15 | }
16 |
17 | program
18 | .version(package.version)
19 | .usage('')
20 | .option('new [string]', 'scaffold new development environment in directory by name, i.e. ngr new my-app')
21 | .option('--src [string]', 'specify a path to an existing src folder')
22 | .option('--skip-install [bool]', 'prevents install during scaffold')
23 | .option('--yarn [bool]', 'use yarn instead of npm to install')
24 | .option('--prettier [bool]', 'scaffold a new workspace with prettier installed')
25 | .option('--ssl [bool]', 'scaffold a new workspace with https express server')
26 | .option('--angularVersion [string]', 'scaffold a new workspace with a specific version of angular')
27 | .option('build [env]', 'build the application')
28 | .option('--env [string]', 'use that particular environment.ts during the build, just like @angular/cli')
29 | .option('--clean [bool]', 'destroy the build folder prior to compilation, default for prod')
30 | .option('--watch [bool]', 'listen for changes in filesystem and rebuild')
31 | .option('--config [string]', 'path to configuration file for library build')
32 | .option('--deploy [bool]', 'call deploy build hook for library build')
33 | .option('--verbose [bool]', 'log all messages in list format')
34 | .option('--closure [bool]', 'bundle and optimize with closure compiler (default)')
35 | .option('--rollup [bool]', 'bundle with rollup and optimize with closure compiler')
36 | .option('--webpack [bool]', 'use @angular/cli to build')
37 | .option('--keepTempFiles [bool]', 'retain the /tmp and /out-tsc directories post production build')
38 | .option('g, generate [string]', 'generate schematics packaged with angular-rollup')
39 | .option('serve, --serve [bool]', 'spawn the local express server')
40 | .parse(process.argv);
41 |
42 | let cli = () => {
43 | let config = require('./src/config');
44 | let util = require('./src/util');
45 | let log = require('./src/log');
46 | let Scaffold = require('./src/scaffold/index');
47 |
48 | if (program.generate) {
49 | if (program.generate === 'library') program.generate = 'lib';
50 | const Generator = require('./src/generate/' + program.generate + '.js');
51 | let build = new Generator().init();
52 | }
53 |
54 | if (program.build) {
55 | log.destroy();
56 | const BuildScript = require('./src/build/' + program.build + '.js');
57 | let build = new BuildScript().init();
58 | }
59 |
60 | if (program.new) {
61 | log.destroy();
62 | let scaffold = new Scaffold(program.new, path.join(processRoot, program.new));
63 | scaffold.basic();
64 | }
65 |
66 | if (program.serve && !program.build) {
67 | log.destroy();
68 | util.serve();
69 | }
70 | };
71 |
72 |
73 | if (process.argv.indexOf('new') > -1) {
74 | if (fs.existsSync(path.join(processRoot, program.new))) {
75 | console.log(colors.red(program.new + ' already exists'));
76 | process.exit(1);
77 | }
78 | if (!fs.existsSync(path.join(processRoot, program.new))) mkdir(path.join(processRoot, program.new));
79 | cp(path.join(cliRoot, 'src', 'scaffold', 'root', 'ngr.config.js'), path.join(processRoot, program.new));
80 | }
81 |
82 |
83 | const env = program.env ? program.env : (program.build === 'dev' ? 'dev' : 'prod');
84 |
85 | fs.writeFile(
86 | __dirname + '/cli.config.json',
87 | JSON.stringify(
88 | {
89 | env: env,
90 | program: program,
91 | build: program.build,
92 | projectRoot: program.new ? path.join(processRoot, program.new) : processRoot,
93 | },
94 | null,
95 | 4
96 | ),
97 | 'utf-8',
98 | cli
99 | );
100 |
101 | let exitHandler = (options, err) => {
102 | if (fs.existsSync(path.join('config', 'environments'))) {
103 | rm('-rf', path.join('src', 'environments'));
104 | cp('-R', path.join('config', 'environments'), 'src');
105 | rm('-rf', path.join('config', 'environments'));
106 | }
107 | if (err && err !== 'SIGINT') {
108 | process.stdout.write('\n');
109 | console.log(colors.red('NGR ERROR', err));
110 | process.stdout.write('\n');
111 | process.exit(1);
112 | }
113 | if (options.exit) {
114 | process.exit(0);
115 | }
116 | };
117 |
118 | // do something when app is closing
119 | process.on('exit', exitHandler.bind(null, { cleanup: true }));
120 |
121 | // catches ctrl+c event
122 | process.on('SIGINT', exitHandler.bind(null, { exit: true }));
123 |
124 | // catches "kill pid" (for example: nodemon restart)
125 | process.on('SIGUSR1', exitHandler.bind(null, { exit: true }));
126 | process.on('SIGUSR2', exitHandler.bind(null, { exit: true }));
127 |
128 | //catches uncaught exceptions
129 | process.on('uncaughtException', exitHandler.bind(null, { exit: true }));
130 |
131 | process.on('unhandledRejection', err => {
132 | process.stdout.write('\n');
133 | console.log(colors.red('NGR ERROR', err))
134 | process.stdout.write('\n');
135 | });
136 |
--------------------------------------------------------------------------------
/src/compile/ngc.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const colors = require('colors');
4 | const exec = require('child_process').exec;
5 | const util = require('./../util.js');
6 | const log = require('./../log.js');
7 | const config = require('./../config');
8 | const cli = require('./../../cli.config.json');
9 |
10 | let interval;
11 |
12 | class AOTBuilder {
13 |
14 | constructor() { }
15 |
16 | compile(tsConfigPath) {
17 |
18 | return new Promise((res) => {
19 |
20 | let hasCompiled = false;
21 |
22 | if (util.hasArg('watch')) {
23 |
24 | log.process('@angular/compiler');
25 |
26 | const ngc = exec(path.join(config.projectRoot, 'node_modules', '.bin', 'ngc') + ' -p ' + tsConfigPath + ' --watch', { silent: true });
27 |
28 | ngc.stderr.on('data', (stderr) => {
29 |
30 | log.stop('@angular/compiler');
31 | let hasLine = false;
32 |
33 | if (hasCompiled == false && stderr.includes('Compilation complete.')) {
34 | hasCompiled = true;
35 | if (!cli.program.verbose) log.destroy();
36 | log.message('Compilation complete. Watching for file changes.', ['TypeScript']);
37 | res();
38 | } else {
39 | this.handleError(stderr);
40 | }
41 |
42 | });
43 |
44 | } else {
45 |
46 | log.process('@angular/compiler');
47 |
48 | let ngc = exec(path.join(config.projectRoot, 'node_modules', '.bin', 'ngc') + ' -p ' + tsConfigPath, { silent: true }, (error, stdout, stderr) => {
49 | //if (config.build !== 'lib') clearInterval(interval);
50 | log.stop('@angular/compiler');
51 | if (stderr) {
52 | this.handleError(stderr);
53 | } else {
54 | if (!cli.program.verbose) log.destroy();
55 | log.message('Compilation complete.', ['TypeScript']);
56 | if (cli.build === 'dev') {
57 | log.break();
58 | }
59 |
60 | res();
61 | }
62 | });
63 |
64 |
65 | }
66 |
67 | });
68 | }
69 |
70 | handleError(stderr) {
71 |
72 | if (stderr.includes('Compilation complete.')) {
73 | log.success(stderr, ['TypeScript']);
74 | }
75 | else if (stderr === ': Compilation failed. Watching for file changes.') {
76 | log.fail(stderr);
77 | }
78 | else if (stderr.includes('File change')) {
79 | log.success(stderr, ['TypeScript']);
80 | }
81 | else {
82 |
83 | if (stderr.split('\n').length > 0) {
84 | //if (!hasLine) log.line();
85 | //hasLine = true;
86 | let tsError = stderr.split('\n').filter((e) => {
87 | return e.length > 0;
88 | }).forEach((e) => {
89 | if (e.includes('error TS')) {
90 | //console.log('TS ERROR:', e);
91 | log.formatTSError(e)
92 | }
93 | });
94 |
95 | }
96 |
97 | if (stderr.split(/\n:\s/g).length > 0) {
98 | //if (!hasLine) log.line();
99 | //hasLine = true;
100 | let templateErr = stderr.split(/\n:\s/g).filter((e) => {
101 | return e.includes('error TS') === false;
102 | }).forEach((e) => {
103 | //console.log('Template ERROR:', e);
104 | log.formatTemplateError(e)
105 | });
106 |
107 | }
108 |
109 | }
110 |
111 | }
112 |
113 |
114 | compileMain() {
115 |
116 | return new Promise((res, rej) => {
117 | let inFile = path.join(config.src, 'main.ts');
118 | let outFile = path.join(config.projectRoot, config.build, 'main.ts');
119 |
120 | const tscPath = path.join(config.projectRoot, 'node_modules', '.bin', 'tsc');
121 | const tsConfig = JSON.parse(fs.readFileSync(path.join(config.projectRoot, 'src', 'tsconfig.' + cli.build + '.json'), 'utf8'));
122 | const modulePattern = tsConfig.compilerOptions.module;
123 | const jsTarget = tsConfig.compilerOptions.target;
124 |
125 | if (cli.build === 'prod') {
126 | outFile = path.join('out-tsc/tmp/main.ts');
127 | }
128 |
129 | fs.readFile(inFile, 'utf8', (err, contents) => {
130 | if (!err) {
131 |
132 | contents = contents.replace(/platformBrowserDynamic/g, 'platformBrowser');
133 | contents = contents.replace(/platform-browser-dynamic/g, 'platform-browser');
134 | contents = contents.replace(/bootstrapModule/g, 'bootstrapModuleFactory');
135 | contents = contents.replace(/AppModule/g, 'AppModuleNgFactory');
136 | if (cli.build === 'dev') {
137 | contents = contents.replace('./app/app.module', './src/app/app.module.ngfactory');
138 | } if (cli.build === 'prod') {
139 | contents = contents.replace('./app/app.module', './app/app.module.ngfactory');
140 | }
141 |
142 | fs.writeFile(outFile, contents, (err) => {
143 | if (!err) {
144 |
145 | let transpile = exec(`${tscPath} ${outFile} --target ${jsTarget} --module ${modulePattern} --emitDecoratorMetadata true --experimentalDecorators true --sourceMap true --moduleResolution node --typeRoots node --lib dom,es2017`,
146 | { silent: true },
147 | (error, stdout, stderr) => {
148 | rm(outFile);
149 | if (error && error.killed) {
150 | log.formatTSError(error);
151 | } else {
152 | res();
153 | }
154 | });
155 | }
156 | else {
157 | rej(err);
158 | }
159 | });
160 | } else {
161 | rej(err);
162 | }
163 |
164 | });
165 |
166 | });
167 | }
168 |
169 |
170 |
171 | }
172 |
173 |
174 | module.exports = AOTBuilder;
175 |
--------------------------------------------------------------------------------
/src/build/dev.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const chokidar = require('chokidar');
4 | const spawn = require('child_process').spawn;
5 | const Build = require('./index.js');
6 | const SassBuilder = require('./../style/sass.js');
7 | const PostCSSBuilder = require('./../style/postcss.js');
8 | const AOTBuilder = require('./../compile/ngc.js');
9 | const Watcher = require('./../watch.js');
10 | const util = require('./../util.js');
11 | const log = require('./../log.js');
12 | const config = require('./../config');
13 | const cli = require('./../../cli.config.json');
14 |
15 | class DevBuild extends Build {
16 | constructor() {
17 | super();
18 | }
19 |
20 | init() {
21 | this.pre();
22 | }
23 |
24 | build() {
25 | const sassBuilder = new SassBuilder({ dist: config.build });
26 | const postcssBuilder = new PostCSSBuilder({ dist: config.build, sourceMap: true });
27 | const aotBuilder = new AOTBuilder();
28 | const libCheck =
29 | config.projects[config.project].architect.build.options.lib &&
30 | config.projects[config.project].architect.build.options.lib[cli.build];
31 |
32 | (async () => {
33 | const lib = await util.copyLib(
34 | libCheck ? config.projects[config.project].architect.build.options.lib[cli.build] : config.lib['dev'],
35 | libCheck ? config.projects[config.project].architect.build.options.lib.src : config.lib.src,
36 | libCheck ? config.projects[config.project].architect.build.options.lib.dist : config.lib.dist
37 | );
38 | })();
39 |
40 | (async () => {
41 | const publicDir = await util.copyDir(path.normalize(config.src + '/public'), config.build);
42 | const template = await util.formatIndex(path.normalize(config.src + '/public/index.html'));
43 | })();
44 |
45 | (async () => {
46 | const sass = await sassBuilder.batch(ls(path.normalize(config.src + '/**/*.scss')));
47 | const postcss = await postcssBuilder.batch(sass);
48 | await log.message('styled components');
49 | const main = await aotBuilder.compileMain();
50 | await log.message('compiled main.js');
51 | const src = await aotBuilder.compile(path.join('src', 'tsconfig.' + cli.build + '.json'));
52 | this.post();
53 | })();
54 | }
55 |
56 | pre() {
57 | let build = () => {
58 | //cp(path.normalize('config/postcss.' + cli.build + '.js'), 'postcss.config.js');
59 |
60 | if (util.hasHook('pre')) {
61 | config.projects[config.project].architect.build.hooks[cli.build].pre(process.argv).then(() => {
62 | if (cli.program.webpack === true) {
63 | spawn('ng', ['serve'], { shell: true, stdio: 'inherit' });
64 | } else {
65 | this.build();
66 | }
67 | });
68 | } else {
69 | if (cli.program.webpack === true) {
70 | spawn('ng', ['serve'], { shell: true, stdio: 'inherit' });
71 | } else {
72 | this.build();
73 | }
74 | }
75 | };
76 |
77 | if (cli.program.clean) {
78 | util.cleanBuild().then(() => {
79 | build();
80 | });
81 | } else {
82 | build();
83 | }
84 |
85 | this.emitter.emit('hook', {
86 | payload: {
87 | step: 'pre'
88 | }
89 | });
90 | }
91 |
92 | post() {
93 |
94 |
95 | if (!fs.existsSync(path.join(this.outputPath, 'environments'))) {
96 | mkdir('-p', path.join(this.outputPath, 'environments'));
97 | }
98 |
99 | if (cli.env === 'dev') {
100 | cp(
101 | path.join(this.outputPath, 'src', 'environments', 'environment.js'),
102 | path.join(this.outputPath, 'environments', 'environment.js')
103 | );
104 | cp(
105 | path.join(this.outputPath, 'src', 'environments', 'environment.js.map'),
106 | path.join(this.outputPath, 'environments', 'environment.js.map')
107 | );
108 | if (fs.existsSync(path.join(this.outputPath, 'src', 'environments', 'environment.ngsummary.json'))) {
109 | cp(
110 | path.join(this.outputPath, 'src', 'environments', 'environment.ngsummary.json'),
111 | path.join(this.outputPath, 'environments', 'environment.ngsummary.json')
112 | );
113 | }
114 | } else {
115 | cp(
116 | path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.env + '.js'),
117 | path.join(this.outputPath, 'environments', 'environment.js')
118 | );
119 |
120 | fs.readFile(path.join(this.outputPath, 'environments', 'environment.js'), 'utf-8', (err, stdout) => {
121 | stdout = stdout.replace(`environment.${cli.env}.js`, 'environment.js');
122 | fs.writeFile(path.join(this.outputPath, 'environments', 'environment.js'), stdout, 'utf-8', () => {});
123 | });
124 |
125 | cp(
126 | path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.env + '.js.map'),
127 | path.join(this.outputPath, 'environments', 'environment.js.map')
128 | );
129 |
130 | fs.readFile(path.join(this.outputPath, 'environments', 'environment.js.map'), 'utf-8', (err, stdout) => {
131 | stdout = stdout.replace(`environment.${cli.env}.ts`, 'environment.ts');
132 | stdout = stdout.replace(`environment.${cli.env}.js`, 'environment.js');
133 | fs.writeFile(path.join(this.outputPath, 'environments', 'environment.js.map'), stdout, 'utf-8', () => {});
134 | });
135 |
136 | cp(
137 | path.join(this.outputPath, 'src', 'environments', 'environment.' + cli.env + '.ngsummary.json'),
138 | path.join(this.outputPath, 'environments', 'environment.ngsummary.json')
139 | );
140 |
141 | fs.readFile(path.join(this.outputPath, 'environments', 'environment.ngsummary.json'), 'utf-8', (err, stdout) => {
142 | stdout = stdout.replace(`environment.${cli.env}`, 'environment');
143 | fs.writeFile(path.join(this.outputPath, 'environments', 'environment.ngsummary.json'), stdout, 'utf-8', () => {});
144 | });
145 |
146 | }
147 |
148 | if (util.hasHook('post')) config.projects[config.project].architect.build.hooks[cli.build].post(process.argv);
149 |
150 | if (cli.program.watch === true) {
151 | const watcher = new Watcher();
152 | }
153 |
154 | if (cli.program.watch === true && util.hasHook('watch') && config.projects[config.project].architect.build.hooks[cli.build].watch.dist) {
155 | const distWatcher = chokidar
156 | .watch([this.outputPath], {
157 | ignored: /[\/\\]\./,
158 | persistent: true,
159 | })
160 | .on('change', filePath => {
161 | config.projects[config.project].architect.build.hooks[cli.build].watch.dist(filePath);
162 | });
163 | }
164 |
165 | if (!util.hasArg('watch')) {
166 | log.break();
167 | log.buildStats(this.startTime);
168 | }
169 |
170 | if (util.hasArg('serve')) {
171 | util.serve(cli.program.watch);
172 | }
173 | this.emitter.emit('hook', {
174 | payload: {
175 | step: 'post'
176 | }
177 | });
178 | }
179 | }
180 |
181 | module.exports = DevBuild;
182 |
--------------------------------------------------------------------------------
/src/build/prod.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 | const path = require('path');
3 | const fs = require('fs');
4 | const spawn = require('child_process').spawn;
5 | const Build = require('./index.js');
6 | const SassBuilder = require('./../style/sass.js');
7 | const PostCSSBuilder = require('./../style/postcss.js');
8 | const AOTBuilder = require('./../compile/ngc.js');
9 | const ClosureBuilder = require('./../bundle/closure.js');
10 | const RollupBuilder = require('./../bundle/rollup.js');
11 | const util = require('./../util.js');
12 | const log = require('./../log.js');
13 | const config = require('./../config');
14 | const cli = require('./../../cli.config.json');
15 | const buildOptimizer = require('@angular-devkit/build-optimizer').buildOptimizer;
16 |
17 |
18 | class ProdBuild extends Build {
19 |
20 | constructor() {
21 | super();
22 | }
23 |
24 | init() {
25 | this.pre();
26 | }
27 |
28 | build() {
29 |
30 | const sassBuilder = new SassBuilder({ dist: config.build, sourceMap: false });
31 | const postcssBuilder = new PostCSSBuilder({ dist: config.build, sourceMap: false });
32 | const aotBuilder = new AOTBuilder();
33 | const closureBuilder = new ClosureBuilder();
34 | const rollupBuilder = new RollupBuilder();
35 | const libCheck = config.projects[config.project].architect.build.options.lib && config.projects[config.project].architect.build.options.lib[cli.build];
36 |
37 | (async () => {
38 | const publicDir = await util.copyDir(path.normalize(config.src + '/public'), config.build);
39 | const template = await util.formatIndex(path.normalize(config.src + '/public/index.html'));
40 | const vendor = await util.formatVendorScripts(libCheck ? config.projects[config.project].architect.build.options.lib[cli.build] : config.lib['prod'],
41 | libCheck ? config.projects[config.project].architect.build.options.lib.src : config.lib.src,
42 | libCheck ? config.build : config.build);
43 | const concatVendor = await util.concatVendorScripts(libCheck ? config.build : config.build);
44 | })();
45 |
46 | (async () => {
47 | // const copyMain = await cp('main.ts', 'main.js');
48 | const copy = await cp('-R', path.normalize(config.src + '/'), path.normalize('./tmp'));
49 | // // remove moduleId prior to ngc build. TODO: look for another method.
50 | // const stripModuleId = await ls(path.normalize('out-tsc/**/*.ts')).forEach(function (file) {
51 | // sed('-i', /^.*moduleId: module.id,.*$/, '', file);
52 | // });
53 | if (ls(path.normalize('tmp/**/*.scss')).length > 0) {
54 |
55 | const sass = await sassBuilder.batch(ls(path.normalize('./tmp/**/*.scss')));
56 | await postcssBuilder.batch(sass);
57 | await this.transformSCSSPathstoCSS();
58 |
59 | }
60 | else if (ls(path.normalize('tmp/**/*.css')).length > 0) {
61 |
62 | const cssFileList = ls(path.normalize('tmp/**/*.css'));
63 | await postcssBuilder.batch(cssFileList);
64 |
65 | }
66 |
67 | // rewrite tsconfig to compile tmp instead of src
68 | await sed('-i', 'src/', 'tmp/', path.join('tmp', 'tsconfig.' + cli.build + '.json'));
69 | // use tsconfig copied to tmp instead of src
70 | const src = await aotBuilder.compile(path.join('tmp', 'tsconfig.' + cli.build + '.json'));
71 |
72 | const main = await aotBuilder.compileMain();
73 | await log.message('copied main.ts');
74 | const buildOptimize = await ls(path.normalize('out-tsc/**/*.component.js')).forEach(function (file) {
75 | let content = fs.readFileSync(file, 'utf-8');
76 | fs.writeFileSync(file, buildOptimizer({ content: content }).content);
77 | });
78 |
79 | await mv(path.normalize('out-tsc/tmp'), path.normalize('out-tsc/src'));
80 |
81 | if (cli.program.rollup) {
82 | const prepRxjs = await this.buildRxjsFESM();
83 | const bundle = await rollupBuilder.bundle(path.join(config.projectRoot, 'rollup.config.js'));
84 | const optimize = await closureBuilder.bundle();
85 | } else {
86 | // use fesm instead for closure compiler, results in smaller bundles
87 | const prepRxjs = await this.buildRxjsFESM();
88 | const bundle = await closureBuilder.bundle();
89 | }
90 |
91 | this.post();
92 |
93 | })();
94 |
95 |
96 | }
97 |
98 | pre() {
99 |
100 | let build = () => {
101 |
102 | cp('-R', path.join('src', 'environments'), 'config');
103 | rm('-rf', path.join('tmp'));
104 | rm('-f', path.join('src', 'environments', 'environment.ts'));
105 | if (cli.env === 'dev') {
106 | cp(path.join('config', 'environments', 'environment.ts'), path.join('src', 'environments', 'environment.ts'));
107 | } else {
108 | cp(path.join('config', 'environments', 'environment.' + cli.env + '.ts'), path.join('src', 'environments', 'environment.ts'));
109 | }
110 | if (util.hasHook('pre')) {
111 |
112 | config.projects[config.project].architect.build.hooks[cli.env].pre(process.argv).then(() => {
113 | if (cli.program.webpack === true) {
114 | exec('ng build --prod', { shell: true, stdio: 'inherit' }, () => {
115 | this.post();
116 | });
117 | } else {
118 | this.build();
119 | }
120 | });
121 |
122 | } else {
123 |
124 | if (cli.program.webpack === true) {
125 | exec('ng build --prod', { shell: true, stdio: 'inherit' }, () => {
126 | this.post();
127 | });
128 | } else {
129 | this.build();
130 | }
131 |
132 | }
133 |
134 | }
135 |
136 | if (cli.program.clean !== false) {
137 |
138 | util.cleanBuild().then(() => {
139 | build();
140 | });
141 | } else {
142 |
143 | build();
144 | }
145 |
146 | this.emitter.emit('hook', {
147 | payload: {
148 | step: 'pre'
149 | }
150 | });
151 |
152 | }
153 |
154 | buildRxjsFESM() {
155 | return new Promise((res) => {
156 |
157 | let editFile = (filePath) => {
158 | return new Promise((res) => {
159 | fs.readFile(filePath, 'utf-8', (error, stdout, stderr) => {
160 | let pack = JSON.parse(stdout);
161 | pack.es2015 = pack.es2015.replace('_esm2015', '_fesm2015');
162 | log.message('editing ' + filePath);
163 | fs.writeFile(filePath, JSON.stringify(pack), () => {
164 | res(filePath);
165 | })
166 | });
167 | });
168 | };
169 |
170 | let rollup;
171 |
172 | if (process.platform === 'win32') {
173 | rollup = spawn('cmd', ['/c', path.join(config.projectRoot, 'node_modules', '.bin', 'rollup'), '-c', path.join('config', 'rollup.rxjs.js')]);
174 | } else {
175 | rollup = spawn(path.join(config.projectRoot, 'node_modules', '.bin', 'rollup'), ['-c', path.join('config', 'rollup.rxjs.js')]);
176 | }
177 |
178 | rollup.stdout.on('data', (msg) => {
179 | log.message(msg);
180 | });
181 |
182 | rollup.on('exit', () => {
183 | log.message('rollup completed');
184 | Promise.all([editFile('node_modules/rxjs/package.json'),
185 | editFile('node_modules/rxjs/operators/package.json'),
186 | editFile('node_modules/rxjs/ajax/package.json'),
187 | editFile('node_modules/rxjs/testing/package.json'),
188 | editFile('node_modules/rxjs/webSocket/package.json')])
189 | .then(data => {
190 | res();
191 | });
192 |
193 | });
194 | });
195 | }
196 |
197 | transformSCSSPathstoCSS() {
198 |
199 | return Promise.all(ls(path.normalize('tmp/**/*.ts')).map((filePath) => {
200 | return new Promise((res, rej) => {
201 |
202 | try {
203 | sed('-i', '.scss', '.css', filePath);
204 | res();
205 | } catch(err) {
206 | rej(err);
207 | }
208 |
209 | });
210 | }));
211 |
212 | }
213 |
214 |
215 | post() {
216 |
217 | if (!cli.program.keepTempFiles) {
218 | rm('-rf', 'tmp');
219 | rm('-rf', 'out-tsc');
220 | rm('-rf', 'dist/out-tsc');
221 | }
222 |
223 | const bundleArtifact = path.join(this.outputPath, 'bundle.es2015.js');
224 | // return environments to rightful place
225 | if (fs.existsSync(path.join('config', 'environments'))) {
226 | rm('-rf', path .join('src', 'environments'));
227 | cp('-R', path.join('config', 'environments'), 'src');
228 | rm('-rf', path.join('config', 'environments'));
229 | }
230 |
231 | if (util.hasHook('post')) config.projects[config.project].architect.build.hooks[cli.env].post(process.argv);
232 | if (fs.existsSync(path.normalize('main.js'))) {
233 | rm(path.normalize('main.js'));
234 | }
235 | if (fs.existsSync(bundleArtifact)) {
236 | rm(bundleArtifact);
237 | }
238 |
239 | log.break();
240 |
241 | if (cli.program.webpack === true) {
242 | ls(this.outputPath).forEach((file) => {
243 | log.logFileStats(path.join(this.outputPath, file));
244 | });
245 | } else {
246 | log.buildStats(this.startTime, this.outputPath);
247 | }
248 |
249 | if (util.hasArg('serve')) {
250 | util.serve(cli.program.watch);
251 | }
252 |
253 | this.emitter.emit('hook', {
254 | payload: {
255 | step: 'post'
256 | }
257 | });
258 | }
259 |
260 | }
261 |
262 | module.exports = ProdBuild;
263 |
--------------------------------------------------------------------------------
/src/scaffold/src/style/util/_normalize.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 |
6 | /* http://meyerweb.com/eric/tools/css/reset/
7 | v2.0 | 20110126
8 | License: none (public domain)
9 | */
10 |
11 | html, body, div, span, applet, object, iframe,
12 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
13 | a, abbr, acronym, address, big, cite, code,
14 | del, dfn, em, img, ins, kbd, q, s, samp,
15 | small, strike, strong, sub, sup, tt, var,
16 | b, u, i, center,
17 | dl, dt, dd, ol, ul, li,
18 | fieldset, form, label, legend,
19 | table, caption, tbody, tfoot, thead, tr, th, td,
20 | article, aside, canvas, details, embed,
21 | figure, figcaption, footer, header, hgroup,
22 | menu, nav, output, ruby, section, summary,
23 | time, mark, audio, video {
24 | margin: 0;
25 | padding: 0;
26 | border: 0;
27 | vertical-align: baseline;
28 | }
29 | /* HTML5 display-role reset for older browsers */
30 | article, aside, details, figcaption, figure,
31 | footer, header, hgroup, menu, nav, section {
32 | display: block;
33 | }
34 | body {
35 | line-height: 1;
36 | width: 100%;
37 | height: 100%;
38 | min-height: 100%;
39 | overflow: hidden;
40 | }
41 | blockquote, q {
42 | quotes: none;
43 | }
44 | blockquote:before, blockquote:after,
45 | q:before, q:after {
46 | content: '';
47 | content: none;
48 | }
49 | table {
50 | border-collapse: collapse;
51 | border-spacing: 0;
52 | }
53 |
54 | /*! normalize.css v3.0.1 | MIT License | git.io/normalize */
55 |
56 | /**
57 | * 1. Set default font family to sans-serif.
58 | * 2. Prevent iOS text size adjust after orientation change, without disabling
59 | * user zoom.
60 | */
61 |
62 | html {
63 | font-family: sans-serif; /* 1 */
64 | -ms-text-size-adjust: 100%; /* 2 */
65 | -webkit-text-size-adjust: 100%; /* 2 */
66 | min-height: 100%;
67 | }
68 |
69 | /**
70 | * Remove default margin.
71 | */
72 |
73 | body {
74 | margin: 0;
75 | }
76 |
77 | /* HTML5 display definitions
78 | ========================================================================== */
79 |
80 | /**
81 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
82 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
83 | * Correct `block` display not defined for `main` in IE 11.
84 | */
85 |
86 | article,
87 | aside,
88 | details,
89 | figcaption,
90 | figure,
91 | footer,
92 | header,
93 | hgroup,
94 | main,
95 | nav,
96 | section,
97 | summary {
98 | display: block;
99 | }
100 |
101 | /**
102 | * 1. Correct `inline-block` display not defined in IE 8/9.
103 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
104 | */
105 |
106 | audio,
107 | canvas,
108 | progress,
109 | video {
110 | display: inline-block; /* 1 */
111 | vertical-align: baseline; /* 2 */
112 | }
113 |
114 | /**
115 | * Prevent modern browsers from displaying `audio` without controls.
116 | * Remove excess height in iOS 5 devices.
117 | */
118 |
119 | audio:not([controls]) {
120 | display: none;
121 | height: 0;
122 | }
123 |
124 | /**
125 | * Address `[hidden]` styling not present in IE 8/9/10.
126 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
127 | */
128 |
129 | [hidden],
130 | template {
131 | display: none;
132 | }
133 |
134 | /* Links
135 | ========================================================================== */
136 |
137 | /**
138 | * Remove the gray background color from active links in IE 10.
139 | */
140 |
141 | a {
142 | background: transparent;
143 | text-decoration: none;
144 | }
145 |
146 | /**
147 | * Improve readability when focused and also mouse hovered in all browsers.
148 | */
149 |
150 | a:active,
151 | a:hover {
152 | outline: 0;
153 | }
154 |
155 | /* Text-level semantics
156 | ========================================================================== */
157 |
158 | /**
159 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
160 | */
161 |
162 | abbr[title] {
163 | border-bottom: 1px dotted;
164 | }
165 |
166 | /**
167 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
168 | */
169 |
170 | b,
171 | strong {
172 | font-weight: bold;
173 | }
174 |
175 | /**
176 | * Address styling not present in Safari and Chrome.
177 | */
178 |
179 | dfn {
180 | font-style: italic;
181 | }
182 |
183 | /**
184 | * Address variable `h1` font-size and margin within `section` and `article`
185 | * contexts in Firefox 4+, Safari, and Chrome.
186 | */
187 |
188 | h1 {
189 | font-size: 2em;
190 | margin: 0.67em 0;
191 | }
192 |
193 | /**
194 | * Address styling not present in IE 8/9.
195 | */
196 |
197 | mark {
198 | background: #ff0;
199 | color: #000;
200 | }
201 |
202 | /**
203 | * Address inconsistent and variable font size in all browsers.
204 | */
205 |
206 | small {
207 | font-size: 80%;
208 | }
209 |
210 | /**
211 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
212 | */
213 |
214 | sub,
215 | sup {
216 | font-size: 75%;
217 | line-height: 0;
218 | position: relative;
219 | vertical-align: baseline;
220 | }
221 |
222 | sup {
223 | top: -0.5em;
224 | }
225 |
226 | sub {
227 | bottom: -0.25em;
228 | }
229 |
230 | /* Embedded content
231 | ========================================================================== */
232 |
233 | /**
234 | * Remove border when inside `a` element in IE 8/9/10.
235 | */
236 |
237 | img {
238 | border: 0;
239 | }
240 |
241 | /**
242 | * Correct overflow not hidden in IE 9/10/11.
243 | */
244 |
245 | svg:not(:root) {
246 | overflow: hidden;
247 | }
248 |
249 | /* Grouping content
250 | ========================================================================== */
251 |
252 | /**
253 | * Address margin not present in IE 8/9 and Safari.
254 | */
255 |
256 | figure {
257 | margin: 1em 40px;
258 | }
259 |
260 | /**
261 | * Address differences between Firefox and other browsers.
262 | */
263 |
264 | hr {
265 | -moz-box-sizing: content-box;
266 | box-sizing: content-box;
267 | height: 0;
268 | }
269 |
270 | /**
271 | * Contain overflow in all browsers.
272 | */
273 |
274 | pre {
275 | overflow: auto;
276 | }
277 |
278 | /**
279 | * Address odd `em`-unit font size rendering in all browsers.
280 | */
281 |
282 | code,
283 | kbd,
284 | pre,
285 | samp {
286 | font-family: monospace, monospace;
287 | font-size: 1em;
288 | }
289 |
290 | /* Forms
291 | ========================================================================== */
292 |
293 | /**
294 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
295 | * styling of `select`, unless a `border` property is set.
296 | */
297 |
298 | /**
299 | * 1. Correct color not being inherited.
300 | * Known issue: affects color of disabled elements.
301 | * 2. Correct font properties not being inherited.
302 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
303 | */
304 |
305 | button,
306 | input,
307 | optgroup,
308 | select,
309 | textarea {
310 | color: inherit; /* 1 */
311 | font: inherit; /* 2 */
312 | margin: 0; /* 3 */
313 | }
314 |
315 | /**
316 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
317 | */
318 |
319 | button {
320 | overflow: visible;
321 | }
322 |
323 | /**
324 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
325 | * All other form control elements do not inherit `text-transform` values.
326 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
327 | * Correct `select` style inheritance in Firefox.
328 | */
329 |
330 | button,
331 | select {
332 | text-transform: none;
333 | }
334 |
335 | /**
336 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
337 | * and `video` controls.
338 | * 2. Correct inability to style clickable `input` types in iOS.
339 | * 3. Improve usability and consistency of cursor style between image-type
340 | * `input` and others.
341 | */
342 |
343 | button,
344 | html input[type="button"], /* 1 */
345 | input[type="reset"],
346 | input[type="submit"] {
347 | -webkit-appearance: button; /* 2 */
348 | cursor: pointer; /* 3 */
349 | }
350 |
351 | /**
352 | * Re-set default cursor for disabled elements.
353 | */
354 |
355 | button[disabled],
356 | html input[disabled] {
357 | cursor: default;
358 | }
359 |
360 | /**
361 | * Remove inner padding and border in Firefox 4+.
362 | */
363 |
364 | button::-moz-focus-inner,
365 | input::-moz-focus-inner {
366 | border: 0;
367 | padding: 0;
368 | }
369 |
370 | /**
371 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
372 | * the UA stylesheet.
373 | */
374 |
375 | input {
376 | line-height: normal;
377 | }
378 |
379 | /**
380 | * It's recommended that you don't attempt to style these elements.
381 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
382 | *
383 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
384 | * 2. Remove excess padding in IE 8/9/10.
385 | */
386 |
387 | input[type="checkbox"],
388 | input[type="radio"] {
389 | box-sizing: border-box; /* 1 */
390 | padding: 0; /* 2 */
391 | }
392 |
393 | /**
394 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
395 | * `font-size` values of the `input`, it causes the cursor style of the
396 | * decrement button to change from `default` to `text`.
397 | */
398 |
399 | input[type="number"]::-webkit-inner-spin-button,
400 | input[type="number"]::-webkit-outer-spin-button {
401 | height: auto;
402 | }
403 |
404 | /**
405 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
406 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
407 | * (include `-moz` to future-proof).
408 | */
409 |
410 | input[type="search"] {
411 | -webkit-appearance: textfield; /* 1 */
412 | -moz-box-sizing: content-box;
413 | -webkit-box-sizing: content-box; /* 2 */
414 | box-sizing: content-box;
415 | }
416 |
417 | /**
418 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
419 | * Safari (but not Chrome) clips the cancel button when the search input has
420 | * padding (and `textfield` appearance).
421 | */
422 |
423 | input[type="search"]::-webkit-search-cancel-button,
424 | input[type="search"]::-webkit-search-decoration {
425 | -webkit-appearance: none;
426 | }
427 |
428 | /**
429 | * Define consistent border, margin, and padding.
430 | */
431 |
432 | fieldset {
433 | border: 1px solid #c0c0c0;
434 | margin: 0 2px;
435 | padding: 0.35em 0.625em 0.75em;
436 | }
437 |
438 | /**
439 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
440 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
441 | */
442 |
443 | legend {
444 | border: 0; /* 1 */
445 | padding: 0; /* 2 */
446 | }
447 |
448 | /**
449 | * Remove default vertical scrollbar in IE 8/9/10/11.
450 | */
451 |
452 | textarea {
453 | overflow: auto;
454 | }
455 |
456 | /**
457 | * Don't inherit the `font-weight` (applied by a rule above).
458 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
459 | */
460 |
461 | optgroup {
462 | font-weight: bold;
463 | }
464 |
465 | /* Tables
466 | ========================================================================== */
467 |
468 | /**
469 | * Remove most spacing between table cells.
470 | */
471 |
472 | table {
473 | border-collapse: collapse;
474 | border-spacing: 0;
475 | }
476 |
477 | td,
478 | th {
479 | padding: 0;
480 | }
481 |
--------------------------------------------------------------------------------
/src/build/lib.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 | const path = require('path');
3 | const fs = require('fs');
4 | const Build = require('./index.js');
5 | const SassBuilder = require('./../style/sass.js');
6 | const PostCSSBuilder = require('./../style/postcss.js');
7 | const AOTBuilder = require('./../compile/ngc.js');
8 | const RollupBuilder = require('./../bundle/rollup.js');
9 | const Watcher = require('./../watch.js');
10 | const util = require('./../util.js');
11 | const log = require('./../log.js');
12 | const config = require('./../config');
13 | const cli = require('./../../cli.config.json');
14 |
15 | class LibBuild extends Build {
16 |
17 | constructor(libName) {
18 | super();
19 |
20 | this.hasInit = false;
21 | this.hasPost = false;
22 |
23 |
24 | if (!cli.program.config) {
25 | if (!libName) {
26 | libName = cli.program.build;
27 | const libConfig = config.projects[cli.program.rawArgs[cli.program.rawArgs.indexOf(libName) + 1]];
28 | this.libConfigPath = path.join(libConfig.root, libConfig.configFile);
29 | } else {
30 | const libConfig = config.projects[libName];
31 | this.libConfigPath = path.join(libConfig.root, libConfig.configFile);
32 | }
33 |
34 | } else {
35 | this.libConfigPath = cli.program.config.trim();
36 | }
37 |
38 | }
39 |
40 | init() {
41 | this.pre();
42 | }
43 |
44 |
45 | build() {
46 |
47 | // TODO: figure out best way to abstract styling tasks for the builds, should be able to support LESS, Stylus, etc.
48 | const sassBuilder = new SassBuilder({ dist: this.libConfig.dist, sourceMap: false });
49 | const postcssBuilder = new PostCSSBuilder({ dist: this.libConfig.dist, sourceMap: false });
50 | const styles = config.projects[config.project].architect.build.options.styles;
51 |
52 |
53 | if (ls(path.normalize('tmp/**/*.scss')).length > 0) {
54 |
55 | const sassFileList = ls(path.normalize('tmp/**/*.scss'));
56 | (async () => {
57 | const sass = await sassBuilder.batch(sassFileList);
58 | const postcss = await postcssBuilder.batch(sass);
59 | const convert = await this.transformSCSSPathstoCSS();
60 | const bundle = await this.bundleLib();
61 | })();
62 |
63 | }
64 | else if (ls(path.normalize('tmp/**/*.css')).length > 0) {
65 |
66 | const cssFileList = ls(path.normalize('tmp/**/*.css'));
67 |
68 | (async () => {
69 | const postcss = await postcssBuilder.batch(cssFileList);
70 | const bundle = await this.bundleLib();
71 | })();
72 |
73 |
74 | } else { // dont barf on a lib without styling
75 | (async () => {
76 | const bundle = await this.bundleLib();
77 | })();
78 | }
79 |
80 | // process global styles
81 |
82 | // if (styles.length > 0) {
83 | // const globalFiles = styles.map((stylePath) => {
84 | // return sassBuilder.file(stylePath);
85 | // });
86 |
87 | // Promise.all(globalFiles).then((css) => {
88 | // postcssBuilder.batch(css);
89 | // });
90 | // }
91 |
92 | }
93 |
94 | transformSCSSPathstoCSS() {
95 |
96 | return Promise.all(ls(path.normalize('tmp/**/*.ts')).map((filePath) => {
97 | return new Promise((res, rej) => {
98 |
99 | try {
100 | sed('-i', '.scss', '.css', filePath);
101 | res();
102 | } catch(err) {
103 | rej(err);
104 | }
105 |
106 | });
107 | }));
108 |
109 | }
110 |
111 | bundleLib() {
112 |
113 | const aotBuilder = new AOTBuilder();
114 | const rollupBuilder = new RollupBuilder();
115 |
116 | ls(path.normalize('tmp/**/*.component.ts')).forEach((file) => {
117 | util.inline(file);
118 | });
119 |
120 | return new Promise((res, rej) => {
121 |
122 | log.process('compiling library');
123 |
124 | (async () => {
125 | const compileFESM = await aotBuilder.compile(path.join(this.libConfig.src, 'config', this.libConfig.es2015.tsConfig));
126 | const rollupFESM = await rollupBuilder.bundle(path.join(this.libConfig.src, 'config', this.libConfig.es2015.rollupConfig));
127 | const post = await this.checkBuild();
128 | })();
129 | (async () => {
130 | const compileUMD = await aotBuilder.compile(path.join(this.libConfig.src, 'config', this.libConfig.es5.tsConfig));
131 | const rollupUMD = await rollupBuilder.bundle(path.join(this.libConfig.src, 'config', this.libConfig.umd.rollupConfig));
132 | const post = await this.checkBuild();
133 | })();
134 | (async () => {
135 | const compileES5 = await aotBuilder.compile(path.join(this.libConfig.src, 'config', this.libConfig.es5.tsConfig));
136 | const rollupES5 = await rollupBuilder.bundle(path.join(this.libConfig.src, 'config', this.libConfig.es5.rollupConfig));
137 | const post = await this.checkBuild();
138 | })();
139 | (async () => {
140 | const compileESM5 = await aotBuilder.compile(path.join(this.libConfig.src, 'config', this.libConfig.esm5.tsConfig));
141 | const post = await this.checkBuild();
142 | })();
143 | (async () => {
144 | const compileESM2015 = await aotBuilder.compile(path.join(this.libConfig.src, 'config', this.libConfig.esm2015.tsConfig));
145 | const post = await this.checkBuild();
146 | })();
147 |
148 | });
149 | }
150 |
151 | checkBuild() {
152 |
153 | return new Promise((res, rej) => {
154 | if (fs.existsSync(this.libConfig.es2015.outFile) &&
155 | fs.existsSync(this.libConfig.es5.outFile) &&
156 | fs.existsSync(this.libConfig.umd.outFile) &&
157 | fs.existsSync(path.join('out-tsc', 'esm5', 'index.js')) &&
158 | fs.existsSync(path.join('out-tsc', 'esm2015', 'index.js'))) {
159 | if (!this.hasPost) {
160 | this.post();
161 | }
162 | log.stop('compiling library');
163 | res();
164 | } else {
165 | log.stop('compiling library');
166 | res(); // fail silently
167 | }
168 | });
169 |
170 | }
171 |
172 | fetchLibConfig() {
173 |
174 | return new Promise((res, rej) => {
175 | fs.readFile(this.libConfigPath, 'utf8', (err, contents) => {
176 | if (!err) {
177 | this.libConfig = JSON.parse(contents);
178 | res();
179 | } else {
180 | rej(err);
181 | }
182 | });
183 | })
184 |
185 | }
186 |
187 | processESM() {
188 |
189 | return new Promise((res, rej) => {
190 |
191 | let copyFile = (filePath, distFilePath) => {
192 | if (!fs.existsSync(util.getFilePath(distFilePath))) {
193 | mkdir('-p', util.getFilePath(distFilePath));
194 | }
195 | cp('-R', filePath, distFilePath);
196 | };
197 |
198 | try {
199 |
200 | // copy typings
201 | find(path.normalize('./out-tsc/esm5'))
202 | .filter(function (file) { return file.match(/\.d.ts$/); })
203 | .forEach((filePath) => {
204 | copyFile(filePath, path.join(this.libConfig.dist, filePath.replace(path.normalize('out-tsc/esm5'), '')));
205 | });
206 | // copy esm5
207 | find(path.normalize('./out-tsc/esm5'))
208 | .filter(function (file) { return file.match(/\.js$/); })
209 | .forEach((filePath) => {
210 | copyFile(filePath, path.join(this.libConfig.dist, filePath.replace('out-tsc', '')));
211 | });
212 | // copy esm2015
213 | find(path.normalize('./out-tsc/esm2015'))
214 | .filter(function (file) { return file.match(/\.js$/); })
215 | .forEach((filePath) => {
216 | copyFile(filePath, path.join(this.libConfig.dist, filePath.replace('out-tsc', '')));
217 | });
218 | // cophy meteadata
219 | cp(path.join('out-tsc', 'esm2015', this.libConfig.filename + '.metadata.json'),
220 | path.join(this.libConfig.dist, this.libConfig.filename + '.metadata.json'));
221 |
222 | res();
223 |
224 | }
225 | catch (err) {
226 | rej(err);
227 | }
228 |
229 | });
230 | }
231 |
232 |
233 | pre() {
234 |
235 | util.cleanBuild();
236 |
237 | this.fetchLibConfig().then((res) => {
238 |
239 | rm('-rf', 'out-tsc');
240 | // rm('-rf', this.libConfig.dist);
241 | mkdir('-p', this.libConfig.dist);
242 |
243 | cp('-R', path.normalize(this.libConfig.src + '/') + '.', path.normalize('./tmp'));
244 |
245 | // remove moduleId prior to ngc build, inline template and styles
246 | ls(path.normalize('tmp/**/*.ts')).forEach((file) => {
247 | sed('-i', /^.*moduleId: module.id,.*$/, '', file);
248 | });
249 |
250 | if (util.hasHook('pre')) {
251 | log.message('processing pre task');
252 | config.projects[config.project].architect.build.hooks[cli.env].pre(process.argv).then(() => {
253 | this.build();
254 | });
255 |
256 | } else {
257 |
258 | this.build();
259 |
260 | }
261 |
262 | this.emitter.emit('hook', {
263 | payload: {
264 | step: 'pre'
265 | }
266 | });
267 |
268 | }).catch((err) => {
269 | log.warn(err); // TODO: exit process
270 | })
271 |
272 | }
273 |
274 | post() {
275 |
276 | this.hasPost = true;
277 |
278 | this.processESM().then((res) => {
279 |
280 |
281 | // copy package.json to dist
282 | exec('cp ' + this.libConfig.src + '/package.json' + ' ' + this.libConfig.dist + '/package.json', () => {
283 |
284 | log.message('package.json copied to ./' + this.libConfig.dist);
285 |
286 | if (util.hasHook('post')) {
287 | log.message('processing post task');
288 | config.projects[config.project].architect.build.hooks[cli.env].post(process.argv);
289 | }
290 |
291 | log.destroy();
292 | log.buildStats(this.startTime, this.libConfig.dist);
293 |
294 | this.emitter.emit('hook', {
295 | payload: {
296 | step: 'post'
297 | }
298 | });
299 |
300 | });
301 |
302 |
303 | }).catch((err) => {
304 | log.warn(err);
305 | });
306 |
307 | }
308 |
309 | }
310 |
311 | module.exports = LibBuild;
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | require('shelljs/global');
2 |
3 | const exec = require('child_process').exec;
4 | const path = require('path');
5 | const fs = require('fs');
6 | const UglifyJS = require('uglify-js');
7 | const MagicString = require('magic-string');
8 | const escape = require('js-string-escape');
9 | const minifyHtml = require('html-minifier').minify;
10 | const spawn = require('child_process').spawn;
11 | const config = require('./config.js');
12 | const cli = require('./../cli.config.json');
13 | const log = require('./log');
14 |
15 | class Util {
16 |
17 | constructor() {
18 | this.moduleIdRegex = /moduleId\s*:(.*)/g;
19 | this.directiveRegex = /@Directive\(\s?{([\s\S]*)}\s?\)$/gm;
20 | this.componentRegex = /@Component\(\s?{([\s\S]*)}\s?\)$/gm;
21 | this.templateUrlRegex = /templateUrl\s*:(.*)/g;
22 | this.styleUrlsRegex = /styleUrls\s*:(\s*\[[\s\S]*?\])/g;
23 | this.stringRegex = /(['"])((?:[^\\]\\\1|.)*?)\1/g;
24 | this.multilineComment = /^[\t\s]*\/\*\*?[^!][\s\S]*?\*\/[\r\n]/gm;
25 | this.singleLineComment = /^[\t\s]*(\/\/)[^\n\r]*[\n\r]/gm;
26 | this.lastError = {
27 | message: ''
28 | };
29 | }
30 |
31 | hasArg(arg) {
32 | return process.argv.indexOf(arg) > -1 || process.argv.indexOf('--' + arg) > -1;
33 | }
34 |
35 | getFilePath(filePath) {
36 |
37 | return path.normalize(filePath.substring(0, filePath.replace(/\\/g, '/').lastIndexOf('/')));
38 |
39 | }
40 |
41 | getFileName(filePath) {
42 |
43 | return filePath.replace(/^.*[\\\/]/, '');
44 |
45 | }
46 |
47 | copyFile(src, dist, options) {
48 |
49 | if (options && options.force) {
50 | rm('-f', dist);
51 | cp(src, dist);
52 | } else {
53 | cp(src, dist);
54 | }
55 | if (options && options.silent !== true) log.message(src + ' copied to ' + dist);
56 |
57 | }
58 |
59 | copyDir(src, dist, options) {
60 |
61 | if (!fs.existsSync(dist)) mkdir('-p', dist);
62 | if (options && options.force) {
63 | rm('-rf', path.normalize(path.join(dist, '/')));
64 | mkdir('-p', path.normalize(path.join(dist, '/')));
65 | cp('-R', path.normalize(src + '/*'), path.normalize(path.join(dist, '/')));
66 | } else {
67 | cp('-R', path.normalize(src + '/*'), path.normalize(path.join(dist, '/')));
68 | }
69 | if (options && options.silent !== true) log.message(this.getFileName(src) + ' copied to ' + this.getFileName(dist));
70 |
71 | }
72 |
73 | copyTo(filePath, dist) {
74 |
75 | const outFile = path.join(dist, filePath.replace(/(node_modules)[\\\/]/g, ''));
76 | return new Promise((res) => {
77 | if (!fs.existsSync(outFile)) {
78 | if (!fs.existsSync(path.dirname(outFile))) {
79 | mkdir('-p', path.dirname(outFile));
80 | }
81 | cp('-R', path.join(filePath), outFile);
82 | log.message(this.getFileName(filePath) + ' copied to ' + dist);
83 | res();
84 | }
85 | });
86 |
87 | }
88 |
89 | copyLib(fileList, src, dist) {
90 |
91 | return Promise.all(fileList.map((filePath) => {
92 | return this.copyTo(path.join(src, filePath), dist);
93 | }));
94 |
95 | }
96 |
97 | copyBatch(fileList, dist) {
98 |
99 | return Promise.all(fileList.map((filePath) => {
100 | return this.copyTo(filePath, dist);
101 | }));
102 |
103 | }
104 |
105 | hasHook(step) {
106 | if (cli.build === 'lib') {
107 | return (config.projects[config.project].architect.build.hooks && config.projects[config.project].architect.build.hooks[cli.env] && config.projects[config.project].architect.build.hooks[cli.env][step]) ? true : false;
108 | } else {
109 | return (config.projects[config.project].architect.build.hooks && config.projects[config.project].architect.build.hooks[cli.build] && config.projects[config.project].architect.build.hooks[cli.build][step]) ? true : false;
110 | }
111 | }
112 |
113 | hasConfigProperty(prop, obj) {
114 | return obj ? obj.hasOwnProperty(prop) : config.hasOwnProperty(prop);
115 | }
116 |
117 | cleanBuild() {
118 |
119 | return new Promise((res, rej) => {
120 | if (fs.existsSync(path.normalize(config.build))) rm('-rf', path.normalize(config.build));
121 | if (fs.existsSync(path.normalize('./closure'))) rm('-rf', path.normalize('./closure'));
122 | if (fs.existsSync(path.normalize('./out-tsc'))) rm('-rf', path.normalize('./out-tsc'));
123 | mkdir(path.normalize('./out-tsc'));
124 | mkdir(path.normalize('./closure'));
125 | res();
126 | });
127 |
128 | }
129 |
130 | formatIndex(template) {
131 |
132 | return new Promise((res, rej) => {
133 |
134 | let env;
135 |
136 | if (cli.build === 'jit') {
137 | env = 'dev';
138 | } else {
139 | env = cli.build;
140 | }
141 |
142 | exec(path.join(config.cliRoot, path.normalize('node_modules/.bin/htmlprocessor')) +
143 | ' ' + path.normalize(template) +
144 | ' -o ' + path.normalize(path.join(config.build, '/') + 'index.html') +
145 | ' -e ' + env, { silent: true }, (error, stdout, stderr) => {
146 | //log.message('htmlprocessor' + ' formatted ' + this.getFileName(template));
147 | if (error) {
148 | log.warn(error);
149 | if (rej) rej(error);
150 | }
151 | if (res) res();
152 | });
153 |
154 | });
155 |
156 |
157 | }
158 |
159 | inline(filePath) {
160 |
161 | const outFile = filePath ? filePath : path.normalize('./' + this.libConfig.dist + '/bundle.js');
162 | let inline = '';
163 |
164 | fs.readFile(outFile, 'utf8', (err, contents) => {
165 | if (!err) {
166 | contents = contents.replace(this.multilineComment, '');
167 | contents = contents.replace(this.singleLineComment, '');
168 |
169 | if (contents.search(this.componentRegex) > -1) {
170 | inline = this.inlineHTMLandCSS({
171 | preprocessors: {
172 | template: template => minifyHtml(template, {
173 | caseSensitive: true,
174 | collapseWhitespace: true,
175 | removeComments: true,
176 | quoteCharacter: '"'
177 | })
178 | }
179 | }, contents, filePath.substring(0, filePath.replace(/\\/g, "/").lastIndexOf('/')));
180 |
181 | if (inline) {
182 | contents = inline.code;
183 | }
184 |
185 | }
186 |
187 | fs.writeFile(outFile, contents, (err) => {
188 | if (!err && this.getFileName(outFile).includes('component')) {
189 | log.message('inline template and styles for ' + this.getFileName(outFile));
190 | } else if (err) {
191 | log.warn(err);
192 | }
193 | });
194 | } else {
195 | log.warn(err);
196 | }
197 |
198 | });
199 | }
200 |
201 | inlineHTMLandCSS(options, source, dir) {
202 |
203 |
204 | let stringRegex = this.stringRegex;
205 |
206 | /* Logic for inling styles adapted from rollup-plugin-angular CREDIT Felix Itzenplitz */
207 | function insertText(str, dir, preprocessor = res => res, processFilename = false) {
208 | return str.replace(stringRegex, function (match, quote, url) {
209 | const includePath = path.join(dir, url);
210 | if (processFilename) {
211 | let text = preprocessor(includePath);
212 | text = escape(text);
213 | return '"' + text + '"';
214 | }
215 | let text = fs.readFileSync(includePath).toString();
216 | text = preprocessor(text, includePath);
217 | text = escape(text);
218 | return '"' + text + '"';
219 | });
220 | }
221 |
222 | options.preprocessors = options.preprocessors || {};
223 | // ignore @angular/** modules
224 | options.exclude = options.exclude || [];
225 | if (typeof options.exclude === 'string' || options.exclude instanceof String) options.exclude = [options.exclude];
226 | if (options.exclude.indexOf('node_modules/@angular/**') === -1) options.exclude.push('node_modules/@angular/**');
227 |
228 | const magicString = new MagicString(source);
229 |
230 | let hasReplacements = false;
231 | let match;
232 | let start, end, replacement;
233 |
234 | while ((match = this.componentRegex.exec(source)) !== null) {
235 | start = match.index;
236 | end = start + match[0].length;
237 |
238 | replacement = match[0]
239 | .replace(this.templateUrlRegex, function (match, url) {
240 | hasReplacements = true;
241 | return 'template:' + insertText(url, dir, options.preprocessors.template, options.processFilename);
242 | })
243 | .replace(this.styleUrlsRegex, function (match, urls) {
244 | hasReplacements = true;
245 | return 'styles:' + insertText(urls, dir, options.preprocessors.style, options.processFilename);
246 | })
247 | .replace(this.moduleIdRegex, function (match, moduleId) {
248 | hasReplacements = true;
249 | return '';
250 | });
251 |
252 | if (hasReplacements) magicString.overwrite(start, end, replacement);
253 | }
254 |
255 | if (!hasReplacements) return null;
256 |
257 | let result = { code: magicString.toString() };
258 | if (options.sourceMap !== false) result.map = magicString.generateMap({ hires: true });
259 |
260 | return result;
261 |
262 | }
263 |
264 | concatVendorScripts(dist) {
265 | let result = UglifyJS.minify(this.vendorScripts, { toplevel: true });
266 | return fs.writeFileSync(path.normalize('./' + dist + '/vendor.js'), result.code);
267 | }
268 |
269 | formatVendorScripts(fileList, src, dist) {
270 | this.vendorScripts = {};
271 | fs.openSync(path.normalize('./' + dist + '/vendor.js'), 'w');
272 | return Promise.all(fileList.map((filePath) => {
273 | return this.concatFile(path.join(src, filePath), src, dist);
274 | }));
275 | }
276 |
277 | concatFile(file, src, dist, code) {
278 | return new Promise((res, rej) => {
279 | fs.readFile(file, 'utf8', (err, fileContent) => {
280 | this.vendorScripts[this.getFileName(file)] = fileContent;
281 | res();
282 | });
283 | });
284 | }
285 |
286 | serve(watch, isUniversal) {
287 |
288 | if (isUniversal === true) {
289 |
290 | spawn('npm run universal', { shell: true, stdio: 'inherit' });
291 |
292 | } else {
293 |
294 | let serverCommand = 'npm run serve';
295 |
296 | if (watch === true) {
297 | serverCommand += ' watch=true';
298 | }
299 | else {
300 | serverCommand += ' watch=false';
301 | }
302 | spawn(serverCommand, { shell: true, stdio: 'inherit' });
303 |
304 | }
305 |
306 | }
307 |
308 | }
309 |
310 |
311 |
312 | module.exports = new Util();
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ngr
2 |
3 | CLI for building Angular with Rollup and Closure Compiler
4 |
5 | [](https://gitter.im/angular2-rollup/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 |
7 | ## Main Features
8 |
9 | * Extends `@angular/cli`. Run `ng` and `ngr` commands in the same project
10 |
11 | * Generates highly optimized bundle using Closure Compiler
12 |
13 | * Builds library packages formatted with [Angular Package Format](https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs/preview)
14 |
15 | * Includes Express server for ramping up backend NodeJS production
16 |
17 | * Stylesheets with [SASS](http://sass-lang.com/) and [PostCSS](http://postcss.org)
18 |
19 | * Follows [Angular Styleguide](https://angular.io/guide/styleguide)
20 |
21 | * Pretty printed error reporting with [TSLint](http://palantir.github.io/tslint/) and [Codelyzer](https://github.com/mgechev/codelyzer)
22 |
23 |
24 | ## Table of Contents
25 |
26 | * [Getting Started](#getting-started)
27 | * [Install](#install)
28 | * [Scaffold](#scaffold)
29 | * [Help](#help)
30 | * [Development](#development)
31 | * [Build](#build)
32 | * [Production](#production)
33 | * [Hooks](#buildhooks)
34 | * [Config](#buildconfig)
35 | * [Server](#server)
36 | * [Libraries](#library)
37 | * [Schematics, Testing, and i18n](#testing)
38 |
39 | * [FAQ](#faq)
40 | * [License](#license)
41 |
42 |
43 | # Getting Started
44 |
45 | ## Install
46 |
47 |
48 | - Install dependencies
49 |
50 | Install the [Java JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
51 |
52 | - Install the cli and global npm dependencies
53 |
54 | `$ npm install -g angular-rollup @angular/cli`
55 |
56 | - Apps are scaffolded just like the `@angular/cli`. Use `ngr` instead of `ng`.
57 |
58 | ```
59 |
60 | $ ngr new my-app
61 |
62 | ```
63 |
64 | ## Scaffold
65 |
66 | To scaffold a new app run `ngr new my-app`. This command will copy required files into the a new directory called my-app and run `npm install`. Use the `--yarn` flag to install with it instead.
67 |
68 | Migrate existing angular-rollup and @angular/cli projects with `--src`.
69 |
70 | `ngr new my-new-app --src /path/to/old/src`
71 |
72 |
73 | ## Help
74 |
75 | `ngr --help` will list all commands and arguments provided in the cli.
76 |
77 | ```
78 |
79 | Options:
80 |
81 | -V, --version output the version number
82 | new [string] scaffold new development environment in directory by name, i.e. ngr new my-app
83 | --src [string] specify a path to an existing src folder
84 | --skip-install [bool] prevents install during scaffold
85 | --yarn [bool] use yarn instead of npm to install
86 | --prettier [bool] scaffold a new workspace with prettier installed
87 | --ssl [bool] scaffold a new workspace with https express server
88 | --angularVersion [string] scaffold a new workspace with a specific version of angular
89 | build [env] build the application
90 | --env [string] use that particular environment.ts during the build, just like @angular/cli
91 | --clean [bool] destroy the build folder prior to compilation, default for prod
92 | --watch [bool] listen for changes in filesystem and rebuild
93 | --config [string] path to configuration file for library build
94 | --deploy [bool] call deploy build hook for library build
95 | --verbose [bool] log all messages in list format
96 | --closure [bool] bundle and optimize with closure compiler (default)
97 | --rollup [bool] bundle with rollup and optimize with closure compiler
98 | --webpack [bool] use @angular/cli to build
99 | g, generate [string] generate schematics packaged with angular-rollup
100 | serve, --serve [bool] spawn the local express server
101 | -h, --help output usage information
102 | ```
103 |
104 |
105 | # Development
106 |
107 | ## Build
108 |
109 | `ng serve` to build for development using `@angular/cli`.
110 |
111 |
112 | ## Production
113 |
114 | * `$ ngr build prod`
115 |
116 | You can choose to bundle with Rollup instead and simplify Closure Compiler's configuration, at the expense of bundle size.
117 |
118 | * `$ ngr build prod --rollup`
119 |
120 | Use native `ng` commands for webpack.
121 |
122 | * `$ ng build --prod`
123 |
124 | To build an application for production and serve it locally:
125 |
126 | * `$ ngr build prod --serve`
127 |
128 |
129 | ## Build Hooks
130 |
131 | Hooks are points in the build where you can inject custom functionality. Each build has a `pre` and `post` hook. All hooks except `post` require that you return a `Promise`. There is a `watch` hook for the development build that takes two parameters: `dist` and `src`. There is a `deploy` hook for the library build to run additional scripts for deployment.
132 |
133 | ```
134 | hooks: {
135 | prod: {
136 | pre: () => {
137 | return new Promise((res, rej) => {
138 | // do something
139 | res();
140 | })
141 | },
142 | post: () => {
143 | // do something
144 | }
145 | }
146 | }
147 | ```
148 |
149 |
150 | ## ngr.config.js
151 |
152 | Config is shared with `angular.json` but for non Webpack builds the following files allow you configure filepaths, SASS options, and includes callbacks for steps in each build.
153 |
154 |
155 | | Script | Description |
156 | | ------------- |:-------------:|
157 | | ngr.config.js | Configures project filepaths, build hooks |
158 | | postcss.config.js | Configures postcss step in each build |
159 | | rollup.config.js | Configures rollup when using `ngr build --rollup` |
160 | | closure.rollup.conf | Configures Closure Compiler when using `ngr build --rollup` |
161 | | closure.conf | Configures Closure Compiler when using `ngr build prod` |
162 | | server.config.*.js | Configures express server |
163 | | tsconfig.*.json | Configures TypeScript (dev) or @angular/compiler (lib,prod)
164 |
165 |
166 | ## Server
167 |
168 | Express is used mainly to provide a development server, but it could also boilerplate for a MEAN stack.
169 |
170 | `server.js` and `router.js` are stored in the `backend` folder.
171 |
172 | `ngr serve` will start up the Express server, so will `--serve` with any build.
173 |
174 |
175 | ### Configure Server
176 |
177 | Change the host and/or port in `/config/server.config.dev.js` if needed. This config is used for the Express Server. `/config/server.config.prod.js` is used for production.
178 |
179 | ```
180 | {
181 | origin: 'localhost',
182 | port: 4200
183 | };
184 |
185 | ```
186 |
187 | ## Libraries
188 |
189 | `ngr` provides a build for developing Angular libraries that conforms to the Angular Package Format.
190 |
191 | Jason Aden gave a presentation about Angular Package Format at ng-conf 2017. [Packaging Angular](https://youtu.be/unICbsPGFIA).
192 |
193 |
194 | ### Generate A Library Package
195 |
196 | Generate library packages with `ngr generate lib my-lib-name`.
197 |
198 | This will generate a library package in the current folder with the necessary configuration set in `ngr.config.js`.
199 |
200 |
201 | ### Tips For Developing A Library
202 |
203 | - Keep your code strictly typed.
204 | - Do not create monolithic `@NgModule`. Separate modules by discrete functionality. This allows the library to be treeshaken.
205 | - In each `module.ts` `export` public components, directives, services, etc.
206 | - Update the library index.ts with `export` for each module.
207 |
208 | ### Build Library
209 |
210 | After you have generated some components for the library, use `ngr build lib` to build the library in the `dist` folder.
211 |
212 | `ngr build lib my-lib-name`
213 |
214 |
215 | ## Use `@angular/cli` for Schematics, Testing, and i18n
216 |
217 | `ng generate` works in `angular-rollup`!
218 |
219 | Use `ng test` and `ng e2e` for unit and end to end tests, respectively.
220 |
221 |
222 | # FAQ
223 |
224 | ### How do I include third party libraries?
225 |
226 | The production build relies heavily on Closure Compiler, which optimizes the bundle far better than other tools. Closure Compiler relies on annotations in JavaScript to optimize the bundle. Third party libraries are often not annotated. If a library package follows the Angular Package Format it will be closure annotated because when configured, the angular compiler will convert TypeScript annotations to closure annoations using a tool called [tsickle](https://github.com/angular/tsickle). Luckily for third party libraries that are not annotated, Closure Compiler can be configured to leave variables found in external scripts unmangled. Follow this step by step to figure out which method to use.
227 |
228 | - Does the library conform to Angular Package Format?
229 | YES: Will be bundled by `ngc`, inject the NgModule into your application, add to `closure.conf`
230 | NO: See next question
231 |
232 | - Is the library written in ES2015?
233 | YES: Include the necessary library files in `closure.conf`
234 | NO: See next question
235 |
236 | - Is the library formatted with UMD modules?
237 | YES: Include the necessary library files in `closure.conf`
238 | NO: You must include the library globally via `` or `SystemJS`.
239 | Add the necessary externs to `closure.externs.js`
240 |
241 |
242 |
243 | ### How do I load a library in index.html?
244 |
245 | If a library must be loaded prior to bootstrap, add the folder name in `ngr.config.js` to have it copied into `dist` directory during the build.
246 |
247 | Add the script in the `` or you can include third party dependencies with `SystemJS`.
248 |
249 | ```
250 |
258 | ```
259 |
260 |
261 | For production, `ngr` will concatenante library packages into `vendor.js`.
262 | For development, all libarary files are copied to the `dist` folder.
263 |
264 | Vendor files are configured in `ngr.config.js` like in this example:
265 |
266 | ```
267 | lib: {
268 | dev: [
269 | 'core-js/client/shim.min.js',
270 | 'core-js/client/shim.min.js.map',
271 | 'zone.js/dist/zone.min.js',
272 | 'systemjs/dist/system.js',
273 | 'systemjs/dist/system.js.map',
274 | 'reflect-metadata/Reflect.js',
275 | 'reflect-metadata/Reflect.js.map',
276 | 'tslib/tslib.js',
277 | '@angular',
278 | 'rxjs'
279 | ],
280 | prod: [
281 | 'core-js/client/shim.min.js',
282 | 'zone.js/dist/zone.min.js',
283 | 'systemjs/dist/system.js'
284 | ],
285 | src: 'node_modules',
286 | dist: 'dist/path/to/lib'
287 | }
288 | ```
289 |
290 |
291 | ### Why are there 2 different index.html?
292 |
293 | `angular-rollup` uses `htmlprocessor` to manipulate `index.html` while webpack works it's magic with the `index.html` provided by `@angular/cli`.
294 |
295 | `src/index.html` is used by `@angular/cli` and `webpack`.
296 | `src/public/index.html` is used by `angular-rollup`.
297 |
298 | For more information about [htmlprocessor](https://www.npmjs.com/package/htmlprocessor); `src/public/index.html` is manipulated by htmlprocessor. `dev` and `prod` environment variables declared via inline comments include chunks of the `index.html` per environment.
299 |
300 |
301 | ### How do I configure SystemJS for dev for jit builds?
302 |
303 | You must configure `system.config.js` in order to inject third party libaries for development. All JavaScript in the development build is compiled into commonjs modules, however the source code is pointing to files packaged with ES2105 modules. In `system.config.js` map each request for a library script to the umd bundle for the library. The build places each library in the `dist/path/to/project/lib` folder. SystemJS needs to know where the library is located in the `dist/path/to/project/lib` folder.
304 |
305 |
306 | Here is an example of mapping requests for library bundles to umd bundles in `system.config.js`.
307 |
308 | ```
309 | map: {
310 | // angular bundles
311 | '@angular/core': 'lib:@angular/core/bundles/core.umd.js',
312 | '@angular/common': 'lib:@angular/common/bundles/common.umd.js',
313 | '@angular/compiler': 'lib:@angular/compiler/bundles/compiler.umd.js',
314 | '@angular/platform-browser': 'lib:@angular/platform-browser/bundles/platform-browser.umd.js',
315 | '@angular/platform-browser-dynamic': 'lib:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
316 | '@angular/http': 'lib:@angular/http/bundles/http.umd.js',
317 | '@angular/router': 'lib:@angular/router/bundles/router.umd.js',
318 | '@angular/forms': 'lib:@angular/forms/bundles/forms.umd.js',
319 | // other libraries
320 | 'rxjs/Observable': 'lib:rxjs/Observable',
321 | 'tslib': 'lib:tslib/tslib.js'
322 | }
323 | ```
324 |
325 |
326 | #### How do I import libraries the most optimal way for treeshaking?
327 |
328 | It is a best practice to treeshake and bundle third party libraries for production, however this process only works if the third party library is packaged with a module pattern such as ES2015 modules.
329 |
330 | It is NOT recommended to import an entire library that is treeshakable.
331 |
332 | DON'T DO THIS : `import * from 'rxjs';`
333 | DO THIS : `import { Observable, Observer } from 'rxjs';`
334 |
335 | It should be noted Closure Compiler relies on named ES2015 modules and cannot handle libraries that import with `*`. If you want a third party library to be compatible with closure compiler, it is recommended to contribute named imports and exports to the open source project.
336 |
337 |
338 |
339 | ### How do I provide typings for external libraries?
340 |
341 | Type definitions are typically packaged with the `@types` scope. Install type definitions for third party libraries with npm and list them in the tsconfig.json file in the types Array.
342 |
343 | ```
344 | "compilerOptions": {
345 | "typeRoots": [ "node_modules/@types" ],
346 | "types": [
347 | "node"
348 | ]
349 | }
350 | ```
351 |
352 |
353 | ### How do I update my project to the latest CLI?
354 |
355 | `npm install -g angular-rollup@latest`
356 |
357 |
358 | ### How do I update my project to the latest versions of Angular?
359 |
360 | - `$ ng update`
361 |
362 | ### How do I deploy?
363 |
364 | The build command has an optional `--deploy` flag.
365 |
366 | Use the post build hook in ngr.config.json to deploy a build. The following example is for a library, but you could use a similar hook for a production build.
367 |
368 | Below is an example of copying the dist folder to a sibling directory that also is a git repository. The example uses `shelljs`.
369 |
370 | ```
371 |
372 | hooks: {
373 | lib: {
374 | post: (args) => {
375 | cp('-R', './dist/.', '../'+folderName);
376 | rm('-rf', './dist');
377 |
378 | if (args.indexOf('deploy=true')) {
379 | cd('../'+folderName);
380 | exec('git add --all .');
381 | exec('git commit -a -m "version bump"');
382 | exec('git push origin master');
383 | }
384 | }
385 | }
386 | }
387 |
388 | ```
389 |
390 | ## VSCode Extensions
391 |
392 | We like [Visual Studio Code](https://code.visualstudio.com/). Below are some VS Code Extensions we find useful when developing Angular applications.
393 |
394 | | Extension | Description |
395 | | ------------- |:-------------:|
396 | | Angular Language Service | Editor services for Angular templates |
397 | | Angular Support | Go to / peek angular specific definitions |
398 | | angular2-inline | Syntax highlighting of inline html and css |
399 | | SCSS Intellisense | Autocompletion and refactoring of SCSS |
400 | | Path Intellisense | Autocomplete for paths in the project |
401 | | NPM Intellisense | Autocomplete paths to node_modules |
402 | | Auto Import ES6 & TS | Auto import for TypeScript |
403 |
404 |
405 | # License
406 |
407 | [MIT](/LICENSE)
--------------------------------------------------------------------------------
/src/log.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const exec = require('child_process').exec;
3 | const path = require('path');
4 | const fs = require('fs');
5 | const ora = require('ora');
6 | const colors = require('colors');
7 | const logger = require('single-line-log').stdout;
8 | const config = require('./config');
9 | const uuid = require('uuid/v4');
10 | const gzipSize = require('gzip-size');
11 | const moment = require('moment');
12 | const cli = require('./../cli.config.json');
13 |
14 | const NGR_LOG_CACHE = Symbol('ngrProcess_'+uuid());
15 | global[NGR_LOG_CACHE] = {
16 | process: {}
17 | };
18 |
19 | const spinner = ora({
20 | text: '',
21 | spinner: 'dots10',
22 | color: 'white',
23 | hideCursor: true
24 | }).start();
25 |
26 |
27 | class Log {
28 |
29 | constructor() {
30 | this.spinner = spinner;
31 | }
32 |
33 | break() {
34 | process.stdout.write('\n');
35 | }
36 |
37 | clear () {
38 | if (!cli.program.verbose) {
39 | logger.clear();
40 | }
41 | }
42 |
43 | stop(str) {
44 | this.spinner.stop();
45 | }
46 |
47 | hasArg(arg) {
48 | return process.argv.indexOf(arg) > -1 || process.argv.indexOf('--'+arg) > -1;
49 | }
50 |
51 | destroy() {
52 | this.spinner.stop();
53 | if (!cli.program.verbose) {
54 | process.stdout.write('\x1B[2J\x1B[0f\u001b[0;0H');
55 | }
56 | }
57 |
58 | line() {
59 | process.stdout.write('\n');
60 | const col = process.stdout.columns;
61 | let line = ' ';
62 | for (let i = 0; i < col - 2; i++) {
63 | line += '\u2500';
64 | }
65 | line += '\n';
66 | process.stdout.write(colors.white(colors.dim(line)));
67 | }
68 |
69 | errorLine() {
70 | process.stdout.write('\n');
71 | const col = process.stdout.columns;
72 | let line = ' ';
73 | for (let i = 0; i < col - 4; i++) {
74 | line += '\u2500';
75 | }
76 | line += '💥';
77 | line += '\n';
78 | process.stdout.write(colors.red(line).dim);
79 | }
80 |
81 | bare(msg) {
82 | logger(msg);
83 | process.stderr.write('\x1B[?25l');
84 | if (cli.program.verbose) this.break();
85 | }
86 |
87 | message(msg) {
88 | //this.spinner.stop();
89 | msg = msg ? '' + colors.white(msg).dim : '';
90 | logger(msg);
91 | process.stderr.write('\x1B[?25l');
92 | if (cli.program.verbose) this.break();
93 | }
94 |
95 | process(msg) {
96 |
97 | if (!cli.program.verbose) this.destroy();
98 |
99 | msg = msg ? '' + colors.white(msg).dim : '';
100 |
101 | this.spinner.text = msg;
102 | this.spinner.start();
103 |
104 | if (cli.program.verbose) this.break();
105 |
106 | }
107 |
108 | success(msg, services) {
109 | services.forEach((service) => { this.cancelError(service); });
110 | if (!this.hasError()) {
111 | this.destroy();
112 | }
113 | msg = '\n'+ (msg ? '' + colors.white(msg) : '');
114 | logger(msg);
115 | process.stderr.write('\x1B[?25l');
116 | //if (!cli.program.verbose) this.line();
117 | if (cli.program.verbose) this.break();
118 | }
119 |
120 | fail(msg) {
121 | // if (!this.hasError()) {
122 | // this.destroy();
123 | // }
124 | msg = msg ? '' + colors.red(msg) : '';
125 | logger(msg);
126 | process.stderr.write('\x1B[?25l');
127 | if (cli.program.verbose) this.break();
128 | }
129 |
130 | alert(msg) {
131 | // if (!this.hasError()) {
132 | // this.destroy();
133 | // }
134 | msg = msg ? '' + colors.white(msg) : '';
135 | process.stdout.write(msg);
136 | process.stdout.write('\n');
137 | }
138 |
139 | warn(msg) {
140 | msg = msg ? '' + colors.yellow(msg) : '';
141 | process.stdout.write(msg);
142 | process.stdout.write('\n');
143 | }
144 |
145 | error(err) {
146 |
147 | this.registerError(err);
148 |
149 | if (typeof err === 'string') {
150 | process.stdout.write('\n');
151 | process.stdout.write(colors.red(err));
152 | } else {
153 |
154 | this.break();
155 | let msg = ' ';
156 | let link = '';
157 |
158 | if (!err.line) {
159 | err.line = '';
160 | }
161 |
162 | if (!err.column) {
163 | err.column = '';
164 | }
165 |
166 | if (typeof err.line === 'number') {
167 | err.line = err.line.toString();
168 | }
169 |
170 | if (typeof err.column === 'number') {
171 | err.column = err.column.toString();
172 | }
173 |
174 |
175 | let lineNumbers = (err.line.length > 0) ? colors.white(err.line + ':' + err.column).dim : '';
176 |
177 | if (err.file && err.file.length > 0) {
178 | msg += err.message.replace(/'(.*?)'/g, colors.red("'") + colors.red("$1") + colors.red("'"))
179 | .replace(/(error)( )((?:TS[a-z0-9]*))(:)/g, colors.white("$1$2$3").dim);
180 | link += err.file.includes(config.projectRoot) ?
181 | colors.dim(' vscode://file/' + err.file + ':' + lineNumbers) + '\n' :
182 | colors.dim(' vscode://file/' + config.projectRoot + '/' + err.file + ':' + lineNumbers) + '\n';
183 | process.stdout.write(colors.red(' ' + err.service.toUpperCase() + ' ERROR') + ' ' +
184 | ((err.file.length > 0) ? colors.white(colors.dim(err.file) + ' ' + lineNumbers) : '') + '\n\n' +
185 | colors.white(msg) + '\n\n'+
186 | ((err.file.length > 0) ? link : '') + '\n');
187 |
188 | } else {
189 | msg = err.message;
190 | process.stdout.write(colors.red(' ' + err.service.toUpperCase() + ' ERROR') + ' ' +
191 | colors.white(msg) + '\n\n');
192 |
193 | }
194 |
195 |
196 |
197 | this.line();
198 |
199 | }
200 |
201 | }
202 |
203 | hasError() {
204 | for (let prop in global[NGR_LOG_CACHE].process) {
205 | if (global[NGR_LOG_CACHE].process[prop].length > 0) {
206 | return true;
207 | }
208 | }
209 | return false;
210 | }
211 |
212 | registerError(err) {
213 | if (!err || !err.service) {
214 | return;
215 | }
216 | if (!global[NGR_LOG_CACHE].process[err.service.toLowerCase()]) {
217 | global[NGR_LOG_CACHE].process[err.service.toLowerCase()] = [];
218 | }
219 | global[NGR_LOG_CACHE].process[err.service.toLowerCase()].push(err);
220 | }
221 |
222 | cancelError(service) {
223 | delete global[NGR_LOG_CACHE].process[service.toLowerCase()];
224 | }
225 |
226 | getFilePath(filePath) {
227 | return path.normalize(filePath.substring(0, filePath.replace(/\\/g, '/').lastIndexOf('/')));
228 | }
229 |
230 | getFileName(filePath) {
231 | return filePath.replace(/^.*[\\\/]/, '');
232 | }
233 |
234 | catchError(str, type) {
235 |
236 | if (str.length) {
237 | this.error(str);
238 | }
239 |
240 | }
241 |
242 | formatTemplateError(str) {
243 |
244 | str = str.replace('Template parse errors:\n', '');
245 |
246 | let msg = (/^(.*?)\(/).exec(str);
247 | let code = (/\(([^)]+)\)/).exec(str);
248 | let lookup = (/\(([^)]+)\)/).exec(str);
249 |
250 | let lineNumberLookup = str.split('"):');
251 |
252 | if (msg != null && code != null) {
253 |
254 | msg[1] = msg[1].replace(': ', '');
255 | code[1] = code[1].replace('[ERROR ->]', colors.red('[ERROR ->]'));
256 |
257 | if (lineNumberLookup.length === 1 && lineNumberLookup[0].match(/\(([1-9]\d{0,5})(,)([1-9]\d{0,5})\)/g) === null) {
258 |
259 | try {
260 |
261 | lookup[1] = lookup[1].substr(1).slice(0, -1); //.replace('[ERROR ->]', '')
262 |
263 | let errorLine = '';
264 | let errorLines = lookup[1].split('\n').filter((line) => {
265 | return line.includes('[ERROR ->]');
266 | });
267 |
268 | errorLine = errorLines[0].replace('[ERROR ->]', '');
269 | if (code[1][0] === '"') code[1] = code[1].substr(1);
270 | if (code[1][code[1].length -1] === '"') code[1] = code[1].slice(0, -1);
271 | let cmd = "grep -rnw '" + config.src + "' -e '" + code[1].replace('[ERROR ->]', '') + "'";
272 | //TODO: figure out if this is possible in Windows
273 | exec(cmd, {silent: true}, (error, stdout, stderr) => {
274 |
275 | try {
276 | let lineNumber = stdout.replace('\n', '');
277 | let columnNumber = errorLines[0].indexOf('[ERROR ->]');
278 |
279 | lineNumber = parseInt(lineNumber.match(/(:)(\d)(:)/)[2]) - 1; //TODO: figure out if - 1 is always true
280 | if (lineNumber < 1) lineNumber = 0;
281 |
282 | this.error({
283 | service: 'Template',
284 | file: stdout.replace('\n', '').split(':')[0],
285 | line: lineNumber.toString(),
286 | column: columnNumber,
287 | message: msg[1] + '\n\n' + code[1].substr(1).slice(0, -1)
288 | });
289 | }
290 | catch (e) {
291 | this.error({
292 | service: 'Template',
293 | file: stdout.replace('\n', '').split(':')[0],
294 | line: '',
295 | column: '',
296 | message: msg[1] + '\n\n' + code[1].substr(1).slice(0, -1)
297 | });
298 | }
299 |
300 | });
301 |
302 | }
303 | catch(e) {
304 | if (cli.program.verbose) this.message(e);
305 | this.catchError(str, 'Template');
306 | }
307 |
308 | } else {
309 |
310 | try {
311 | let lineNoRegex = /\(([1-9]\d{0,5})(,)([1-9]\d{0,5})\)/g;
312 |
313 |
314 | if (str.indexOf(': :') > 0) { // this is janky may need better regex here
315 |
316 | let lineNumber = lineNumberLookup[lineNumberLookup.length - 1].match(lineNoRegex)[0].replace('(', '').replace(')', '');
317 |
318 | this.error({
319 | service: 'Template',
320 | file: lineNumberLookup[0].trim().split(':')[0].replace(lineNoRegex, ''),
321 | line: lineNumber.split(',')[0],
322 | column: lineNumber.split(',')[1],
323 | message: lineNumberLookup[0].trim().split(': :')[1],
324 | });
325 |
326 |
327 | } else {
328 |
329 | let line = lineNumberLookup[lineNumberLookup.length - 1].replace(/\n/g, '').split('@');
330 |
331 | this.error({
332 | service: 'Template',
333 | file: line[0].trim(),
334 | line: line[1].split(':')[0],
335 | column: line[1].split(':')[1],
336 | message: msg[1] + '\n\n' + code[1].substr(1).slice(0, -1)
337 | });
338 |
339 | }
340 |
341 |
342 | } catch(e) {
343 |
344 | if (cli.program.verbose) this.message(e);
345 | this.catchError(str, 'Template');
346 | // this.error(str);
347 |
348 | }
349 |
350 |
351 | }
352 |
353 | } else {
354 | this.catchError(str, 'Template');
355 | }
356 |
357 | }
358 |
359 | formatTSError(str) {
360 |
361 | try {
362 | let lineNumbers = str.slice(str.indexOf('(') + 1, str.indexOf(')')).split(',');
363 | let err = {
364 | service: 'TypeScript',
365 | file: str.slice(0, str.indexOf('(')),
366 | line: lineNumbers[0],
367 | column: lineNumbers[1],
368 | message: str.slice(str.indexOf(':') + 2, str.length)
369 | };
370 | this.error(err);
371 | }
372 | catch(e) {
373 | if (cli.program.verbose) this.message(e);
374 | this.catchError(str, 'TypeScript');
375 | }
376 |
377 | }
378 |
379 | formatClosureError(str) {
380 |
381 | let lineNumber = str.match(/:([0-9]+):/) ? str.match(/:([0-9]+):/)[1] : null;
382 | try {
383 | let err = {
384 | service: 'Closure',
385 | file: str.slice(0, str.indexOf(':')),
386 | line: lineNumber ? lineNumber : '',
387 | column: '',
388 | message: str.slice(str.indexOf('ERROR'), str.length).length ? str.slice(str.indexOf('ERROR'), str.length).replace(/\n/g, '\n ') : str
389 | };
390 | this.error(err);
391 | }
392 | catch(e) {
393 | if (cli.program.verbose) this.message(e);
394 | this.catchError(str, 'Closure');
395 | }
396 |
397 | }
398 |
399 | logFileStats(file) {
400 | if (fs.lstatSync(path.join(file)).isFile()) {
401 | this.alert(colors.dim('') + colors.white(file) + ' ' +
402 | colors.dim((fs.statSync(path.join(file)).size / 1000).toFixed(2) + ' kB') + ' ' +
403 | colors.green(colors.dim('(') + (gzipSize.sync(fs.readFileSync(path.join(file))) / 1000).toFixed(2) + ' kB' + ' ' + colors.dim('gzipped') + colors.dim(')') + ' ')
404 | );
405 | }
406 | }
407 |
408 | buildStats(startTime, dist) {
409 |
410 | if (dist) {
411 | config.build = dist;
412 | }
413 |
414 | let endTime = moment(new Date());
415 | let duration = moment.duration(endTime.diff(startTime));
416 | // this.destroy();
417 | this.alert(colors.green('✅ build complete'));
418 |
419 | this.alert(colors.dim('Date: ')+ new Date().toISOString());
420 | this.alert(colors.dim('Time: ')+colors.white(duration.asMilliseconds() + 'ms'));
421 | this.alert(colors.dim('Environment: ')+ colors.white(cli.env));
422 | this.alert(colors.dim('Location: ')+ colors.white(path.join(config.build)));
423 |
424 | ls(config.build).forEach((file) => {
425 | if (fs.lstatSync(path.join(config.build,file)).isFile()) {
426 | this.logFileStats(path.join(config.build, file));
427 | }
428 | });
429 |
430 | if (fs.existsSync(path.join(config.build, 'style'))) {
431 | ls(path.join(config.build, 'style')).forEach((file) => {
432 | this.logFileStats(path.join(config.build, 'style', file));
433 | });
434 | }
435 |
436 | if (fs.existsSync(path.join(config.build, 'fesm2015'))) {
437 | ls(path.join(config.build, 'fesm2015')).forEach((file) => {
438 | if (fs.lstatSync(path.join(config.build, 'fesm2015', file)).isFile()) {
439 | this.logFileStats(path.join(config.build, 'fesm2015', file));
440 | }
441 | });
442 | }
443 |
444 | if (fs.existsSync(path.join(config.build, 'fesm5'))) {
445 | ls(path.join(config.build, 'fesm5')).forEach((file) => {
446 | if (fs.lstatSync(path.join(config.build, 'fesm5', file)).isFile()) {
447 | this.logFileStats(path.join(config.build, 'fesm5', file));
448 | }
449 | });
450 | }
451 |
452 | if (fs.existsSync(path.join(config.build, 'esm2015'))) {
453 | ls(path.join(config.build, 'esm2015')).forEach((file) => {
454 | if (fs.lstatSync(path.join(config.build, 'esm2015', file)).isFile()) {
455 | this.logFileStats(path.join(config.build, 'esm2015', file));
456 | }
457 | });
458 | }
459 |
460 | if (fs.existsSync(path.join(config.build, 'esm5'))) {
461 | ls(path.join(config.build, 'esm5')).forEach((file) => {
462 | if (fs.lstatSync(path.join(config.build, 'esm5', file)).isFile()) {
463 | this.logFileStats(path.join(config.build, 'esm5', file));
464 | }
465 | });
466 | }
467 |
468 | if (fs.existsSync(path.join(config.build, 'bundles'))) {
469 | ls(path.join(config.build, 'bundles')).forEach((file) => {
470 | if (fs.lstatSync(path.join(config.build, 'bundles', file)).isFile()) {
471 | this.logFileStats(path.join(config.build, 'bundles', file));
472 | }
473 | });
474 | }
475 |
476 | }
477 |
478 |
479 | }
480 |
481 |
482 |
483 | module.exports = new Log();
484 |
--------------------------------------------------------------------------------