├── app ├── core │ ├── services.ts │ ├── components.ts │ ├── tests.ts │ ├── modules.ts │ └── bootstrap.ts ├── index.scss ├── common │ ├── component.ts │ ├── bindingTypes.ts │ └── service.ts ├── components │ └── dropdown │ │ ├── dropdown.scss │ │ ├── dropdown.html │ │ ├── dropdown.spec.ts │ │ └── dropdown.ts ├── app.d.ts ├── services │ └── stock-service.ts └── index.html ├── .gitignore ├── gulpfile.js ├── tsconfig.json ├── typings.json ├── webpack.config.js ├── karma.conf.js ├── package.json ├── tslint.json └── README.md /app/core/services.ts: -------------------------------------------------------------------------------- 1 | require('../services/stock-service.ts'); -------------------------------------------------------------------------------- /app/core/components.ts: -------------------------------------------------------------------------------- 1 | require('../components/dropdown/dropdown.ts'); -------------------------------------------------------------------------------- /app/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | color: red; 3 | } 4 | 5 | :fullscreen a { 6 | display: flex; 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/* 2 | !.gitkeep 3 | node_modules/ 4 | bower_components/ 5 | typings/ 6 | docs/ 7 | tmp 8 | .DS_Store 9 | .idea -------------------------------------------------------------------------------- /app/common/component.ts: -------------------------------------------------------------------------------- 1 | export class BaseComponent { 2 | public bindToController = true; 3 | public restrict = 'E'; 4 | } 5 | -------------------------------------------------------------------------------- /app/core/tests.ts: -------------------------------------------------------------------------------- 1 | require('../../node_modules/mocha/mocha.js'); 2 | export var chai = require('../../node_modules/chai/chai.js'); 3 | -------------------------------------------------------------------------------- /app/components/dropdown/dropdown.scss: -------------------------------------------------------------------------------- 1 | [component="DropDown"] { 2 | &.dropdown { 3 | a { 4 | color: pink !important; 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /app/core/modules.ts: -------------------------------------------------------------------------------- 1 | import * as angular from 'angular'; 2 | 3 | angular.module('app.services', []); 4 | angular.module('app', ['app.services']); 5 | -------------------------------------------------------------------------------- /app/common/bindingTypes.ts: -------------------------------------------------------------------------------- 1 | export class BindingType { 2 | public static ONE_WAY: string = '@'; 3 | public static TWO_WAY: string = '='; 4 | public static METHOD: string = '&'; 5 | } 6 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | gulp.task('ngdocs', [], function() { 6 | 7 | var gulpDocs = require('gulp-ngdocs'); 8 | 9 | return gulp.src('./app/**/*.ts') 10 | .pipe(gulpDocs.process()) 11 | .pipe(gulp.dest('./docs')); 12 | }); -------------------------------------------------------------------------------- /app/app.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Uncomment this to use a user defined require function 3 | */ 4 | 5 | //declare var require: { 6 | // (path: string): T; 7 | // (paths: string[], callback: (...modules: any[]) => void): void; 8 | // ensure: (paths: string[], callback: (require: (path: string) => T) => void) => void; 9 | //}; -------------------------------------------------------------------------------- /app/core/bootstrap.ts: -------------------------------------------------------------------------------- 1 | require('bootstrap-loader'); 2 | import '../index.scss'; 3 | import './modules.ts'; 4 | import './services.ts'; 5 | import './components.ts'; 6 | 7 | angular.element(document).ready( () => { 8 | angular.bootstrap(document, ['app'], { 9 | strictDi: true 10 | }); 11 | }); 12 | 13 | 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitAny": false, 5 | "removeComments": true, 6 | "preserveConstEnums": true, 7 | "sourceMap": true 8 | }, 9 | "exclude": [ 10 | "typings/browser.d.ts", 11 | "typings/browser", 12 | "node_modules" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /app/components/dropdown/dropdown.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/services/stock-service.ts: -------------------------------------------------------------------------------- 1 | import {HttpService} from "../common/service"; 2 | 3 | export interface Quote { 4 | name: string, 5 | symbol: string, 6 | lastPrice: number, 7 | high: number, 8 | low: number, 9 | open: number 10 | } 11 | 12 | export class StockService extends HttpService { 13 | 14 | getQuote(symbol: string): ng.IPromise { 15 | var url = `http://dev.markitondemand.com/MODApis/Api/v2/Quote/jsonp?symbol=${symbol}&callback=JSON_CALLBACK`; 16 | return this.jsonp(url); 17 | } 18 | 19 | } 20 | 21 | angular.module('app.services').service('stockService', StockService); 22 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nightwing - An Application Framework 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/components/dropdown/dropdown.spec.ts: -------------------------------------------------------------------------------- 1 | import '../../core/tests.ts'; 2 | import {chai} from '../../core/tests.ts'; 3 | 4 | var expect = chai.expect; 5 | 6 | describe('Unit tests for DropDown component', () => { 7 | 8 | describe('2 + 4', () => { 9 | 10 | it('should be 6', (done) => { 11 | expect(2 + 4).to.equal(6); 12 | done(); 13 | }); 14 | 15 | it('should not be 7', (done) => { 16 | expect(2 + 4).to.not.equals(7); 17 | done(); 18 | }); 19 | 20 | it('should be 10', (done) => { 21 | expect(6 + 4).to.equal(10); 22 | done(); 23 | }); 24 | 25 | it('should not be 20', (done) => { 26 | expect(10 + 10).to.not.equal(20); 27 | done(); 28 | }); 29 | 30 | }); 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /app/components/dropdown/dropdown.ts: -------------------------------------------------------------------------------- 1 | import './dropdown.scss'; 2 | 3 | import {BaseComponent} from "../../common/component"; 4 | import {BindingType} from '../../common/bindingTypes'; 5 | import {StockService} from "../../services/stock-service"; 6 | import {Quote} from "../../services/stock-service"; 7 | 8 | interface DropDownItem { 9 | href: string, 10 | label: string 11 | } 12 | 13 | class DropDownController { 14 | 15 | items: DropDownItem[]; 16 | stockService: StockService; 17 | 18 | static $inject = ['$scope', '$attrs', 'stockService']; 19 | 20 | constructor($scope: ng.IScope, $attrs: ng.IAttributes, stockService: StockService) { 21 | this.items = $scope.$eval($attrs['items']); 22 | 23 | stockService.getQuote('AAPL').then( (response: ng.IHttpPromiseCallbackArg) => { 24 | 25 | var quoteResponse: any = response.data; 26 | 27 | var quote: Quote = { 28 | name: quoteResponse.Name, 29 | symbol: quoteResponse.Symbol, 30 | lastPrice: quoteResponse.LastPrice, 31 | high: quoteResponse.High, 32 | low: quoteResponse.Low, 33 | open: quoteResponse.Open 34 | } 35 | 36 | console.log(quote); 37 | }); 38 | } 39 | } 40 | 41 | class DropDown extends BaseComponent { 42 | 43 | public scope = { 44 | name: BindingType.ONE_WAY 45 | }; 46 | 47 | public controllerAs = 'ctrl'; 48 | 49 | public controller = DropDownController; 50 | 51 | public template = require('./dropdown.html'); 52 | } 53 | 54 | angular 55 | .module('app') 56 | .directive('dropdown', () => new DropDown()); 57 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nightwing", 3 | "version": false, 4 | "ambientDependencies": { 5 | "angular": "registry:dt/angular#1.5.0+20160328125810", 6 | "assertion-error": "github:DefinitelyTyped/DefinitelyTyped/assertion-error/assertion-error.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 7 | "bluebird": "github:DefinitelyTyped/DefinitelyTyped/bluebird/bluebird.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 8 | "bootstrap": "github:DefinitelyTyped/DefinitelyTyped/bootstrap/bootstrap.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 9 | "chai": "github:DefinitelyTyped/DefinitelyTyped/chai/chai.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 10 | "express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 11 | "jquery": "github:DefinitelyTyped/DefinitelyTyped/jquery/jquery.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 12 | "karma": "github:DefinitelyTyped/DefinitelyTyped/karma/karma.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 13 | "lodash": "github:DefinitelyTyped/DefinitelyTyped/lodash/lodash.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 14 | "log4js": "github:DefinitelyTyped/DefinitelyTyped/log4js/log4js.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 15 | "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 16 | "mocha": "github:DefinitelyTyped/DefinitelyTyped/mocha/mocha.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 17 | "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 18 | "serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a", 19 | "socket.io-client": "github:DefinitelyTyped/DefinitelyTyped/socket.io-client/socket.io-client.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'), 4 | HtmlWebpackPlugin = require('html-webpack-plugin'), 5 | autoprefixer = require('autoprefixer'), 6 | ngAnnotatePlugin = require('ng-annotate-webpack-plugin'); 7 | 8 | module.exports = { 9 | 10 | entry: './app/core/bootstrap.ts', 11 | 12 | output: { 13 | path: __dirname + '/build', 14 | filename: 'bundle.js' 15 | }, 16 | 17 | devtool: 'source-map', 18 | 19 | resolve: { 20 | extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'] 21 | }, 22 | 23 | module: { 24 | 25 | preloaders: [ 26 | { 27 | test: /\.ts$/, 28 | loader: 'tslint' 29 | } 30 | ], 31 | 32 | loaders: [ 33 | { 34 | test: /\.html$/, 35 | loader: 'raw', 36 | }, 37 | { 38 | test: /\.ts$/, 39 | loader: 'ts' 40 | }, 41 | { 42 | test: /\.scss$/, 43 | loader: 'style!css!postcss!sass' 44 | }, 45 | { 46 | test: /bootstrap-sass\/assets\/javascripts\//, 47 | loader: 'imports?jQuery=jquery' 48 | }, 49 | { 50 | test: /\.(woff2?|svg)$/, 51 | loader: 'url?limit=10000' 52 | }, 53 | { 54 | test: /\.(ttf|eot)$/, 55 | loader: 'file' 56 | }, 57 | ] 58 | }, 59 | 60 | postcss: function() { 61 | return [autoprefixer]; 62 | }, 63 | 64 | node: { 65 | fs: "empty" 66 | }, 67 | 68 | plugins: [ 69 | new HtmlWebpackPlugin({ 70 | title: 'Nightwing - An Application Framework', 71 | filename: './index.html', 72 | template: './app/index.html', 73 | inject: false 74 | }), 75 | new webpack.ProvidePlugin({ 76 | jQuery: "jquery" 77 | }), 78 | new ngAnnotatePlugin({ 79 | add: true 80 | }) 81 | ] 82 | }; 83 | -------------------------------------------------------------------------------- /app/common/service.ts: -------------------------------------------------------------------------------- 1 | import 'socket.io-client'; 2 | 3 | /** 4 | * 5 | * @ngdoc service 6 | * @name HttpService 7 | * @requires $http 8 | * 9 | * @description 10 | * 11 | * Base class for a service which communicates with the server via HTTP. The service contains 12 | * all the HTTP methods and delegates to angular's $http service. An extension of this service 13 | * can implement its own logic and internally will have access to $http service's methods. 14 | * 15 | * {@link https://docs.angularjs.org/api/ng/service/$http} 16 | * 17 | **/ 18 | export class HttpService { 19 | 20 | $http: ng.IHttpService; 21 | 22 | static $inject = ['$http']; 23 | 24 | constructor($http: ng.IHttpService) { 25 | this.$http = $http; 26 | } 27 | 28 | get(url: string, config = {}): ng.IPromise { 29 | return this.$http.get(url, config); 30 | } 31 | 32 | delete(url: string, config = {}): ng.IPromise { 33 | return this.$http.delete(url, config); 34 | } 35 | 36 | head(url: string, config = {}): ng.IPromise { 37 | return this.$http.head(url, config); 38 | } 39 | 40 | jsonp(url: string, config = {}): ng.IPromise { 41 | return this.$http.jsonp(url, config); 42 | } 43 | 44 | post(url: string, data = {}, config = {}): ng.IPromise { 45 | return this.$http.post(url, data, config); 46 | } 47 | 48 | put(url: string, data = {}, config = {}): ng.IPromise { 49 | return this.$http.put(url, data, config); 50 | } 51 | 52 | patch(url: string, data = {}, config = {}): ng.IPromise { 53 | return this.$http.patch(url, data, config); 54 | } 55 | } 56 | 57 | export class SocketService { 58 | 59 | $socket: SocketIOClient.Socket; 60 | 61 | createConnection(endPoint: string) { 62 | this.$socket = io.connect(endPoint); 63 | } 64 | 65 | on(event: string, callback: () => void) { 66 | this.$socket.on(event, callback); 67 | } 68 | 69 | emit(event: string, data = {}, callback: () => void) { 70 | this.$socket.emit(event, [data, callback]); 71 | } 72 | 73 | } 74 | 75 | export class BufferService { 76 | 77 | } 78 | 79 | export class SoapService { 80 | 81 | } 82 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | var WebpackConfig = require('webpack-config'); 2 | 3 | // Karma configuration 4 | // Generated on Wed Dec 30 2015 11:13:38 GMT-0500 (EST) 5 | 6 | module.exports = function (config) { 7 | config.set({ 8 | 9 | // base path that will be used to resolve all patterns (eg. files, exclude) 10 | basePath: '.', 11 | 12 | files: [ 13 | 'app/**/*.spec.ts' 14 | ], 15 | 16 | 17 | // frameworks to use 18 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 19 | frameworks: ['mocha', 'chai'], 20 | 21 | 22 | // list of files to exclude 23 | exclude: [ 24 | 'node_modules' 25 | ], 26 | 27 | 28 | // test results reporter to use 29 | // possible values: 'dots', 'progress' 30 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 31 | reporters: ['progress', 'dots'], 32 | 33 | 34 | // web server port 35 | port: 9876, 36 | 37 | 38 | // enable / disable colors in the output (reporters and logs) 39 | colors: true, 40 | 41 | 42 | // level of logging 43 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 44 | logLevel: config.LOG_INFO, 45 | 46 | 47 | // enable / disable watching file and executing tests whenever any file changes 48 | autoWatch: true, 49 | 50 | 51 | // start these browsers 52 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 53 | browsers: ['PhantomJS'], 54 | 55 | 56 | // Continuous Integration mode 57 | // if true, Karma captures browsers, runs the tests and exits 58 | singleRun: false, 59 | 60 | // Concurrency level 61 | // how many browser should be started simultaneous 62 | concurrency: Infinity, 63 | 64 | preprocessors: { 65 | 'app/**/*.spec.ts': ['webpack'] 66 | }, 67 | 68 | webpack: new WebpackConfig().extend("webpack.config"), 69 | 70 | webpackMiddleware: { 71 | noInfo: true 72 | }, 73 | 74 | plugins: [ 75 | require('karma-mocha'), 76 | require('karma-chai'), 77 | require('karma-phantomjs-launcher'), 78 | require('karma-webpack') 79 | ] 80 | }) 81 | }; 82 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nightwing", 3 | "version": "0.0.1", 4 | "description": "Starter project and application development framework using future proof cutting edge web technologies", 5 | "main": "app.js", 6 | "scripts": { 7 | "setup": "npm install && typings install", 8 | "clean-docs": "rimraf docs/**/*", 9 | "clean-build": "rimraf build/**/*", 10 | "clean": "npm run clean-docs && npm run clean-build", 11 | "build": "npm run clean && webpack --progress --colors", 12 | "serve": "webpack-dev-server --content-base app/ --progress --colors --inline --hot", 13 | "test": "karma start" 14 | }, 15 | "keywords": [ 16 | "angular", 17 | "typescript", 18 | "bootstrap", 19 | "gulp", 20 | "webpack", 21 | "graphql", 22 | "rest", 23 | "soap", 24 | "socketio", 25 | "protobuf", 26 | "karma", 27 | "chai", 28 | "mocha", 29 | "jasmine", 30 | "protractor", 31 | "angular2.0" 32 | ], 33 | "author": "Daiyan Alamgir", 34 | "license": "ISC", 35 | "devDependencies": { 36 | "angular-mocks": "^1.5.3", 37 | "autoprefixer": "^6.3.3", 38 | "bootstrap-loader": "^1.0.1", 39 | "chai": "^3.4.1", 40 | "constants": "0.0.2", 41 | "css-loader": "^0.23.1", 42 | "extract-text-webpack-plugin": "^0.9.1", 43 | "file-loader": "^0.8.5", 44 | "gulp": "^3.9.0", 45 | "gulp-ngdocs": "^0.2.13", 46 | "html-webpack-plugin": "^1.7.0", 47 | "imports-loader": "^0.6.5", 48 | "karma": "^0.13.16", 49 | "karma-chai": "^0.1.0", 50 | "karma-chrome-launcher": "^0.2.2", 51 | "karma-cli": "^0.1.2", 52 | "karma-coverage": "^0.5.3", 53 | "karma-mocha": "^0.2.1", 54 | "karma-phantomjs-launcher": "^0.2.2", 55 | "karma-sourcemap-loader": "^0.3.6", 56 | "karma-webpack": "^1.7.0", 57 | "mocha": "^2.3.4", 58 | "ng-annotate-webpack-plugin": "^0.1.2", 59 | "node-sass": "^3.4.2", 60 | "phantomjs": "^1.9.19", 61 | "postcss-loader": "^0.8.0", 62 | "protractor": "^3.0.0", 63 | "raw-loader": "^0.5.1", 64 | "resolve-url-loader": "^1.4.3", 65 | "rimraf": "^2.5.0", 66 | "sass-loader": "^3.1.2", 67 | "style-loader": "^0.13.0", 68 | "ts-loader": "^0.7.2", 69 | "tslint": "^3.2.1", 70 | "tslint-loader": "^2.1.0", 71 | "typings": "^0.7.12", 72 | "typescript": "^1.8.9", 73 | "url-loader": "^0.5.7", 74 | "webpack": "^1.12.9", 75 | "webpack-config": "^3.1.0", 76 | "webpack-dev-server": "^1.14.0", 77 | "webpack-stream": "^3.1.0" 78 | }, 79 | "dependencies": { 80 | "angular": "^1.5.3", 81 | "bootstrap": "^3.3.6", 82 | "bootstrap-sass": "^3.3.6", 83 | "jquery": "^2.1.4", 84 | "socket.io-client": "^1.3.7" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "align": [ 4 | true, 5 | "parameters", 6 | "arguments", 7 | "statements" 8 | ], 9 | "ban": false, 10 | "class-name": true, 11 | "comment-format": [ 12 | true, 13 | "check-space", 14 | "check-lowercase" 15 | ], 16 | "curly": true, 17 | "eofline": true, 18 | "forin": true, 19 | "indent": [ 20 | true, 21 | "spaces" 22 | ], 23 | "interface-name": true, 24 | "jsdoc-format": true, 25 | "label-position": true, 26 | "label-undefined": true, 27 | "max-line-length": [ 28 | true, 29 | 140 30 | ], 31 | "member-access": true, 32 | "member-ordering": [ 33 | true, 34 | "public-before-private", 35 | "static-before-instance", 36 | "variables-before-functions" 37 | ], 38 | "no-any": false, 39 | "no-arg": true, 40 | "no-bitwise": true, 41 | "no-conditional-assignment": true, 42 | "no-consecutive-blank-lines": false, 43 | "no-console": [ 44 | true, 45 | "debug", 46 | "info", 47 | "time", 48 | "timeEnd", 49 | "trace" 50 | ], 51 | "no-construct": true, 52 | "no-constructor-vars": true, 53 | "no-debugger": true, 54 | "no-duplicate-key": true, 55 | "no-duplicate-variable": true, 56 | "no-empty": true, 57 | "no-eval": true, 58 | "no-inferrable-types": false, 59 | "no-internal-module": true, 60 | "no-null-keyword": true, 61 | "no-require-imports": true, 62 | "no-shadowed-variable": true, 63 | "no-string-literal": true, 64 | "no-switch-case-fall-through": true, 65 | "no-trailing-whitespace": true, 66 | "no-unreachable": true, 67 | "no-unused-expression": true, 68 | "no-unused-variable": true, 69 | "no-use-before-declare": true, 70 | "no-var-keyword": true, 71 | "no-var-requires": true, 72 | "object-literal-sort-keys": true, 73 | "one-line": [ 74 | true, 75 | "check-open-brace", 76 | "check-catch", 77 | "check-else", 78 | "check-whitespace" 79 | ], 80 | "quotemark": [ 81 | true, 82 | "double", 83 | "avoid-escape" 84 | ], 85 | "radix": true, 86 | "semicolon": true, 87 | "switch-default": true, 88 | "trailing-comma": [ 89 | true, 90 | { 91 | "multiline": "always", 92 | "singleline": "never" 93 | } 94 | ], 95 | "triple-equals": [ 96 | true, 97 | "allow-null-check" 98 | ], 99 | "typedef": [ 100 | true, 101 | "call-signature", 102 | "parameter", 103 | "property-declaration", 104 | "variable-declaration", 105 | "member-variable-declaration" 106 | ], 107 | "typedef-whitespace": [ 108 | true, 109 | { 110 | "call-signature": "nospace", 111 | "index-signature": "nospace", 112 | "parameter": "nospace", 113 | "property-declaration": "nospace", 114 | "variable-declaration": "nospace" 115 | } 116 | ], 117 | "use-strict": [ 118 | true, 119 | "check-module", 120 | "check-function" 121 | ], 122 | "variable-name": [ 123 | true, 124 | "check-format", 125 | "allow-leading-underscore", 126 | "ban-keywords" 127 | ], 128 | "whitespace": [ 129 | true, 130 | "check-branch", 131 | "check-decl", 132 | "check-operator", 133 | "check-separator", 134 | "check-type" 135 | ] 136 | } 137 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-next-starter-kit 2 | Seed project for developing angular 1.x applications in preparation for migrating on to Angular 2.0 3 | 4 | Angular 2.0 brings in quite a few new concepts and design patterns. However, Angular 2.0 is a few months away from being production ready. For those starting off with an Angular 1.x application but want to use the concepts of Angular 2.0 and some of the technologies used in Angular 2.0 today, then this starter kit may serve the purpose. 5 | 6 | The goals of this project is simple: 7 | * Focus on the application logic by: 8 | * Create a `service` to get some data (see **Creating a Service** below) 9 | * Create a `component` to use the data (see **Creating a Component** below) 10 | * Compose larger components using smaller components 11 | 12 | The developer **DOES NOT** have to worry about the following: 13 | * Configuring a `build system` 14 | * Configuring `unit tests`, `end-to-end tests`, `code coverage` 15 | * Provide `static analysis` and configure `typescript` 16 | * Automatically generate `documentation` 17 | 18 | # Features 19 | 20 | * Complete scaffolding with Angular 1.4.x 21 | * Typescript integration 22 | * Webpack bundling system with multiple loaders (sass, html, typescript) 23 | * Gulp integration (currently only one task to provide auto documentation) 24 | * Karma integration with Mocha, Chai, multiple browser launchers (Chrome, PhantomJS) and code coverage 25 | * Interfaces and APIs to create testable and reusable components 26 | * Various kinds of service interface 27 | * Http Service 28 | * Socket Service using Socket IO 29 | * SOAP Service using soap client 30 | * Buffer Service using ProtobufJS 31 | 32 | # Framework 33 | 34 | * Angular 1.4.x 35 | * Bootstrap (sass) 3.3.6 36 | * Socket IO Client 1.3.7 37 | * Typescript v1.7.5 38 | 39 | # Build 40 | 41 | * Webpack 42 | * Gulp 43 | 44 | # Test 45 | 46 | * Karma 47 | * Mocha 48 | * Chai 49 | * Protractor 50 | 51 | # Getting Started 52 | 53 | To get started using the seed project, complete the following steps: 54 | 55 | ## Clone the current repository 56 | 57 | ``` 58 | git clone https://github.com/alamgird/angular-next-starter-kit.git 59 | ``` 60 | 61 | ## Install all dependencies 62 | 63 | There are two kinds of dependencies in this project: 64 | 65 | 1. `NPM` dependencies which are used for development as well as application code 66 | 2. `Typescript` dependencies which are the definitely typed files for some of the `NPM` modules 67 | 68 | The following command will continue to install all dependencies: 69 | 70 | ``` 71 | npm run setup 72 | ``` 73 | 74 | ## Run the application 75 | 76 | To run the application with a development server with hot module reload, run the following command: 77 | 78 | ``` 79 | npm run serve 80 | ``` 81 | 82 | ## Run the tests 83 | 84 | To run the unit tests for the application, run the following command: 85 | 86 | ``` 87 | npm test 88 | ``` 89 | 90 | Integration tests are on their way. 91 | 92 | ## Package the application 93 | 94 | To produce a bundled application, run the following command: 95 | 96 | ``` 97 | npm run build 98 | ``` 99 | 100 | # Directory Structure 101 | 102 | ``` 103 | |-- app | Root directory for the application 104 | | 105 | |---- common | All modules common to the application 106 | |------ bindingTypes.ts | Module containing Angular binding types 107 | |------ component.ts | Interface for a BaseComponent 108 | |------ service.ts | Interfaces for HttpService, SocketService, SoapService and BufferService 109 | | 110 | |---- components | Root directory for all the components. Any component should go in here 111 | |------ dropdown | Sample implementation of a component 112 | |-------- dropdown.html | Template file for the component using Angular's template syntax 113 | |-------- dropdown.scss | Scoped styles for the component. This can now just be `required` in 114 | |-------- dropdown.spec.ts | Unit test spec file for the component. This should be local to the component 115 | |-------- dropdown.ts | Implementation of the component itself 116 | | 117 | |---- core | Utility modules that bootstrap the application 118 | |------ bootstrap.ts | Loads in all the other utility modules and bootstrap's Angular 119 | |------ components.ts | Holds references to all the components 120 | |------ modules.ts | Registers all the modules 121 | |------ services.ts | Holds references to all the services 122 | |------ tests.ts | Imports all the necessary modules needed for testing 123 | | 124 | |---- services 125 | |------ stock-service.ts | Reference implementation of an HttpService using JSONP 126 | | 127 | |---- utilities | Any utilities used across the application 128 | | 129 | |---- app.d.ts | Typescript definition file for the application 130 | |---- index.html | Main html file for the application 131 | |---- index.scss | Main css file for the application 132 | | 133 | |-- build | Contains the bundled application 134 | |-- docs | Contains all auto generated documentation 135 | |-- fonts | Contains application wide fonts 136 | |-- images | Contains application wide images 137 | |-- gulpfile | Gulp task file. Currently only one task to generate documentation is provided 138 | |-- karma.conf.js | Configuration file for the karma test runner 139 | |-- package.json | Contains NPM dependencies and application commands 140 | |-- tsconfig.json | Typescript compiler configuration 141 | |-- tsd.json | Contains references to definitely typed libraries 142 | |-- tslint.json | Configuration used by the tslint-loader 143 | |-- webpack.config.js | Webpack's global configuration file 144 | ``` 145 | 146 | # Creating a Service 147 | 148 | Suppose we want to create a service that gets **Stock Quote** from [Dev Markit API](http://dev.markitondemand.com/MODApis/). The service will take a **symbol** and return a **quote**. 149 | 150 | Create a file under `app/services/stock-service`. All services should go under `app/services`. 151 | 152 | ### First define a `Quote` object 153 | 154 | ``` 155 | export interface Quote { 156 | name: string, 157 | symbol: string, 158 | lastPrice: number, 159 | high: number, 160 | low: number, 161 | open: number 162 | } 163 | ``` 164 | 165 | Since `typescript` is used, the fields in the Quote object can be strongly typed. The interface should be exported since it may be used in other parts of the application. These interfaces can also be moved to a common file. 166 | 167 | ### Create an extension of HttpService interface 168 | 169 | An HttpService interface is already provided. Angular's `$http` service is automatically injected. All that needs to be done is a new class should be created **implementing the service logic**. 170 | 171 | ``` 172 | export class StockService extends HttpService { 173 | 174 | getQuote(symbol: string): ng.IPromise { 175 | var url = `http://dev.markitondemand.com/MODApis/Api/v2/Quote/jsonp?symbol=${symbol}&callback=JSON_CALLBACK`; 176 | return this.jsonp(url); 177 | } 178 | 179 | } 180 | ``` 181 | 182 | The `getQuote` method takes a `string` argument and returns an `ng.IPromise` which should eventually resolve to a `Quote` object. To read mode about angular's definitely typed objects, visit [AngularJS DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/angularjs). It is very clear from the code what this service does and what the method returns. 183 | 184 | ### Lastly, register the service 185 | 186 | An angular module `app.services` is readily available: 187 | 188 | ``` 189 | angular.module('app.services').service('stockService', StockService); 190 | ``` 191 | 192 | Now, this service is **ready to be injected into any component**. 193 | 194 | # Creating a Component 195 | 196 | All components should go under `app/components/[component-name]`. 197 | 198 | A component should be composed of 4 files 199 | * [component-name].html - Template for the component 200 | * [component-name].scss - Scoped styles for the component 201 | * [component-name].spec.ts - Unit test for the component 202 | * [component-name].ts - Implementation of the component logic 203 | 204 | Suppose we want to create a drop down component. Intuitively, the component should be used like this: 205 | 206 | ``` 207 | 210 | 211 | ``` 212 | 213 | ##### Create a template (dropdown.html): 214 | 215 | ``` 216 | 228 | ``` 229 | 230 | ##### Create a scoped stylesheet (dropdown.scss): 231 | ``` 232 | [component="DropDown"] { 233 | &.dropdown { 234 | a { 235 | color: pink !important; 236 | } 237 | } 238 | } 239 | ``` 240 | 241 | ##### Create the component implementation (dropdown.ts) by extending the BaseComponent: 242 | 243 | **See downdown.ts reference implementation** 244 | --------------------------------------------------------------------------------