├── .codelyzer.js ├── .editorconfig ├── .gitignore ├── .npmrc ├── .travis.yml ├── LICENSE ├── README.md ├── config └── spec-bundle.js ├── karma.conf.js ├── package.json ├── src ├── app │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app.scss │ ├── index.ts │ └── shared │ │ └── test-helpers.ts ├── assets │ └── images │ │ └── pluto-the-planet.jpg ├── globals.d.ts ├── index.html ├── main.ts ├── polyfills.ts └── vendor.ts ├── tsconfig.json ├── tslint.json ├── webpack-build.config.js ├── webpack-test.config.js └── webpack.config.js /.codelyzer.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Transformation of the templates. This hooks is quite useful 3 | // if you're using any other templating language, for instance 4 | // jade, markdown, haml, etc. 5 | // 6 | // NOTE that this method WILL NOT throw an error in case of invalid template. 7 | // 8 | transformTemplate(code, url, decorator) { 9 | return {code: code.replace(/\$ctrl\./g, ''), url, decorator}; 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | src/**/*.js 4 | src/**/*.js.map 5 | typings 6 | dist 7 | coverage 8 | ts-out 9 | npm-debug.log 10 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_script: 3 | - export DISPLAY=:99.0 4 | - sh -e /etc/init.d/xvfb start 5 | - sleep 3 6 | node_js: 7 | - 6.3.0 8 | install: 9 | - npm install 10 | script: 11 | - npm run test:ci 12 | notifications: 13 | slack: 14 | secure: lQ1bu6FYIRGshHffZKDDDMiDalCo1jm944XT5CIJQhzO7ARXeE1y8MPs4cwSxv+rg3KtGA/0JPkr3t1gGdueANP2XlI6vZDABZk7poxZNDpR/L6mUB1jZt3wriB2u5Br9CLI/lqwv4haO0c37aL7ZTZTroblLNkL5qq74yYEHYKvr4OIg+t9UCpieGuKmjXw4l9pQRaMl+SC9MtDepWbGqj+6dGuYksXVp8EmwE/t6zQGu91dMuyWWf2YDW0qj9SPveU3PBKTfp8KwlFmDTIHXmW+RJSUMM7t5WEQTqMrzWm+Tm33Pyowftmb6nhCgdcM5iAXQJsrx4vGaviaCsnauLK0U+iTWwGQo5PLpFleldmWFXMQvR2mku8GPY8OHa/G8vxcjyz3AhiRuSQy3vIrTwkG553JWZ6prvzc9EIlygfjJj0qeb9hwRoNOmhzywypZgnqMZZQjwUK0IXYGGBXTy4EUXJTX0Y0FEOAa+UXROACkiRfOVbZBD6xQ/6dmdBnJSY8mQInM2dgmo32bOCbo7mCBcZraxsSHMM2TP5TGShVc9Ki8CJp2fj2zygzttn1IbWttIUo9pmQnzEaU4QYERR5RrL0FlYr31Tib2tqA9Agp+PkYJGx260qFskb2lqLUubEYlZ33ckzhExjdyqCoFGqeg27QxAar7EoFLzh6k= 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2016, ngParty 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, 5 | provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 8 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 9 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 10 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 11 | THIS SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/ngParty/Angular1-scaffold.svg?branch=master)](https://travis-ci.org/ngParty/Angular1-scaffold) 2 | [![GitHub version](https://badge.fury.io/gh/ngParty%2FAngular1-scaffold.svg)](https://badge.fury.io/gh/ngParty%2FAngular1-scaffold) 3 | [![Dependency Status](https://david-dm.org/ngParty/Angular1-scaffold.svg)](https://david-dm.org/ngParty/Angular1-scaffold) 4 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/ngParty/Angular1-scaffold/master/LICENSE) 5 | 6 | # Angular 1 TypeScript Scaffold [![Join Slack](https://img.shields.io/badge/slack-join-brightgreen.svg)](https://ngparty.herokuapp.com) 7 | 8 | ![ngparty-scaffold-logo](https://cloud.githubusercontent.com/assets/1223799/15454478/db5b45f6-2039-11e6-8a24-315656d53b6d.png) 9 | 10 | > The de facto starter repo for building scalable and Angular 2 migration ready apps with Angular, Typescript 2.x, ng-metadata and Webpack 1.x 11 | 12 | This seed repo serves as a minimal starter for anyone looking to get up and running with Angular 1 and Typescript fast. 13 | It uses Webpack for the build process, which is highly maintainable, fast and modular build system. 14 | 15 | **Features:** 16 | 17 | - [x] un-opinionated directory/file structure ( we recommend to follow [Angular 2 styleguide](https://angular.io/styleguide) ) 18 | - [x] Ready to go build system using [Webpack](https://webpack.github.io/) for working with TypeScript 19 | - [x] great Angular 1 seed repo for anyone who wants to start their project and be ready for migration to Angular 2. 20 | - [x] Angular code powered by [ng-metadata](https://github.com/ngParty/ng-metadata) which allows you to write angular 2 ready code with angular 1 21 | - [x] includes TSlint and [Codelyzer](https://github.com/mgechev/codelyzer) so it will tell you if your code is not following Angular 2 styleguide 22 | - [x] testing Angular code with Jasmine and Karma. 23 | - [x] coverage with Istanbul and Karma 24 | - [x] type manager with npm ( via [@types](https://www.npmjs.com/~types ) 25 | - [x] Sass support ( you can add your own preprocessor pretty easily ) 26 | - [x] source maps support 27 | - [x] [UI-Router](https://github.com/ngParty/Angular1-scaffold/tree/ui-router) ( for this we have separate branch, because we don't want to force you to use it ;) ) 28 | - [x] ~~[Component Router](https://github.com/ngParty/Angular1-scaffold/tree/component-router)~~ ( for this we have separate branch, because we don't want to force you to use it ;) ) *NOTE* this is deprecated since angular team dropped router support to ng1 29 | - [ ] ngUpgrade + Angular 2 integration within build 30 | 31 | ### Static analysis via Typescript and Codelyzer ( exactly like with Angular 2 ): 32 | 33 | ![ng-metadata-with-codelyzer-on-steroids](https://cloud.githubusercontent.com/assets/1223799/21472541/fd7f804c-cadf-11e6-94ae-62c4682c76f8.gif) 34 | 35 | 36 | ## Install 37 | 38 | ```bash 39 | # clone our repo 40 | # --depth 1 removes all but one .git commit history 41 | git clone --depth=1 https://github.com/ngParty/Angular1-scaffold.git 42 | 43 | # change directory to our repo 44 | cd 45 | 46 | # install all dependencies locally ( global is evil ! ) 47 | npm install 48 | ``` 49 | 50 | ## Start Development 51 | 52 | ```bash 53 | # start the server, webpack ( which runs Typescript compilation and linting with TSlint and Codelyzer ) 54 | npm start 55 | 56 | open http://localhost:9000 57 | ``` 58 | 59 | ## Testing 60 | 61 | ```bash 62 | # for running test once 63 | npm test 64 | 65 | # for running tests in watch mode 66 | npm run test:watch 67 | ``` 68 | 69 | ## Production build 70 | 71 | ```bash 72 | npm run build 73 | ``` 74 | 75 | check your production ready application within `/dist` 76 | 77 | **NOTE:** 78 | If you need to include any assets like images, custom fonts etc. place them withing `src/assets` 79 | 80 | This folder will be copied and flattened to your `/dist`. so as an example: 81 | `/src/assets/images/hello.png` -> `/dist/images/hello.png` 82 | 83 | For these reasons use `images/pluto-the-planet.jpg` path when directly referencing assets withing your html 84 | 85 | 86 | ### Adding 3rd party libraries 87 | 88 | ```bash 89 | npm install --save 90 | ``` 91 | 92 | If it doesn't ship with type definitions, you need to download them via [npm @types](#customtypedefinitions) 93 | 94 | now just `import` what you need via `es2015` module syntax 95 | 96 | ### Custom Type Definitions 97 | 98 | When including 3rd party modules you also need to include the type definition for the module if they don't provide one within the module. 99 | You can install it with npm: 100 | 101 | ```bash 102 | npm install --save @types/moment 103 | ``` 104 | 105 | If there isn't a type definition for your 3rd party library, which is very unlikely, you can place your own custom global type definitions within `src/globals.d.ts` 106 | 107 | For example: 108 | 109 | ```typescript 110 | declare module "my-module" { 111 | export function doesSomething(value: string): string; 112 | } 113 | ``` 114 | 115 | If you're prototyping and you will fix the types later you can also declare it as type any 116 | 117 | ```typescript 118 | declare var assert: any; 119 | ``` 120 | 121 | If you're importing a module that uses Node.js modules which are CommonJS you need to import as 122 | 123 | ```typescript 124 | import * as _ from 'lodash'; 125 | ``` 126 | 127 | You can include your type definitions in this file until you create one for the @types npm registry 128 | 129 | ### Proposed File structure 130 | 131 | ``` 132 | src/ 133 | ├──app/ * WebApp: folder, our source files that will be compiled to javascript 134 | │ │--shared/ * Do put all shared files within a component feature in a shared folder. 135 | | | |-- exception.service.ts 136 | | | |-- exception.service.spec.ts 137 | | | |-- shared.module.ts * shared module with all shared declarations and providers 138 | | | |-- index.ts * barrel file 139 | │ |--app.module.ts * angular module 140 | │ |--app.component.ts * root component 141 | │ │──app.spec.ts * a simple test of components in app.ts 142 | │ │──index.ts * barrel file 143 | │ │ 144 | │──assets/ * static assets are served here 145 | │ ├──icon/ * our list of icons from www.favicon-generator.org 146 | │ ├──images/ * our custom app images 147 | │ ├──service-worker.js * ignore this. Web App service worker that's not complete yet 148 | │ ├──robots.txt * for search engines to crawl your website 149 | │ └──human.txt * for humans to know who the developers are 150 | |──main.ts * our entry file for our browser environment 151 | │ 152 | |──index.html * Index.html: where we generate our index page 153 | │ 154 | |──polyfills.ts * our polyfills file 155 | │ 156 | |──vendor.ts * our vendor file 157 | | 158 | |──globals.d.ts * our custom global type definitions 159 | ``` 160 | 161 | > What is a [barrel file](https://angular.io/styleguide#!#create-and-import-barrels) ? 162 | 163 | ### Code snippets 164 | 165 | Be efficient, we have [code snippets](https://github.com/ngParty/jetbrains-angular1-snippets) for you my friend! 166 | 167 | ### Data flow and state management 168 | 169 | We highly recommend to go fully reactive by embracing [Redux](https://github.com/angular-redux/ng-redux) or [RxJs](http://reactivex.io/rxjs/) or both! 170 | From architectural point Smart and Dumb components, is the way to go! 171 | 172 | Have fun! 173 | 174 | 175 | Created with ❤ by ngParty team. 176 | -------------------------------------------------------------------------------- /config/spec-bundle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @ngParty 3 | */ 4 | 5 | /* 6 | * When testing with webpack and ES6, we have to do some extra 7 | * things get testing to work right. Because we are gonna write test 8 | * in ES6 to, we have to compile those as well. That's handled in 9 | * karma.conf.js with the karma-webpack plugin. This is the entry 10 | * file for webpack test. Just like webpack will create a bundle.js 11 | * file for our client, when we run test, it well compile and bundle them 12 | * all here! Crazy huh. So we need to do some setup 13 | */ 14 | Error.stackTraceLimit = Infinity; 15 | 16 | // polyfills 17 | require('../src/polyfills'); 18 | 19 | // vendors 20 | require('../src/vendor'); 21 | 22 | // testing specific 23 | require('angular-mocks/ngMock'); 24 | 25 | /* 26 | * Ok, this is kinda crazy. We can use the the context method on 27 | * require that webpack created in order to tell webpack 28 | * what files we actually want to require or import. 29 | * Below, context will be an function/object with file names as keys. 30 | * using that regex we are saying look in ./src/app and ./test then find 31 | * any file that ends with spec.js and get its path. By passing in true 32 | * we say do this recursively 33 | */ 34 | var testContext = require.context('../src', true, /\.spec\.ts/); 35 | 36 | // requires and returns all modules that match 37 | var modules = requireAll(testContext); 38 | 39 | 40 | /* 41 | * get all the files, for each file, call the context function 42 | * that will require the file and load it up here. Context will 43 | * loop and require those spec files here 44 | */ 45 | function requireAll( requireContext ) { 46 | return requireContext.keys().map( ( path ) => { 47 | try { 48 | return requireContext( path ); 49 | } catch ( err ) { 50 | console.error( '[ERROR] WITH SPEC FILE: ', path ); 51 | console.error( err ); 52 | } 53 | } ); 54 | } 55 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @ngParty 3 | */ 4 | const testWebpackConfig = require('./webpack-test.config'); 5 | 6 | module.exports = function(config) { 7 | 8 | config.set({ 9 | 10 | // base path that will be used to resolve all patterns (e.g. files, exclude) 11 | basePath: '', 12 | 13 | /* 14 | * Frameworks to use 15 | * 16 | * available frameworks: https://npmjs.org/browse/keyword/karma-adapter 17 | */ 18 | frameworks: ['jasmine'], 19 | 20 | // list of files to exclude 21 | exclude: [ ], 22 | 23 | /* 24 | * list of files / patterns to load in the browser 25 | * 26 | * we are building the test environment in ./spec-bundle.js 27 | */ 28 | files: [ { pattern: './config/spec-bundle.js', watched: false } ], 29 | 30 | /* 31 | * preprocess matching files before serving them to the browser 32 | * available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 33 | */ 34 | preprocessors: { './config/spec-bundle.js': ['webpack', 'sourcemap'] }, 35 | 36 | // Webpack Config at ./webpack-test.config.js 37 | webpack: testWebpackConfig, 38 | 39 | coverageReporter: { 40 | // specify a common output directory 41 | dir : 'coverage/', 42 | // multiple reporters 43 | reporters: [ 44 | { type: 'text-summary' }, 45 | { type: 'json' }, 46 | { type: 'html' } 47 | ] 48 | }, 49 | 50 | // Webpack please don't spam the console when running in karma! 51 | webpackServer: { noInfo: true }, 52 | 53 | /* 54 | * test results reporter to use 55 | * 56 | * possible values: 'dots', 'progress' 57 | * available reporters: https://npmjs.org/browse/keyword/karma-reporter 58 | */ 59 | reporters: [ 'mocha', 'coverage' ], 60 | 61 | // web server port 62 | port: 9876, 63 | 64 | // enable / disable colors in the output (reporters and logs) 65 | colors: true, 66 | 67 | /* 68 | * level of logging 69 | * possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 70 | */ 71 | logLevel: config.LOG_INFO, 72 | 73 | // enable / disable watching file and executing tests whenever any file changes 74 | autoWatch: false, 75 | 76 | /* 77 | * start these browsers 78 | * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 79 | */ 80 | browsers: [ 81 | 'Chrome' 82 | // 'PhantomJS' 83 | ], 84 | 85 | /* 86 | * Continuous Integration mode 87 | * if true, Karma captures browsers, runs the tests and exits 88 | */ 89 | singleRun: true 90 | }); 91 | 92 | }; 93 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular1-scaffold", 3 | "version": "1.0.0", 4 | "description": "Angular 1 scaffold with Typescript and ng-metadata", 5 | "main": "src/main.ts", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/ngParty/Angular1-scaffold.git" 9 | }, 10 | "scripts": { 11 | "start": "npm run server", 12 | "build": "NODE_ENV=production webpack --config webpack-build.config.js", 13 | "build:dev": "webpack --progress --profile --colors --display-error-details --display-cached", 14 | "test": "karma start", 15 | "test:ci": "karma start --browsers Firefox", 16 | "test:watch": "npm run test -- --auto-watch --no-single-run", 17 | "clean": "rimraf doc/ coverage/ dist/", 18 | "server": "webpack-dev-server --inline --progress --profile --colors --watch --display-error-details --display-cached --content-base src/" 19 | }, 20 | "keywords": [], 21 | "contributors": [ 22 | "Martin Hochel ", 23 | "Mario Vejlupek " 24 | ], 25 | "license": "ISC", 26 | "dependencies": { 27 | "@types/angular": "1.5.22", 28 | "@types/core-js": "0.9.35", 29 | "angular": "1.6.1", 30 | "core-js": "2.4.1", 31 | "ng-metadata": "4.0.0", 32 | "reflect-metadata": "0.1.9", 33 | "rxjs": "5.0.2", 34 | "tslib": "1.4.0" 35 | }, 36 | "devDependencies": { 37 | "@angular/compiler": "2.4.1", 38 | "@angular/core": "2.4.1", 39 | "@types/angular-mocks": "1.5.8", 40 | "@types/jasmine": "2.5.38", 41 | "@types/lodash": "4.14.37", 42 | "@types/node": "6.0.53", 43 | "angular-mocks": "1.6.1", 44 | "awesome-typescript-loader": "3.0.0-beta.17", 45 | "codelyzer": "2.0.0-beta.4", 46 | "copy-webpack-plugin": "4.0.1", 47 | "css-loader": "0.26.1", 48 | "html-webpack-plugin": "2.24.1", 49 | "istanbul-instrumenter-loader": "1.2.0", 50 | "jasmine-core": "2.5.2", 51 | "json-loader": "0.5.4", 52 | "karma": "1.3.0", 53 | "karma-chrome-launcher": "2.0.0", 54 | "karma-coverage": "1.1.1", 55 | "karma-firefox-launcher": "1.0.0", 56 | "karma-jasmine": "1.1.0", 57 | "karma-mocha-reporter": "2.2.1", 58 | "karma-phantomjs-launcher": "1.0.2", 59 | "karma-sourcemap-loader": "0.3.7", 60 | "karma-webpack": "1.8.1", 61 | "lodash": "4.17.3", 62 | "node-sass": "4.1.1", 63 | "raw-loader": "0.5.1", 64 | "remap-istanbul": "0.8.4", 65 | "rimraf": "2.5.4", 66 | "sass-loader": "4.1.1", 67 | "source-map-loader": "0.1.5", 68 | "style-loader": "0.13.1", 69 | "tslint": "4.2.0", 70 | "tslint-loader": "3.3.0", 71 | "typescript": "2.1.4", 72 | "webpack": "1.14.0", 73 | "webpack-dev-server": "1.16.2", 74 | "zone.js": "0.7.4" 75 | }, 76 | "engines": { 77 | "node": ">= 6.x", 78 | "npm": ">= 3" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import * as angular from 'angular'; 2 | import { IRender, renderFactory } from 'ng-metadata/testing'; 3 | import { NgModule, Component } from 'ng-metadata/core'; 4 | 5 | import { queryByDirective, createAngular1Module } from './shared/test-helpers'; 6 | import { AppComponent } from './app.component'; 7 | 8 | describe( `AppComponent`, () => { 9 | 10 | @Component( { 11 | selector: 'np-test-component', 12 | template: `` 13 | } ) 14 | class TestComponent { 15 | } 16 | 17 | @NgModule( { 18 | declarations: [ AppComponent, TestComponent ] 19 | } ) 20 | class TestModule { 21 | } 22 | 23 | const TestModuleName = createAngular1Module( TestModule ); 24 | 25 | 26 | let render: IRender; 27 | 28 | beforeEach( angular.mock.module( TestModuleName ) ); 29 | 30 | beforeEach( angular.mock.inject( ( $injector: ng.auto.IInjectorService ) => { 31 | 32 | const $compile = $injector.get( '$compile' ); 33 | const $rootScope = $injector.get( '$rootScope' ); 34 | const $scope = $rootScope.$new(); 35 | 36 | render = renderFactory( $compile, $scope ); 37 | 38 | } ) ); 39 | 40 | it( `should render Hello Pluto!!!`, () => { 41 | 42 | const {compiledElement} = render(TestComponent); 43 | 44 | // now we need to get our tested component 45 | const { debugElement, componentInstance } = queryByDirective( compiledElement, AppComponent ); 46 | 47 | expect( componentInstance instanceof AppComponent ).toBe( true ); 48 | expect( debugElement.text() ).toContain( 'Hello from Pluto !' ); 49 | 50 | } ); 51 | 52 | 53 | } ); 54 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Inject } from 'ng-metadata/core'; 2 | 3 | @Component({ 4 | selector: 'np-app', 5 | styles: [ require( './app.scss' ) ], 6 | template: ` 7 |

Hello from {{ $ctrl.planet }} !

8 | ` 9 | }) 10 | export class AppComponent implements OnInit { 11 | 12 | planet = 'Pluto'; 13 | constructor( @Inject( '$log' ) private _$log: ng.ILogService ) {} 14 | 15 | ngOnInit() { 16 | this._$log.log( 'hello from pluto during OnInit' ); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from 'ng-metadata/core'; 2 | import { AppComponent } from './app.component'; 3 | 4 | @NgModule( { 5 | declarations: [ 6 | AppComponent 7 | ] 8 | } ) 9 | export class AppModule { 10 | } 11 | -------------------------------------------------------------------------------- /src/app/app.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: black; 3 | color: navajowhite; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app.module'; 2 | -------------------------------------------------------------------------------- /src/app/shared/test-helpers.ts: -------------------------------------------------------------------------------- 1 | import { getInjectableName, bundle } from 'ng-metadata/core'; 2 | import { kebabCase } from 'lodash'; 3 | 4 | interface Type extends Function { 5 | new (...args: any[]): any; 6 | } 7 | 8 | /** 9 | * helper for getting tested components 10 | * - this is just temporary and will be removed when it's part if ngMetadata 11 | */ 12 | export function queryByDirective( host: ng.IAugmentedJQuery, Type: T ) { 13 | const ctrlName = getInjectableName( Type ); 14 | const selector = kebabCase( ctrlName ); 15 | const debugElement = host.find( selector ); 16 | const componentInstance = debugElement.controller( ctrlName ) as T; 17 | 18 | return { debugElement, componentInstance }; 19 | } 20 | 21 | 22 | export function createAngular1Module(NgMetadataModule: Type) { 23 | if (typeof NgMetadataModule !== 'function') { 24 | throw new Error(` 25 | [Angular module creation Error] 26 | You have to provide ngMetadata Module class with @NgModule decorator. You provided ${NgMetadataModule} 27 | `) 28 | } 29 | return bundle(NgMetadataModule).name 30 | } 31 | -------------------------------------------------------------------------------- /src/assets/images/pluto-the-planet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngParty/Angular1-scaffold/7f729d375f4a9baeaeea5c10d670b5e77bad8f3a/src/assets/images/pluto-the-planet.jpg -------------------------------------------------------------------------------- /src/globals.d.ts: -------------------------------------------------------------------------------- 1 | // we import angular type definition to support 'provide' ng-metadata function 2 | /// 3 | 4 | // Extra variables that live on Global that will be replaced by webpack DefinePlugin 5 | declare const ENV: string; 6 | interface GlobalEnvironment { 7 | ENV: typeof ENV 8 | } 9 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= webpackConfig.metadata.title %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Loading... 21 | 22 | 23 | 24 | 25 | <% if (webpackConfig.metadata.googleAnalytics) { %> 26 | 38 | <% } %> 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from 'ng-metadata/platform-browser-dynamic'; 2 | import { enableProdMode } from 'ng-metadata/core'; 3 | import { AppModule } from './app'; 4 | 5 | if ( ENV === 'production' ) { 6 | enableProdMode(); 7 | } 8 | 9 | 10 | platformBrowserDynamic().bootstrapModule( AppModule ); 11 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | // Added parts of es6 which are necessary for your project or your browser support requirements. 2 | import 'core-js/es6/symbol'; 3 | import 'core-js/es6/object'; 4 | import 'core-js/es6/function'; 5 | import 'core-js/es6/parse-int'; 6 | import 'core-js/es6/parse-float'; 7 | import 'core-js/es6/number'; 8 | import 'core-js/es6/math'; 9 | import 'core-js/es6/string'; 10 | import 'core-js/es6/date'; 11 | import 'core-js/es6/array'; 12 | import 'core-js/es6/regexp'; 13 | import 'core-js/es6/map'; 14 | import 'core-js/es6/set'; 15 | import 'core-js/es6/weak-map'; 16 | import 'core-js/es6/weak-set'; 17 | import 'core-js/es6/typed'; 18 | import 'core-js/es6/reflect'; 19 | 20 | import 'reflect-metadata'; 21 | 22 | import 'tslib'; 23 | -------------------------------------------------------------------------------- /src/vendor.ts: -------------------------------------------------------------------------------- 1 | import 'angular'; 2 | import 'ng-metadata/platform-browser-dynamic'; 3 | import 'ng-metadata/core'; 4 | import 'ng-metadata/common'; 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "noImplicitAny": false, 6 | "sourceMap": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "moduleResolution": "node", 10 | "pretty": true, 11 | "stripInternal": true, 12 | "noEmitHelpers": true, 13 | "outDir": "ts-out" 14 | }, 15 | "exclude": [ 16 | "node_modules" 17 | ], 18 | "compileOnSave": false 19 | } 20 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | 7 | "directive-selector": [true, "attribute", "np", "camelCase"], 8 | "component-selector": [true, "element", "np", "kebab-case"], 9 | "use-input-property-decorator": true, 10 | "use-output-property-decorator": true, 11 | "use-host-property-decorator": true, 12 | "no-attribute-parameter-decorator": true, 13 | "no-output-rename": true, 14 | "use-life-cycle-interface": true, 15 | "use-pipe-transform-interface": true, 16 | "pipe-naming": [true, "camelCase", "np"], 17 | "component-class-suffix": true, 18 | "directive-class-suffix": true, 19 | "templates-use-public": true, 20 | "no-access-missing-member": true, 21 | "invoke-injectable": true, 22 | 23 | "class-name": true, 24 | "radix": true, 25 | "eofline": true, 26 | "comment-format": [ 27 | true, 28 | "check-space" 29 | ], 30 | "indent": [ 31 | true, 32 | "spaces" 33 | ], 34 | "no-arg": true, 35 | "no-bitwise": true, 36 | "no-construct": true, 37 | "no-console": [ 38 | true, 39 | "log", 40 | "error" 41 | ], 42 | "no-use-before-declare": true, 43 | "no-unused-expression": true, 44 | "no-debugger": true, 45 | "no-conditional-assignment": true, 46 | "no-duplicate-variable": true, 47 | "no-eval": true, 48 | "no-internal-module": true, 49 | "no-trailing-whitespace": true, 50 | "no-var-keyword": true, 51 | "one-line": [ 52 | true, 53 | "check-catch", 54 | "check-else", 55 | "check-open-brace", 56 | "check-whitespace" 57 | ], 58 | "quotemark": [ 59 | true, 60 | "single" 61 | ], 62 | "triple-equals": [ 63 | true, 64 | "allow-null-check" 65 | ], 66 | "typedef-whitespace": [ 67 | true, 68 | { 69 | "call-signature": "nospace", 70 | "index-signature": "nospace", 71 | "parameter": "nospace", 72 | "property-declaration": "nospace", 73 | "variable-declaration": "nospace" 74 | }, 75 | { 76 | "call-signature": "onespace", 77 | "index-signature": "onespace", 78 | "parameter": "onespace", 79 | "property-declaration": "onespace", 80 | "variable-declaration": "onespace" 81 | } 82 | ], 83 | "variable-name": [ 84 | true, 85 | "ban-keywords", 86 | "allow-leading-underscore" 87 | ], 88 | "whitespace": [ 89 | true, 90 | "check-branch", 91 | "check-decl", 92 | "check-operator", 93 | "check-module", 94 | "check-separator", 95 | "check-type", 96 | "check-typecast" 97 | ], 98 | "max-line-length": [ 99 | true, 100 | 120 101 | ], 102 | "no-default-export": true, 103 | "member-ordering": [ 104 | true, 105 | "variables-before-functions" 106 | ], 107 | "one-variable-per-declaration": [ 108 | true 109 | ], 110 | "no-namespace": [ 111 | true, 112 | "allow-declarations" 113 | ], 114 | "no-invalid-this": [ 115 | true, 116 | "check-function-in-method" 117 | ] 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /webpack-build.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require( 'webpack' ); 2 | 3 | const webpackConfig = require( './webpack.config' ); 4 | 5 | /** 6 | * Static analysis linter for TypeScript advanced options configuration 7 | * Description: An extensible linter for the TypeScript language. 8 | * 9 | * See: https://github.com/wbuchwalter/tslint-loader 10 | */ 11 | const tslintConfig = { 12 | emitErrors: true, 13 | failOnHint: true 14 | }; 15 | 16 | const webpackConfigPlugins = [ 17 | // Reference: http://webpack.github.io/docs/list-of-plugins.html#noerrorsplugin 18 | // Only emit files when there are no errors 19 | new webpack.NoErrorsPlugin(), 20 | 21 | // Reference: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin 22 | // Dedupe modules in the output 23 | new webpack.optimize.DedupePlugin(), 24 | 25 | // Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin 26 | // Minify all javascript, switch loaders to minimizing mode 27 | new webpack.optimize.UglifyJsPlugin( { 28 | compress: { 29 | warnings: false 30 | } 31 | } ) 32 | ]; 33 | 34 | webpackConfig.plugins.push.apply( webpackConfig.plugins, webpackConfigPlugins ); 35 | 36 | Object.assign( webpackConfig, { 37 | watch: false, 38 | output: Object.assign( webpackConfig.output, { 39 | // Path where bundle files will be served on production env 40 | publicPath: '/' 41 | } ), 42 | tslint: Object.assign( webpackConfig.tslint, tslintConfig ) 43 | } ); 44 | 45 | module.exports = webpackConfig; 46 | -------------------------------------------------------------------------------- /webpack-test.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require( 'webpack' ); 2 | const webpackConfig = require( './webpack.config' ); 3 | 4 | 5 | /** 6 | * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack 7 | * 8 | * Do not change, leave as is or it wont work. 9 | * See: https://github.com/webpack/karma-webpack#source-maps 10 | */ 11 | const webpackDevtool = 'inline-source-map'; 12 | 13 | const webpackPostLoaders = [ 14 | 15 | /** 16 | * Instruments JS files with Istanbul for subsequent code coverage reporting. 17 | * Instrument only testing sources. 18 | * 19 | * See: https://github.com/deepsweet/istanbul-instrumenter-loader 20 | */ 21 | { 22 | test: /\.(js|ts)$/, 23 | loader: 'istanbul-instrumenter-loader', 24 | include: webpackConfig.resolve.root, 25 | exclude: [ 26 | /\.(e2e|spec)\.ts$/, 27 | /node_modules/, 28 | // @TODO this is temporary, will remove when typescript-helpers will be extracted to separate package 29 | /(polyfills|vendor)\.ts$/ 30 | ] 31 | } 32 | ]; 33 | 34 | const webpackNode = { 35 | /** 36 | * Include polyfills or mocks for various node stuff 37 | * Description: Node configuration 38 | * 39 | * See: https://webpack.github.io/docs/configuration.html#node 40 | */ 41 | process: false 42 | }; 43 | 44 | Object.assign( webpackConfig, { 45 | entry: {}, 46 | output: {}, 47 | devtool: webpackDevtool, 48 | watch: false, 49 | plugins: [], 50 | node: Object.assign( webpackConfig.node, webpackNode ) 51 | } ); 52 | Object.assign( webpackConfig.module, { 53 | postLoaders: webpackPostLoaders 54 | } ); 55 | 56 | module.exports = webpackConfig; 57 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require( 'path' ); 2 | const webpack = require( 'webpack' ); 3 | 4 | /** 5 | * Webpack Plugins 6 | */ 7 | const DefinePlugin = require('webpack/lib/DefinePlugin'); 8 | const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); 9 | const HtmlWebpackPlugin = require( 'html-webpack-plugin' ); 10 | 11 | /** 12 | * Webpack Constants 13 | */ 14 | const ENV = ( process.env.NODE_ENV || 'development' ); 15 | const ROOT = path.resolve( __dirname, 'src' ); 16 | const DESTINATION = path.resolve( __dirname, 'dist' ); 17 | 18 | /** 19 | * Static metadata for index.html 20 | * 21 | * See: (custom attribute) 22 | */ 23 | const METADATA = { 24 | baseUrl: '/', 25 | lang: 'en', 26 | title: 'Tombaugh Regio', 27 | ENV: JSON.stringify( ENV ), 28 | host: '0.0.0.0', 29 | // port is determined from npm config 30 | // which is set in package.json 31 | // "config": { 32 | // "port": "9000" 33 | // } 34 | port: process.env.npm_package_config_port || 9000, 35 | googleAnalytics: { 36 | trackingId: 'UA-XXXX-XX' 37 | } 38 | }; 39 | 40 | const webpackConfigEntryPoints = { 41 | /** 42 | * Cache generated modules and chunks to improve performance for multiple incremental builds. 43 | * This is enabled by default in watch mode. 44 | * You can pass false to disable it. 45 | * 46 | * See: http://webpack.github.io/docs/configuration.html#cache 47 | * cache: false, 48 | * 49 | * The entry point for the bundle 50 | * Our Angular.js app 51 | * 52 | * See: http://webpack.github.io/docs/configuration.html#entry 53 | */ 54 | polyfills: path.resolve( ROOT, 'polyfills.ts' ), 55 | vendor: path.resolve( ROOT, 'vendor.ts' ), 56 | main: path.resolve( ROOT, 'main.ts' ) 57 | }; 58 | 59 | /** 60 | * Developer tool to enhance debugging 61 | * 62 | * See: http://webpack.github.io/docs/configuration.html#devtool 63 | * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps 64 | */ 65 | // const webpackDevtool = 'source-map'; 66 | const webpackDevtool = '#cheap-module-source-map'; 67 | 68 | const webpackPreLoaders = [ 69 | 70 | /* 71 | * Tslint loader support for *.ts files 72 | * 73 | * See: https://github.com/wbuchwalter/tslint-loader 74 | */ 75 | // @TODO codelyzer is breaking somehow source maps, allow this when it will be resolved 76 | { 77 | test: /\.ts$/, 78 | loader: 'tslint-loader', 79 | exclude: [ /node_modules/ ] 80 | }, 81 | 82 | /** 83 | * Source map loader support for *.js files 84 | * Extracts SourceMaps for source files that as added as sourceMappingURL comment. 85 | * 86 | * See: https://github.com/webpack/source-map-loader 87 | */ 88 | { 89 | test: /\.js$/, 90 | loader: 'source-map-loader', 91 | exclude: [ 92 | // these packages have problems with their sourcemaps 93 | /node_modules\/ng-metadata/ 94 | // helpers.root( 'node_modules/rxjs' ), 95 | // helpers.root( 'node_modules/@angular2-material' ) 96 | ] 97 | } 98 | ]; 99 | 100 | const webpackConfigLoaders = [ 101 | 102 | // Scripts 103 | { 104 | test: /\.ts$/, 105 | exclude: [ /node_modules/ ], 106 | loader: 'awesome-typescript-loader' 107 | }, 108 | 109 | // Styles 110 | { 111 | test: /\.scss$/, 112 | loaders: [ 'style-loader', 'css-loader', 'sass-loader' ] 113 | }, 114 | 115 | /** 116 | * Raw loader support for *.css files 117 | * Returns file content as string 118 | * 119 | * See: https://github.com/webpack/raw-loader 120 | */ 121 | { 122 | test: /\.css$/, 123 | loaders: [ 'style-loader', 'css-loader' ] 124 | }, 125 | 126 | /** 127 | * Raw loader support for *.html 128 | * Returns file content as string 129 | * 130 | * See: https://github.com/webpack/raw-loader 131 | */ 132 | { 133 | test: /\.html$/, 134 | loader: 'raw-loader', 135 | exclude: [ path.resolve( ROOT, 'index.html' ) ] 136 | }, 137 | 138 | /* 139 | * Json loader support for *.json files. 140 | * 141 | * See: https://github.com/webpack/json-loader 142 | */ 143 | { 144 | test: /\.json$/, 145 | loader: 'json-loader' 146 | } 147 | 148 | ]; 149 | 150 | const webpackConfigPlugins = [ 151 | 152 | /** 153 | * Plugin: DefinePlugin 154 | * Description: Define free variables. 155 | * Useful for having development builds with debug logging or adding global constants. 156 | * 157 | * Environment helpers 158 | * 159 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin 160 | */ 161 | // NOTE: when adding more properties, make sure you include them in globals.d.ts 162 | new DefinePlugin( { 163 | ENV: METADATA.ENV, 164 | 'process.env': { 165 | ENV: METADATA.ENV, 166 | NODE_ENV: METADATA.ENV 167 | } 168 | } ), 169 | 170 | /** 171 | * Plugin: OccurenceOrderPlugin 172 | * Description: Varies the distribution of the ids to get the smallest id length 173 | * for often used ids. 174 | * 175 | * See: https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin 176 | * See: https://github.com/webpack/docs/wiki/optimization#minimize 177 | */ 178 | new webpack.optimize.OccurenceOrderPlugin( true ), 179 | 180 | /** 181 | * Plugin: CommonsChunkPlugin 182 | * Description: Shares common code between the pages. 183 | * It identifies common modules and put them into a commons chunk. 184 | * 185 | * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin 186 | * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app 187 | */ 188 | new webpack.optimize.CommonsChunkPlugin({ 189 | name: [ 'vendor', 'polyfills' ] 190 | }), 191 | 192 | /** 193 | * Plugin: CopyWebpackPlugin 194 | * Description: Copy files and directories in webpack. 195 | * 196 | * Copies project static assets. 197 | * 198 | * See: https://www.npmjs.com/package/copy-webpack-plugin 199 | */ 200 | new CopyWebpackPlugin( [ 201 | { 202 | from: 'src/assets', 203 | to: './' 204 | } 205 | ] ), 206 | 207 | /** 208 | * Plugin: HtmlWebpackPlugin 209 | * Description: Simplifies creation of HTML files to serve your webpack bundles. 210 | * This is especially useful for webpack bundles that include a hash in the filename 211 | * which changes every compilation. 212 | * 213 | * See: https://github.com/ampedandwired/html-webpack-plugin 214 | */ 215 | new HtmlWebpackPlugin( { 216 | template: path.resolve( ROOT, 'index.html' ), 217 | chunksSortMode: 'dependency' 218 | } ) 219 | 220 | ]; 221 | 222 | const webpackNode = { 223 | /** 224 | * Include polyfills or mocks for various node stuff 225 | * Description: Node configuration 226 | * 227 | * See: https://webpack.github.io/docs/configuration.html#node 228 | */ 229 | global: 'window', 230 | process: true, 231 | crypto: 'empty', 232 | module: false, 233 | clearImmediate: false, 234 | setImmediate: false 235 | }; 236 | 237 | 238 | /** 239 | * Static analysis linter for TypeScript advanced options configuration 240 | * Description: An extensible linter for the TypeScript language. 241 | * 242 | * See: https://github.com/wbuchwalter/tslint-loader 243 | */ 244 | const tslintConfig = { 245 | emitErrors: false, 246 | failOnHint: false, 247 | resourcePath: 'src' 248 | }; 249 | 250 | module.exports = { 251 | metadata: METADATA, 252 | devtool: webpackDevtool, 253 | entry: webpackConfigEntryPoints, 254 | output: { 255 | /** 256 | * The output directory as absolute path (required). 257 | * 258 | * See: http://webpack.github.io/docs/configuration.html#output-path 259 | */ 260 | path: DESTINATION, 261 | 262 | /** 263 | * Specifies the name of each output file on disk. 264 | * IMPORTANT: You must not specify an absolute path here! 265 | * 266 | * See: http://webpack.github.io/docs/configuration.html#output-filename 267 | */ 268 | filename: '[name].js', 269 | 270 | /** 271 | * The filename of the SourceMaps for the JavaScript files. 272 | * They are inside the output.path directory. 273 | * 274 | * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename 275 | */ 276 | sourceMapFilename: '[name].map', 277 | 278 | /** The filename of non-entry chunks as relative path 279 | * inside the output.path directory. 280 | * 281 | * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename 282 | */ 283 | chunkFilename: '[id].chunk.js' 284 | }, 285 | resolve: { 286 | /** 287 | * An array of extensions that should be used to resolve modules. 288 | * 289 | * See: http://webpack.github.io/docs/configuration.html#resolve-extensions 290 | */ 291 | extensions: [ '', '.ts', '.js' ], 292 | 293 | // Make sure root is src 294 | root: ROOT, 295 | 296 | // remove other default values 297 | modulesDirectories: [ 'node_modules' ] 298 | }, 299 | watch: true, 300 | module: { 301 | preLoaders: webpackPreLoaders, 302 | loaders: webpackConfigLoaders 303 | }, 304 | devServer: { 305 | // This is required for webpack-dev-server. The path should 306 | // be an absolute path to your build destination. 307 | outputPath: DESTINATION 308 | }, 309 | plugins: webpackConfigPlugins, 310 | tslint: tslintConfig, 311 | node: webpackNode 312 | }; 313 | --------------------------------------------------------------------------------