├── .clang-format ├── .editorconfig ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .nvmrc ├── .travis.yml ├── .vscode ├── launch.json └── settings.json ├── Dockerfile ├── LICENSE ├── README.md ├── TODO.md ├── angular-cli.json ├── config ├── advance │ ├── helper.e2e.js │ ├── helpers.js │ ├── protractor.conf.js │ ├── update.md │ ├── webpack.common.js │ ├── webpack.common.web.js │ ├── webpack.desktop.build.main.js │ ├── webpack.desktop.build.renderer.js │ ├── webpack.desktop.dev.js │ ├── webpack.github-deploy.js │ ├── webpack.web.dev.js │ ├── webpack.web.e2e.js │ ├── webpack.web.prod.js │ └── webpack.web.test.js ├── custom │ ├── webpack.common.js │ ├── webpack.common.web.js │ ├── webpack.desktop.build.main.js │ ├── webpack.desktop.dev.js │ ├── webpack.web.dev.js │ ├── webpack.web.prod.js │ └── webpack.web.test.js ├── empty.js ├── github-deploy │ └── index.js ├── head-config.common.js ├── helpers.js ├── html-elements-plugin │ └── index.js ├── karma.conf.js ├── protractor.conf.js ├── resource-override.js ├── spec-bundle.js ├── webpack.common.js ├── webpack.dev.js ├── webpack.github-deploy.js ├── webpack.prod.js └── webpack.test.js ├── electron ├── main.desktop.ts ├── package.json └── tsconfig.json ├── firebase.json ├── karma.conf.js ├── netlify.toml ├── package.json ├── protractor.conf.js ├── src ├── app │ ├── app.advance.ts │ ├── app.config.ts │ ├── app.module.ts │ ├── app.resolver.ts │ ├── app.routerModule.desktop.ts │ ├── app.routerModule.ts │ ├── app.routes.ts │ ├── app.service.ts │ ├── components │ │ ├── about │ │ │ ├── about.component.e2e.ts │ │ │ ├── about.component.html │ │ │ ├── about.component.scss │ │ │ ├── about.component.spec.ts │ │ │ ├── about.component.tns.html │ │ │ ├── about.component.tns.scss │ │ │ ├── about.component.ts │ │ │ ├── about.module.ts │ │ │ ├── about.routing.ts │ │ │ └── index.ts │ │ ├── app.component.e2e.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.tns.html │ │ ├── app.component.ts │ │ ├── home │ │ │ ├── home.component.e2e.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.spec.ts │ │ │ ├── home.component.tns.html │ │ │ ├── home.component.tns.scss │ │ │ ├── home.component.ts │ │ │ ├── home.module.ts │ │ │ ├── home.routing.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── operators.ts │ ├── environment.ts │ ├── index.ts │ └── shared │ │ ├── analytics │ │ ├── analytics.module.ts │ │ ├── index.ts │ │ └── services │ │ │ ├── analytics.service.spec.ts │ │ │ └── analytics.service.ts │ │ ├── core │ │ ├── core.module.ts │ │ ├── directives │ │ │ ├── index.ts │ │ │ ├── platform.directive.spec.ts │ │ │ └── platform.directive.ts │ │ ├── index.ts │ │ ├── interfaces │ │ │ ├── iconsole.ts │ │ │ ├── ilang.ts │ │ │ ├── index.ts │ │ │ └── iwindow.ts │ │ ├── services │ │ │ ├── app.service.ts │ │ │ ├── console.service.ts │ │ │ ├── index.ts │ │ │ ├── log.service.spec.ts │ │ │ ├── log.service.ts │ │ │ ├── router-extensions.service.ts │ │ │ └── window.service.ts │ │ ├── testing │ │ │ ├── index.ts │ │ │ ├── mocks │ │ │ │ ├── mock-location-strategy.ts │ │ │ │ ├── ng2-config.mock.ts │ │ │ │ ├── router-extensions.mock.ts │ │ │ │ └── window.mock.ts │ │ │ └── providers │ │ │ │ ├── core.ts │ │ │ │ ├── http.ts │ │ │ │ └── router.ts │ │ └── utils │ │ │ ├── config.spec.ts │ │ │ ├── config.ts │ │ │ ├── index.ts │ │ │ ├── type.ts │ │ │ ├── view-broker.spec.ts │ │ │ └── view-broker.ts │ │ ├── electron │ │ ├── index.ts │ │ ├── services │ │ │ └── event.service.ts │ │ └── utils │ │ │ ├── desktop-config.spec.ts │ │ │ └── desktop-config.ts │ │ ├── i18n │ │ ├── actions │ │ │ ├── index.ts │ │ │ └── multilingual.action.ts │ │ ├── common │ │ │ ├── category.common.ts │ │ │ └── index.ts │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── lang-switcher.component.css │ │ │ ├── lang-switcher.component.html │ │ │ ├── lang-switcher.component.spec.ts │ │ │ ├── lang-switcher.component.tns.css │ │ │ ├── lang-switcher.component.tns.html │ │ │ ├── lang-switcher.component.tns.ios.css │ │ │ └── lang-switcher.component.ts │ │ ├── effects │ │ │ ├── index.ts │ │ │ └── multilingual.effect.ts │ │ ├── index.ts │ │ ├── multilingual.module.ts │ │ ├── reducers │ │ │ ├── index.ts │ │ │ └── multilingual.reducer.ts │ │ ├── services │ │ │ ├── i18n.providers.ts │ │ │ ├── index.ts │ │ │ ├── multilingual.service.spec.ts │ │ │ └── multilingual.service.ts │ │ ├── states │ │ │ ├── index.ts │ │ │ └── multilingual.state.ts │ │ └── testing │ │ │ ├── index.ts │ │ │ └── mocks │ │ │ ├── ng2-config-multilang.mock.ts │ │ │ ├── ng2-translate-loader.mock.ts │ │ │ └── ng2-translate.mock.ts │ │ ├── ngrx │ │ ├── index.ts │ │ └── state │ │ │ └── app.state.ts │ │ ├── sample │ │ ├── actions │ │ │ ├── index.ts │ │ │ └── name-list.action.ts │ │ ├── common │ │ │ ├── category.common.ts │ │ │ └── index.ts │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── navbar.component.css │ │ │ ├── navbar.component.html │ │ │ ├── navbar.component.tns.css │ │ │ ├── navbar.component.tns.html │ │ │ ├── navbar.component.ts │ │ │ ├── toolbar.component.css │ │ │ ├── toolbar.component.html │ │ │ ├── toolbar.component.tns.css │ │ │ ├── toolbar.component.tns.html │ │ │ └── toolbar.component.ts │ │ ├── effects │ │ │ ├── index.ts │ │ │ └── name-list.effect.ts │ │ ├── index.ts │ │ ├── reducers │ │ │ ├── index.ts │ │ │ └── name-list.reducer.ts │ │ ├── sample.module.ts │ │ ├── services │ │ │ ├── index.ts │ │ │ ├── name-list.service.spec.ts │ │ │ └── name-list.service.ts │ │ └── states │ │ │ ├── index.ts │ │ │ └── name-list.state.ts │ │ └── test │ │ ├── e2e │ │ └── dropdowns.ts │ │ ├── index.ts │ │ └── shorthand │ │ └── ng2-jasmine.ts ├── assets │ ├── 404.html │ ├── Angular.icontainer │ ├── css │ │ └── .gitkeep │ ├── data.json │ ├── googleplay │ │ └── icon.png │ ├── hdpi │ │ └── icon.png │ ├── humans.txt │ ├── i18n │ │ ├── bg.json │ │ ├── en.json │ │ ├── es.json │ │ ├── fr.json │ │ └── ru.json │ ├── icon-120x120.png │ ├── icon-128x128.png │ ├── icon-128x128@2x.png │ ├── icon-144x144.png │ ├── icon-16x16.png │ ├── icon-16x16@2x.png │ ├── icon-180x180.png │ ├── icon-18x18.png │ ├── icon-18x18@2x.png │ ├── icon-192x192.png │ ├── icon-20x20.png │ ├── icon-24x24.png │ ├── icon-24x24@2x.png │ ├── icon-256x256.png │ ├── icon-256x256@2x.png │ ├── icon-27.5x27.5@2x.png │ ├── icon-29x29.png │ ├── icon-29x29@2x.png │ ├── icon-29x29@3x.png │ ├── icon-32x32.png │ ├── icon-32x32@2x.png │ ├── icon-36x36.png │ ├── icon-40x40.png │ ├── icon-40x40@2x.png │ ├── icon-40x40@3x.png │ ├── icon-44x44@2x.png │ ├── icon-48x48.png │ ├── icon-50x50.png │ ├── icon-50x50@2x.png │ ├── icon-512x512.png │ ├── icon-512x512@2x.png │ ├── icon-57x57.png │ ├── icon-57x57@2x.png │ ├── icon-60x60@2x.png │ ├── icon-60x60@3x.png │ ├── icon-64x64.png │ ├── icon-72x72.png │ ├── icon-72x72@2x.png │ ├── icon-76x76.png │ ├── icon-76x76@2x.png │ ├── icon-83.5x83.5@2x.png │ ├── icon-86x86@2x.png │ ├── icon-96x96.png │ ├── icon-98x98@2x.png │ ├── icon.icns │ ├── icon.ico │ ├── icon.iconset │ │ ├── icon_128x128.png │ │ ├── icon_128x128@2x.png │ │ ├── icon_16x16.png │ │ ├── icon_16x16@2x.png │ │ ├── icon_256x256.png │ │ ├── icon_256x256@2x.png │ │ ├── icon_32x32.png │ │ ├── icon_32x32@2x.png │ │ ├── icon_512x512.png │ │ └── icon_512x512@2x.png │ ├── icon.tiff │ ├── icon │ │ ├── icon-38-Notification.png │ │ ├── icon-38-Short-Look.png │ │ ├── icon-42-Long-Look.png │ │ ├── icon-42-Notification.png │ │ ├── icon-42-Short-Look.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-72.png │ │ ├── icon-72@2x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ ├── icon-83.5@2x.png │ │ ├── icon-AppStore.png │ │ ├── icon-AppStore@2x.png │ │ ├── icon-CarPlay.png │ │ ├── icon-HomeScreen-38-Long-Look.png │ │ ├── icon-Small-40.png │ │ ├── icon-Small-40@2x.png │ │ ├── icon-Small-40@3x.png │ │ ├── icon-Small-50.png │ │ ├── icon-Small-50@2x.png │ │ ├── icon-Small.png │ │ ├── icon-Small@2x.png │ │ ├── icon-Small@3x.png │ │ ├── icon.png │ │ └── icon@2x.png │ ├── img │ │ └── angular-logo.png │ ├── ldpi │ │ └── icon.png │ ├── manifest.json │ ├── mdpi │ │ └── icon.png │ ├── preloadDesktop.js │ ├── robots.txt │ ├── service-worker.js │ ├── svg │ │ ├── more.svg │ │ └── smile.svg │ ├── xhdpi │ │ └── icon.png │ ├── xxhdpi │ │ └── icon.png │ └── xxxhdpi │ │ └── icon.png ├── custom-typings.d.ts ├── index.html ├── main.browser.aot.ts ├── main.browser.ts ├── meta │ ├── humans.txt │ └── robots.txt ├── polyfills.browser.ts └── styles │ ├── _variables.scss │ ├── headings.css │ └── styles.scss ├── tsconfig.desktop.json ├── tsconfig.json ├── tsconfig.webpack.json ├── tslint.json ├── typedoc.json ├── webpack.config.js └── yarn.lock /.clang-format: -------------------------------------------------------------------------------- 1 | Language: JavaScript 2 | BasedOnStyle: Google 3 | ColumnLimit: 100 -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | yarn.lock -diff 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at jonnybgod@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Read and contribute to the Wiki 2 | 3 | Make sure you read the [Wiki](https://github.com/JonnyBGod/angular2-webpack-advance-starter/wiki). 4 | 5 | ## Submitting Pull Requests 6 | 7 | If you're changing the structure of the repository please create an issue first. 8 | 9 | ## Submitting bug reports 10 | 11 | Make sure you are on latest changes and that you ran this command `npm run clean:install` after updating your local repository. If you can, please provide more information about your environment such as browser, operating system, node version, and npm version. 12 | 13 | ## Project Structure 14 | 15 | The configuration files are devided in config/, config/advance/ and config/custom 16 | - config/ files are upstream configuration files shared with [AngularClass's angular2-webpack-starter](https://github.com/AngularClass/angular2-webpack-starter) 17 | - config/advance/ files are the files related to this project 18 | - config/custom/ files should be left empty for end users only -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Note: for support questions, please use one of these channels:** [Chat: Gitter](https://gitter.im/angular2-webpack-advance-starter/Lobby) 2 | 3 | * **I'm submitting a ...** 4 | [ ] bug report 5 | [ ] feature request 6 | [ ] question about the decisions made in the repository 7 | 8 | * **Do you want to request a *feature* or report a *bug*?** 9 | 10 | 11 | 12 | * **What is the current behavior?** 13 | 14 | 15 | 16 | * **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via 17 | https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5). 18 | 19 | 20 | 21 | * **What is the expected behavior?** 22 | 23 | 24 | 25 | * **What is the motivation / use case for changing the behavior?** 26 | 27 | 28 | 29 | * **Please tell us about your environment:** 30 | 31 | - Angular version: 2.0.0-beta.X 32 | - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] 33 | 34 | 35 | 36 | * **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc) 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...) 2 | 3 | 4 | 5 | * **What is the current behavior?** (You can also link to an open issue here) 6 | 7 | 8 | 9 | * **What is the new behavior (if this is a feature change)?** 10 | 11 | 12 | 13 | * **Other information**: 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # @AngularClass 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Users Environment Variables 25 | .lock-wscript 26 | 27 | # OS generated files # 28 | .DS_Store 29 | ehthumbs.db 30 | Icon? 31 | Thumbs.db 32 | 33 | # Node Files # 34 | /node_modules/ 35 | /bower_components/ 36 | npm-debug.log 37 | /npm-debug.log.* 38 | yarn-error.log 39 | 40 | # Coverage # 41 | /coverage/ 42 | 43 | # Typing # 44 | /src/typings/tsd/ 45 | /typings/ 46 | /tsd_typings/ 47 | 48 | # Dist # 49 | /dist 50 | /public/__build__/ 51 | /src/*/__build__/ 52 | /__build__/** 53 | /public/dist/ 54 | /src/*/dist/ 55 | /dist/** 56 | /dist_desktop/** 57 | /.awcache 58 | .webpack.json 59 | /compiled/ 60 | dll/ 61 | 62 | # Doc # 63 | /doc/ 64 | 65 | # IDE # 66 | .idea/ 67 | *.swp 68 | 69 | # Angular # 70 | *.ngfactory.ts 71 | *.css.shim.ts 72 | *.ngsummary.json 73 | *.shim.ngstyle.ts 74 | 75 | # Advance # 76 | !/src/client/app/shared/test 77 | /nativescript/app 78 | /nativescript/hooks 79 | /nativescript/node_modules 80 | /nativescript/platforms 81 | /nativescript/**/*.js 82 | /nativescript/**/*.js.map 83 | /nativescript/*.d.ts 84 | !/nativescript/references.d.ts 85 | /desktop/ 86 | yarn-error.log -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "google", 3 | "maximumLineLength": 100 4 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "esversion": 6, 4 | "immed": true, 5 | "newcap": true, 6 | "noarg": true, 7 | "noempty": true, 8 | "nonew": true, 9 | "maxlen": 200, 10 | "boss": true, 11 | "eqnull": true, 12 | "expr": true, 13 | "laxbreak": true, 14 | "loopfunc": true, 15 | "strict": false, 16 | "sub": true, 17 | "undef": true, 18 | "indent": 2, 19 | 20 | "node": true, 21 | 22 | "globals": { 23 | "ArrayBuffer": false, 24 | "Uint8Array": false 25 | } 26 | } -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | addons: 4 | apt: 5 | sources: 6 | - google-chrome 7 | packages: 8 | - google-chrome-stable 9 | language: node_js 10 | node_js: 11 | - "6" 12 | - "7" 13 | - "node" 14 | matrix: 15 | fast_finish: true 16 | before_install: 17 | - npm i npm@^4 -g 18 | install: 19 | - npm install 20 | before_script: 21 | - export DISPLAY=:99.0 22 | - sh -e /etc/init.d/xvfb start 23 | - sleep 3 24 | script: 25 | - npm run ci:travis 26 | cache: 27 | directories: 28 | - node_modules 29 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Chrome against localhost, with sourcemaps", 6 | "type": "chrome", 7 | "request": "launch", 8 | "url": "http://localhost:3000/*", 9 | "runtimeArgs": [ 10 | "--disable-web-security", 11 | "--user-data-dir", 12 | "--remote-debugging-port=9222" 13 | ], 14 | "sourceMaps": true, 15 | "webRoot": "${workspaceRoot}" 16 | }, 17 | { 18 | "name": "Attach to Chrome, with sourcemaps", 19 | "type": "chrome", 20 | "request": "attach", 21 | "url": "http://localhost:3000/*", 22 | "port": 9222, 23 | "sourceMaps": true, 24 | "webRoot": "${workspaceRoot}" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib/" 3 | } 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Builds a Docker to deliver dist/ 2 | FROM nginx:latest 3 | COPY dist/ /usr/share/nginx/html -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 JonnyBGod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | TODO 2 | ==== 3 | 4 | - [ ] Nativescript (https://github.com/NativeScript/nativescript-angular/issues/385) 5 | - [ ] Make sure all commands work on windows 6 | 7 | ## Improvements 8 | 9 | - [ ] Angular Universal (upstream?) (should?) 10 | - [ ] Make new repo for nativescript and npm run setup:nativescript 11 | - [ ] Make new repo for electron and npm run setup:electron 12 | - [ ] Make clean extension scripts (npm run clean:nativescript) 13 | - [ ] CI release all platforms for demo app 14 | - [ ] Gitlab CI 15 | 16 | ## Extras (branches?) 17 | 18 | - [ ] Windows Universal App 19 | - [ ] Ionic 20 | - [ ] React Native 21 | 22 | ## Bugs 23 | 24 | ## Before commit manual checks 25 | 26 | - [x] npm run ci 27 | 28 | - [x] npm start 29 | - [x] npm run docs 30 | - [x] npm run build:aot:desktop 31 | - [x] npm run github-deploy:aot 32 | 33 | ./nativescript 34 | - [ ] npm run start:ios 35 | - [ ] npm run start:android 36 | 37 | ... more nativescript related -------------------------------------------------------------------------------- /angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": { 3 | "version": "1.0.0-beta.24", 4 | "name": "angular2-webpack-advance-starter" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "dist", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "test": "test.ts", 17 | "tsconfig": "tsconfig.json", 18 | "prefix": "app", 19 | "mobile": false, 20 | "styles": [ 21 | "styles.css" 22 | ], 23 | "scripts": [], 24 | "environments": { 25 | "source": "environments/environment.ts", 26 | "dev": "environments/environment.ts", 27 | "prod": "environments/environment.prod.ts" 28 | } 29 | } 30 | ], 31 | "addons": [], 32 | "packages": [], 33 | "e2e": { 34 | "protractor": { 35 | "config": "./protractor.conf.js" 36 | } 37 | }, 38 | "test": { 39 | "karma": { 40 | "config": "./karma.conf.js" 41 | } 42 | }, 43 | "defaults": { 44 | "styleExt": "scss", 45 | "prefixInterfaces": false, 46 | "inline": { 47 | "style": false, 48 | "template": false 49 | }, 50 | "spec": { 51 | "class": false, 52 | "component": true, 53 | "directive": true, 54 | "module": false, 55 | "pipe": true, 56 | "service": true 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /config/advance/helper.e2e.js: -------------------------------------------------------------------------------- 1 | var req = require.context('../../src', true, /\.e2e\.ts/); 2 | req.keys().forEach(req); -------------------------------------------------------------------------------- /config/advance/helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | var path = require('path'); 5 | const EVENT = process.env.npm_lifecycle_event || ''; 6 | 7 | // Helper functions 8 | var ROOT = path.resolve(__dirname, '../..'); 9 | 10 | function hasProcessFlag(flag) { 11 | return process.argv.join('').indexOf(flag) > -1; 12 | } 13 | 14 | function hasNpmFlag(flag) { 15 | return EVENT.includes(flag); 16 | } 17 | 18 | function isWebpackDevServer() { 19 | return process.argv[1] && !! (/webpack-dev-server$/.exec(process.argv[1])); 20 | } 21 | 22 | function root(args) { 23 | args = Array.prototype.slice.call(arguments, 0); 24 | return path.join.apply(path, [ROOT].concat(args)); 25 | } 26 | 27 | function checkNodeImport(context, request, cb) { 28 | if (!path.isAbsolute(request) && request.charAt(0) !== '.') { 29 | cb(null, 'commonjs ' + request); return; 30 | } 31 | cb(); 32 | } 33 | 34 | function removePlugins(plugins, test) { 35 | for (var i = plugins.length - 1; i >= 0; i--) { 36 | if (test.filter(function(t) { return plugins[i] instanceof t;}).length > 0) { 37 | plugins.splice(i, 1); 38 | } 39 | } 40 | return; 41 | } 42 | 43 | function removeRules(rules, test) { 44 | for (var i = rules.length - 1; i >= 0; i--) { 45 | if (test.filter(function(t) { return t.toString() === rules[i].test.toString();}).length > 0) { 46 | rules.splice(i, 1); 47 | } 48 | } 49 | return; 50 | } 51 | 52 | exports.hasProcessFlag = hasProcessFlag; 53 | exports.hasNpmFlag = hasNpmFlag; 54 | exports.isWebpackDevServer = isWebpackDevServer; 55 | exports.root = root; 56 | exports.checkNodeImport = checkNodeImport; 57 | exports.removePlugins = removePlugins; 58 | exports.removeRules = removeRules; 59 | -------------------------------------------------------------------------------- /config/advance/protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | var helpers = require('./helpers'); 6 | 7 | exports.config = { 8 | baseUrl: 'http://localhost:3000/', 9 | 10 | // use `npm run e2e` 11 | specs: [ 12 | helpers.root('_temp/tests/**/**.e2e.js'), 13 | helpers.root('_temp/tests/**/*.e2e.js') 14 | ], 15 | exclude: [], 16 | 17 | framework: 'jasmine2', 18 | 19 | allScriptsTimeout: 110000, 20 | 21 | jasmineNodeOpts: { 22 | showTiming: true, 23 | showColors: true, 24 | isVerbose: false, 25 | includeStackTrace: false, 26 | defaultTimeoutInterval: 400000 27 | }, 28 | directConnect: true, 29 | 30 | capabilities: { 31 | 'browserName': 'chrome', 32 | 'chromeOptions': { 33 | 'args': ['show-fps-counter=true'] 34 | } 35 | }, 36 | 37 | onPrepare: function() { 38 | browser.ignoreSynchronization = true; 39 | }, 40 | 41 | /** 42 | * Angular 2 configuration 43 | * 44 | * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching 45 | * `rootEl` 46 | */ 47 | useAllAngular2AppRoots: true 48 | }; -------------------------------------------------------------------------------- /config/advance/update.md: -------------------------------------------------------------------------------- 1 | # Help upstream update 2 | 3 | ## package.json 4 | copy/paste all dependencies from upstream 5 | 6 | npm i --save @ngrx/core @ngrx/store ng2-translate lodash-es angulartics2 7 | npm i --save-dev electron-builder electron-debug electron-prebuilt node-sass postcss-loader sass-loader webpack-target-electron-renderer @types/lodash 8 | -------------------------------------------------------------------------------- /config/advance/webpack.common.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpack = require('webpack'); 7 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 8 | 9 | const customConfig = require('../custom/webpack.common.js'); 10 | 11 | /** 12 | * Webpack Plugins 13 | */ 14 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 15 | const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin'); 16 | const DefinePlugin = require('webpack/lib/DefinePlugin'); 17 | 18 | /** 19 | * Webpack Constants 20 | */ 21 | const METADATA = Object.assign({ 22 | baseUrl: '/', 23 | isDevServer: helpers.isWebpackDevServer() 24 | }, customConfig.metadata); 25 | 26 | /** 27 | * Webpack configuration 28 | * 29 | * See: http://webpack.github.io/docs/configuration.html#cli 30 | */ 31 | module.exports = function(options) { 32 | return webpackMerge.smart({ 33 | 34 | resolve: { 35 | alias: { 36 | components: helpers.root('src/app/components'), 37 | shared: helpers.root('src/app/shared'), 38 | assets: helpers.root('src/assets') 39 | } 40 | }, 41 | 42 | module: { 43 | 44 | /* 45 | * An array of automatically applied loaders. 46 | * 47 | * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. 48 | * This means they are not resolved relative to the configuration file. 49 | * 50 | * See: http://webpack.github.io/docs/configuration.html#module-loaders 51 | */ 52 | rules: [ 53 | { test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url-loader?limit=10000' } 54 | ] 55 | 56 | }, 57 | 58 | plugins: [ 59 | new NormalModuleReplacementPlugin( 60 | /routerModule/, 61 | helpers.root('src/app/app.routerModule.ts') 62 | ), 63 | /** 64 | * Plugin: DefinePlugin 65 | * Description: Define free variables. 66 | * Useful for having development builds with debug logging or adding global constants. 67 | * 68 | * Environment helpers 69 | * 70 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin 71 | */ 72 | // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts 73 | new DefinePlugin({ 74 | 'BASE_URL': JSON.stringify(METADATA.baseUrl), 75 | 'RUN_DEMO': METADATA.runDemo 76 | }), 77 | 78 | new HtmlWebpackPlugin({ 79 | template: 'src/index.html', 80 | title: METADATA.title, 81 | chunksSortMode: 'dependency', 82 | metadata: METADATA, 83 | inject: 'head' 84 | }), 85 | 86 | new webpack.LoaderOptionsPlugin({ 87 | options: { 88 | context: helpers.root(), 89 | output: { 90 | path: helpers.root('dist') 91 | } 92 | } 93 | }) 94 | ], 95 | 96 | /*externals: [ 97 | (function () { 98 | var IGNORES = [ 99 | 'electron', 'electron-debug' 100 | ]; 101 | return function (context, request, callback) { 102 | if (IGNORES.indexOf(request) >= 0) { 103 | return callback(null, "require('" + request + "')"); 104 | } 105 | return callback(); 106 | }; 107 | })() 108 | ]*/ 109 | 110 | }, customConfig.config()); 111 | } 112 | -------------------------------------------------------------------------------- /config/advance/webpack.common.web.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 7 | 8 | const commonAdvanceConfig = require('./webpack.common.js'); 9 | const customConfig = require('../custom/webpack.common.web.js'); 10 | 11 | /** 12 | * Webpack configuration 13 | * 14 | * See: http://webpack.github.io/docs/configuration.html#cli 15 | */ 16 | module.exports = function(options) { 17 | return webpackMerge.smart(commonAdvanceConfig(), { 18 | 19 | }, customConfig()); 20 | } 21 | -------------------------------------------------------------------------------- /config/advance/webpack.desktop.build.renderer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 7 | 8 | const commonAdvanceConfig = require('./webpack.common.web.js'); 9 | const simpleWebProdConfig = require('../webpack.prod.js'); 10 | const customCommonConfig = require('../custom/webpack.common.js'); 11 | const customConfig = require('../custom/webpack.web.prod.js'); 12 | 13 | /** 14 | * Webpack Constants 15 | */ 16 | const ENV = process.env.ENV = process.env.NODE_ENV = 'production'; 17 | const AOT = helpers.hasNpmFlag('aot'); 18 | 19 | /** 20 | * Webpack Plugins 21 | */ 22 | const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin'); 23 | const DefinePlugin = require('webpack/lib/DefinePlugin'); 24 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 25 | const ngcWebpack = require('ngc-webpack'); 26 | 27 | 28 | const METADATA = Object.assign({ 29 | baseUrl: '', 30 | isDevServer: helpers.isWebpackDevServer() 31 | }, customConfig.metadata); 32 | 33 | let webpackConfig = webpackMerge.smart(simpleWebProdConfig({env: ENV}), commonAdvanceConfig({env: ENV})); 34 | 35 | // remove the plugins to be overwriten. 36 | helpers.removePlugins(webpackConfig.plugins, [ 37 | HtmlWebpackPlugin, 38 | ngcWebpack.NgcWebpackPlugin 39 | ]); 40 | // remove the rules to be overwriten. 41 | helpers.removeRules(webpackConfig.module.rules, [/\.ts$/]); 42 | 43 | /** 44 | * Webpack configuration 45 | * 46 | * See: http://webpack.github.io/docs/configuration.html#cli 47 | */ 48 | module.exports = function(options) { 49 | isProd = ENV === 'production'; 50 | 51 | return webpackMerge.smart(webpackConfig, { 52 | module: { 53 | rules: [ 54 | /* 55 | * Typescript loader support for .ts and Angular 2 async routes via .async.ts 56 | * Replace templateUrl and stylesUrl with require() 57 | * 58 | * See: https://github.com/s-panferov/awesome-typescript-loader 59 | * See: https://github.com/TheLarkInn/angular2-template-loader 60 | */ 61 | { 62 | test: /\.ts$/, 63 | use: [ 64 | '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd, 65 | { 66 | loader: 'ng-router-loader', 67 | options: { 68 | loader: 'async-import', 69 | genDir: 'compiled', 70 | aot: AOT 71 | } 72 | }, 73 | 'awesome-typescript-loader?{configFileName: "tsconfig.desktop.json"}', 74 | 'angular2-template-loader' 75 | ], 76 | exclude: [/\.(spec|e2e)\.ts$/] 77 | }, 78 | ] 79 | }, 80 | 81 | plugins: [ 82 | new NormalModuleReplacementPlugin( 83 | /routerModule/, 84 | helpers.root('src/app/app.routerModule.desktop.ts') 85 | ), 86 | 87 | new ngcWebpack.NgcWebpackPlugin({ 88 | disabled: !AOT, 89 | tsConfig: helpers.root('tsconfig.desktop.json'), 90 | resourceOverride: helpers.root('config/resource-override.js') 91 | }), 92 | 93 | new DefinePlugin({ 94 | 'BASE_URL': METADATA.baseUrl, 95 | 'TARGET_DESKTOP': true, 96 | 'TARGET_DESKTOP_BUILD': true 97 | }), 98 | 99 | new HtmlWebpackPlugin({ 100 | template: 'src/index.html', 101 | title: METADATA.title, 102 | chunksSortMode: 'dependency', 103 | metadata: METADATA, 104 | inject: 'head' 105 | }), 106 | ] 107 | }, customConfig({env: ENV})); 108 | } 109 | -------------------------------------------------------------------------------- /config/advance/webpack.web.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 7 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 8 | 9 | const commonAdvanceConfig = require('./webpack.common.web.js'); 10 | const simpleWebDevConfig = require('../webpack.dev.js'); 11 | const customConfig = require('../custom/webpack.web.dev.js'); 12 | 13 | /** 14 | * Webpack Constants 15 | */ 16 | const ENV = process.env.ENV = process.env.NODE_ENV = 'development'; 17 | 18 | let webpackConfig = simpleWebDevConfig({env: ENV}); 19 | // remove the instance of HtmlWebpackPlugin. 20 | helpers.removePlugins(webpackConfig.plugins, [HtmlWebpackPlugin]); 21 | 22 | /** 23 | * Webpack configuration 24 | * 25 | * See: http://webpack.github.io/docs/configuration.html#cli 26 | */ 27 | module.exports = function(options) { 28 | return webpackMerge.smart(webpackConfig, commonAdvanceConfig({env: ENV}), { 29 | 30 | }, customConfig({env: ENV})); 31 | } -------------------------------------------------------------------------------- /config/advance/webpack.web.e2e.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | 7 | /** 8 | * Webpack Constants 9 | */ 10 | const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; 11 | 12 | /** 13 | * Webpack configuration 14 | * 15 | * See: http://webpack.github.io/docs/configuration.html#cli 16 | */ 17 | module.exports = function(options) { 18 | return { 19 | entry: helpers.root('config/advance/helper.e2e.js'), 20 | 21 | resolve: { 22 | 23 | /* 24 | * An array of extensions that should be used to resolve modules. 25 | * 26 | * See: http://webpack.github.io/docs/configuration.html#resolve-extensions 27 | */ 28 | extensions: ['.ts', '.js', '.json'], 29 | 30 | modules: [ 31 | helpers.root('src'), 32 | 'node_modules' 33 | ], 34 | 35 | alias: { 36 | components: helpers.root('src/app/components'), 37 | shared: helpers.root('src/app/shared'), 38 | assets: helpers.root('src/assets') 39 | }, 40 | 41 | }, 42 | 43 | module: { 44 | rules: [ 45 | { 46 | test: /\.ts$/, 47 | loader: 'awesome-typescript-loader' 48 | } 49 | ] 50 | }, 51 | 52 | /** 53 | * Developer tool to enhance debugging 54 | * 55 | * See: http://webpack.github.io/docs/configuration.html#devtool 56 | * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps 57 | */ 58 | devtool: 'source-map', 59 | 60 | /** 61 | * Options affecting the output of the compilation. 62 | * 63 | * See: http://webpack.github.io/docs/configuration.html#output 64 | */ 65 | output: { 66 | 67 | /** 68 | * The output directory as absolute path (required). 69 | * 70 | * See: http://webpack.github.io/docs/configuration.html#output-path 71 | */ 72 | path: helpers.root('_temp/tests'), 73 | 74 | /** 75 | * Specifies the name of each output file on disk. 76 | * IMPORTANT: You must not specify an absolute path here! 77 | * 78 | * See: http://webpack.github.io/docs/configuration.html#output-filename 79 | */ 80 | filename: '[name].e2e.js', 81 | 82 | /** 83 | * The filename of the SourceMaps for the JavaScript files. 84 | * They are inside the output.path directory. 85 | * 86 | * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename 87 | */ 88 | sourceMapFilename: '[name].e2e.map', 89 | 90 | /** 91 | * The filename of non-entry chunks as relative path 92 | * inside the output.path directory. 93 | * 94 | * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename 95 | */ 96 | chunkFilename: '[id].chunk.js' 97 | 98 | }, 99 | 100 | target: 'node', 101 | 102 | node: { 103 | __dirname: false, 104 | __filename: false, 105 | } 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /config/advance/webpack.web.prod.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 7 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 8 | 9 | const commonAdvanceConfig = require('./webpack.common.web.js'); 10 | const simpleWebProdConfig = require('../webpack.prod.js'); 11 | const customConfig = require('../custom/webpack.web.prod.js'); 12 | 13 | /** 14 | * Webpack Constants 15 | */ 16 | const ENV = process.env.ENV = process.env.NODE_ENV = 'production'; 17 | 18 | let webpackConfig = simpleWebProdConfig({env: ENV}); 19 | // remove the instance of HtmlWebpackPlugin. 20 | helpers.removePlugins(webpackConfig.plugins, [HtmlWebpackPlugin]); 21 | 22 | /** 23 | * Webpack configuration 24 | * 25 | * See: http://webpack.github.io/docs/configuration.html#cli 26 | */ 27 | module.exports = function(options) { 28 | return webpackMerge.smart(webpackConfig, commonAdvanceConfig({env: ENV}), { 29 | 30 | }, customConfig({env: ENV})); 31 | } 32 | -------------------------------------------------------------------------------- /config/advance/webpack.web.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @JonnyBGod 3 | */ 4 | 5 | const helpers = require('./helpers'); 6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 7 | 8 | const HtmlElementsPlugin = require('../html-elements-plugin'); 9 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 10 | const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); 11 | 12 | const commonAdvanceConfig = require('./webpack.common.web.js'); 13 | const simpleWebTestConfig = require('../webpack.test.js'); 14 | const customConfig = require('../custom/webpack.web.test.js'); 15 | 16 | /** 17 | * Webpack Constants 18 | */ 19 | const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; 20 | 21 | let webpackConfig = simpleWebTestConfig({env: ENV}); 22 | // remove the instance of HtmlWebpackPlugin. 23 | helpers.removePlugins(webpackConfig.plugins, [HtmlWebpackPlugin]); 24 | 25 | /** 26 | * Webpack configuration 27 | * 28 | * See: http://webpack.github.io/docs/configuration.html#cli 29 | */ 30 | module.exports = function(options) { 31 | return webpackMerge.smart(webpackConfig, commonAdvanceConfig({env: ENV}), { 32 | 33 | plugins: [ 34 | /* 35 | * Plugin: ScriptExtHtmlWebpackPlugin 36 | * Description: Enhances html-webpack-plugin functionality 37 | * with different deployment options for your scripts including: 38 | * 39 | * See: https://github.com/numical/script-ext-html-webpack-plugin 40 | */ 41 | new ScriptExtHtmlWebpackPlugin({ 42 | defaultAttribute: 'defer' 43 | }), 44 | 45 | /* 46 | * Plugin: HtmlElementsPlugin 47 | * Description: Generate html tags based on javascript maps. 48 | * 49 | * If a publicPath is set in the webpack output configuration, it will be automatically added to 50 | * href attributes, you can disable that by adding a "=href": false property. 51 | * You can also enable it to other attribute by settings "=attName": true. 52 | * 53 | * The configuration supplied is map between a location (key) and an element definition object (value) 54 | * The location (key) is then exported to the template under then htmlElements property in webpack configuration. 55 | * 56 | * Example: 57 | * Adding this plugin configuration 58 | * new HtmlElementsPlugin({ 59 | * headTags: { ... } 60 | * }) 61 | * 62 | * Means we can use it in the template like this: 63 | * <%= webpackConfig.htmlElements.headTags %> 64 | * 65 | * Dependencies: HtmlWebpackPlugin 66 | */ 67 | new HtmlElementsPlugin({ 68 | headTags: require('../head-config.common') 69 | }), 70 | ] 71 | 72 | }, customConfig({env: ENV})); 73 | } 74 | -------------------------------------------------------------------------------- /config/custom/webpack.common.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | 7 | module.exports = { 8 | metadata: { 9 | title: 'Angular2 Webpack Advance Starter', 10 | GOOGLE_ANALYTICS: 'YOUR_ANALYTICS_ID' 11 | }, 12 | config: function(options) { 13 | return { 14 | 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /config/custom/webpack.common.web.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /config/custom/webpack.desktop.build.main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } -------------------------------------------------------------------------------- /config/custom/webpack.desktop.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /config/custom/webpack.web.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /config/custom/webpack.web.prod.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /config/custom/webpack.web.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack configuration 3 | * 4 | * See: http://webpack.github.io/docs/configuration.html#cli 5 | */ 6 | module.exports = function(options) { 7 | return { 8 | 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /config/empty.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NgProbeToken: {}, 3 | HmrState: function() {}, 4 | _createConditionalRootRenderer: function(rootRenderer, extraTokens, coreTokens) { 5 | return rootRenderer; 6 | }, 7 | __platform_browser_private__: {} 8 | }; 9 | -------------------------------------------------------------------------------- /config/github-deploy/index.js: -------------------------------------------------------------------------------- 1 | const execSync = require('child_process').execSync; 2 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const helpers = require('../helpers'); 5 | 6 | const REPO_NAME_RE = /Push {2}URL: ((git@github\.com:)|(https:\/\/github\.com\/)).+\/(.+)\.git/; 7 | 8 | function getWebpackConfigModule(options) { 9 | if (options.githubDev) { 10 | return require('../advance/webpack.web.dev.js'); 11 | } else if (options.githubProd) { 12 | return require('../advance/webpack.web.prod.js'); 13 | } else { 14 | throw new Error('Invalid compile option.'); 15 | } 16 | } 17 | 18 | function getRepoName(remoteName) { 19 | remoteName = remoteName || 'origin'; 20 | 21 | var stdout = execSync('git remote show ' + remoteName), 22 | match = REPO_NAME_RE.exec(stdout); 23 | 24 | if (!match) { 25 | throw new Error('Could not find a repository on remote ' + remoteName); 26 | } else { 27 | return match[4]; 28 | } 29 | } 30 | 31 | function stripTrailing(str, char) { 32 | 33 | if (str[0] === char) { 34 | str = str.substr(1); 35 | } 36 | 37 | if (str.substr(-1) === char) { 38 | str = str.substr(0, str.length - 1); 39 | } 40 | 41 | return str; 42 | } 43 | 44 | /** 45 | * Given a string remove trailing slashes and adds 1 slash at the end of the string. 46 | * 47 | * Example: 48 | * safeUrl('/value/') 49 | * // 'value/' 50 | * 51 | * @param url 52 | * @returns {string} 53 | */ 54 | function safeUrl(url) { 55 | const stripped = stripTrailing(url || '', '/'); 56 | return stripped ? stripped + '/' : ''; 57 | } 58 | 59 | function replaceHtmlWebpackPlugin(plugins, ghRepoName) { 60 | for (var i=0; i tags for "apple-touch-icon" (AKA Web Clips). **/ 19 | { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon-57x57.png" }, 20 | { rel: "apple-touch-icon", sizes: "60x60", href: "/assets/icon-60x60.png" }, 21 | { rel: "apple-touch-icon", sizes: "72x72", href: "/assets/icon-72x72.png" }, 22 | { rel: "apple-touch-icon", sizes: "76x76", href: "/assets/icon-76x76.png" }, 23 | { rel: "apple-touch-icon", sizes: "114x114", href: "/assets/icon-57x57@2x.png" }, 24 | { rel: "apple-touch-icon", sizes: "120x120", href: "/assets/icon-120x120.png" }, 25 | { rel: "apple-touch-icon", sizes: "144x144", href: "/assets/icon-144x144.png" }, 26 | { rel: "apple-touch-icon", sizes: "152x152", href: "/assets/icon-76x76@2x.png" }, 27 | { rel: "apple-touch-icon", sizes: "180x180", href: "/assets/icon-180x180.png" }, 28 | 29 | /** tags for android web app icons **/ 30 | { rel: "icon", type: "image/png", sizes: "192x192", href: "/assets/icon-192x192.png" }, 31 | 32 | /** tags for favicons **/ 33 | { rel: "icon", type: "image/png", sizes: "32x32", href: "/assets/icon-32x32.png" }, 34 | { rel: "icon", type: "image/png", sizes: "96x96", href: "/assets/icon-96x96.png" }, 35 | { rel: "icon", type: "image/png", sizes: "16x16", href: "/assets/icon-16x16.png" }, 36 | 37 | /** tags for a Web App Manifest **/ 38 | { rel: "manifest", href: "/assets/manifest.json" } 39 | ], 40 | meta: [ 41 | { name: "msapplication-TileColor", content: "#00bcd4" }, 42 | { name: "msapplication-TileImage", content: "/assets/icon-144x144.png", "=content": true }, 43 | { name: "theme-color", content: "#00bcd4" } 44 | ] 45 | }; -------------------------------------------------------------------------------- /config/helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | var path = require('path'); 5 | 6 | const EVENT = process.env.npm_lifecycle_event || ''; 7 | 8 | // Helper functions 9 | var ROOT = path.resolve(__dirname, '..'); 10 | 11 | function hasProcessFlag(flag) { 12 | return process.argv.join('').indexOf(flag) > -1; 13 | } 14 | 15 | function hasNpmFlag(flag) { 16 | return EVENT.includes(flag); 17 | } 18 | 19 | function isWebpackDevServer() { 20 | return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1])); 21 | } 22 | 23 | var root = path.join.bind(path, ROOT); 24 | 25 | exports.hasProcessFlag = hasProcessFlag; 26 | exports.hasNpmFlag = hasNpmFlag; 27 | exports.isWebpackDevServer = isWebpackDevServer; 28 | exports.root = root; 29 | -------------------------------------------------------------------------------- /config/protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | require('ts-node/register'); 6 | var helpers = require('./helpers'); 7 | 8 | exports.config = { 9 | baseUrl: 'http://localhost:3000/', 10 | 11 | // use `npm run e2e` 12 | specs: [ 13 | helpers.root('src/**/**.e2e.ts'), 14 | helpers.root('src/**/*.e2e.ts') 15 | ], 16 | exclude: [], 17 | 18 | framework: 'jasmine2', 19 | 20 | allScriptsTimeout: 110000, 21 | 22 | jasmineNodeOpts: { 23 | showTiming: true, 24 | showColors: true, 25 | isVerbose: false, 26 | includeStackTrace: false, 27 | defaultTimeoutInterval: 400000 28 | }, 29 | directConnect: true, 30 | 31 | capabilities: { 32 | 'browserName': 'chrome', 33 | 'chromeOptions': { 34 | 'args': ['show-fps-counter=true'] 35 | } 36 | }, 37 | 38 | onPrepare: function() { 39 | browser.ignoreSynchronization = true; 40 | }, 41 | 42 | /** 43 | * Angular 2 configuration 44 | * 45 | * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching 46 | * `rootEl` 47 | */ 48 | useAllAngular2AppRoots: true 49 | }; -------------------------------------------------------------------------------- /config/resource-override.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonnyBGod/angular2-webpack-advance-starter/ef13163a84f468a8a1661034d429fe32581287da/config/resource-override.js -------------------------------------------------------------------------------- /config/spec-bundle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | /* 6 | * When testing with webpack and ES6, we have to do some extra 7 | * things to get testing to work right. Because we are gonna write tests 8 | * in ES6 too, 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 will compile and bundle them 12 | * all here! Crazy huh. So we need to do some setup 13 | */ 14 | Error.stackTraceLimit = Infinity; 15 | 16 | require('core-js/es6'); 17 | require('core-js/es7/reflect'); 18 | 19 | require('zone.js/dist/zone'); 20 | require('zone.js/dist/long-stack-trace-zone'); 21 | require('zone.js/dist/proxy'); // since zone.js 0.6.15 22 | require('zone.js/dist/sync-test'); 23 | require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14 24 | require('zone.js/dist/async-test'); 25 | require('zone.js/dist/fake-async-test'); 26 | 27 | // RxJS 28 | require('rxjs/Rx'); 29 | 30 | var testing = require('@angular/core/testing'); 31 | var browser = require('@angular/platform-browser-dynamic/testing'); 32 | 33 | testing.TestBed.initTestEnvironment( 34 | browser.BrowserDynamicTestingModule, 35 | browser.platformBrowserDynamicTesting() 36 | ); 37 | 38 | /* 39 | * Ok, this is kinda crazy. We can use the context method on 40 | * require that webpack created in order to tell webpack 41 | * what files we actually want to require or import. 42 | * Below, context will be a function/object with file names as keys. 43 | * Using that regex we are saying look in ../src then find 44 | * any file that ends with spec.ts and get its path. By passing in true 45 | * we say do this recursively 46 | */ 47 | var testContext = require.context('../src', true, /\.spec\.ts/); 48 | 49 | /* 50 | * get all the files, for each file, call the context function 51 | * that will require the file and load it up here. Context will 52 | * loop and require those spec files here 53 | */ 54 | function requireAll(requireContext) { 55 | return requireContext.keys().map(requireContext); 56 | } 57 | 58 | // requires and returns all modules that match 59 | var modules = requireAll(testContext); -------------------------------------------------------------------------------- /config/webpack.github-deploy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const helpers = require('./helpers'); 7 | const ghDeploy = require('./github-deploy'); 8 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs 9 | 10 | /** 11 | * Webpack Constants 12 | */ 13 | const GIT_REMOTE_NAME = 'origin'; 14 | const COMMIT_MESSAGE = 'Updates'; 15 | const GH_REPO_NAME = ghDeploy.getRepoName(GIT_REMOTE_NAME); 16 | 17 | module.exports = function (options) { 18 | const webpackConfigFactory = ghDeploy.getWebpackConfigModule(options); // the settings that are common to prod and dev 19 | const webpackConfig = webpackConfigFactory(options); 20 | 21 | // replace the instance of HtmlWebpackPlugin with an updated one. 22 | ghDeploy.replaceHtmlWebpackPlugin(webpackConfig.plugins, GH_REPO_NAME); 23 | 24 | return webpackMerge(webpackConfig, { 25 | output: { 26 | /** 27 | * The public path is set to the REPO name. 28 | * 29 | * `HtmlElementsPlugin` will add it to all resources url's created by it. 30 | * `HtmlWebpackPlugin` will add it to all webpack bundels/chunks. 31 | * 32 | * In theory publicPath shouldn't be used since the browser should automatically prefix the 33 | * `baseUrl` into all URLs, however this is not the case when the URL is absolute (start with /) 34 | * 35 | * It's important to prefix & suffix the repo name with a slash (/). 36 | * Prefixing so every resource will be absolute (otherwise it will be url.com/repoName/repoName... 37 | * Suffixing since chunks will not do it automatically (testes against about page) 38 | */ 39 | publicPath: '/' + GH_REPO_NAME + '/' + ghDeploy.safeUrl(webpackConfig.output.publicPath) 40 | }, 41 | 42 | plugins: [ 43 | function() { 44 | this.plugin('done', function(stats) { 45 | console.log('Starting deployment to GitHub.'); 46 | 47 | const logger = function (msg) { 48 | console.log(msg); 49 | }; 50 | 51 | const options = { 52 | logger: logger, 53 | remote: GIT_REMOTE_NAME, 54 | message: COMMIT_MESSAGE, 55 | dotfiles: true // for .nojekyll 56 | }; 57 | 58 | // Since GitHub moved to Jekyll 3.3, their server ignores the "node_modules" and "vendors" folder by default. 59 | // but, as of now, it also ignores "vendors*" files. 60 | // This means vendor.bundle.js or vendor.[chunk].bundle.js will return 404. 61 | // this is the fix for now. 62 | fs.writeFileSync(path.join(webpackConfig.output.path, '.nojekyll'), ''); 63 | 64 | const ghpages = require('gh-pages'); 65 | ghpages.publish(webpackConfig.output.path, options, function(err) { 66 | if (err) { 67 | console.log('GitHub deployment done. STATUS: ERROR.'); 68 | throw err; 69 | } else { 70 | console.log('GitHub deployment done. STATUS: SUCCESS.'); 71 | } 72 | }); 73 | }); 74 | } 75 | ] 76 | }); 77 | }; 78 | -------------------------------------------------------------------------------- /electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-webpack-advance-starter", 3 | "version": "1.0.0", 4 | "description": "An Angular 2 Webpack Advance Starter kit featuring Angular 2 (Router, Http, Forms, Services, Tests, E2E, Coverage), Karma, Protractor, Jasmine, Istanbul, TypeScript, and Webpack by AngularClass", 5 | "author": "João Ribeiro ", 6 | "homepage": "https://github.com/JonnyBGod/angular2-webpack-advance-starter", 7 | "license": "MIT", 8 | "main": "main.desktop.bundle.js" 9 | } 10 | -------------------------------------------------------------------------------- /electron/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "sourceMap": true, 9 | "noEmitHelpers": true, 10 | "lib": ["es6", "dom"], 11 | "strictNullChecks": false, 12 | }, 13 | "awesomeTypescriptLoaderOptions": { 14 | "forkChecker": true, 15 | "useWebpackText": true 16 | }, 17 | "compileOnSave": false, 18 | "buildOnSave": false, 19 | "atom": { "rewriteTsconfig": false } 20 | } 21 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "rewrites": [ 5 | { 6 | "source": "**", 7 | "destination": "/index.html" 8 | } 9 | ], 10 | "ignore": [ 11 | "firebase.json", 12 | "**/.*", 13 | "**/node_modules/**" 14 | ] 15 | } 16 | } -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | // Look in ./config for karma.conf.js 6 | module.exports = require('./config/karma.conf.js'); 7 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run build:prod" 3 | publish = "dist" 4 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | // look in ./config for protractor.conf.js 6 | exports.config = require('./config/advance/protractor.conf.js').config; 7 | -------------------------------------------------------------------------------- /src/app/app.advance.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Http } from '@angular/http'; 3 | 4 | // libs 5 | import { StoreModule } from '@ngrx/store'; 6 | import { EffectsModule } from '@ngrx/effects'; 7 | import { StoreDevtoolsModule } from '@ngrx/store-devtools'; 8 | import { ConfigModule, ConfigLoader, ConfigStaticLoader } from '@nglibs/config'; 9 | import { TranslateLoader } from '@ngx-translate/core'; 10 | import { Angulartics2Module, Angulartics2GoogleAnalytics } from 'angulartics2'; 11 | 12 | // feature modules 13 | import { CoreModule } from 'shared/core/core.module'; 14 | import { AppReducer } from 'shared/ngrx/index'; 15 | import { AnalyticsModule } from 'shared/analytics/analytics.module'; 16 | import { MultilingualModule, translateLoaderFactory } from 'shared/i18n/multilingual.module'; 17 | import { MultilingualEffects } from 'shared/i18n/index'; 18 | import { SampleModule } from 'shared/sample/sample.module'; 19 | import { NameListEffects } from 'shared/sample/index'; 20 | 21 | // config 22 | import { Config } from 'shared/core/index'; 23 | import { WindowService, ConsoleService } from 'shared/core/services/index'; 24 | Config.PLATFORM_TARGET = Config.PLATFORMS.WEB; 25 | 26 | import { routerModule } from 'routerModule'; 27 | 28 | import { AppConfig } from './app.config'; 29 | 30 | export function configFactory(): ConfigLoader { 31 | return new ConfigStaticLoader(AppConfig); 32 | } 33 | 34 | if (typeof TARGET_DESKTOP !== 'undefined' && TARGET_DESKTOP === true) { 35 | Config.PLATFORM_TARGET = Config.PLATFORMS.DESKTOP; 36 | } 37 | 38 | declare var window; 39 | declare var console; 40 | 41 | // For AoT compilation to work: 42 | export function win() { 43 | return window; 44 | } 45 | export function cons() { 46 | return console; 47 | } 48 | 49 | export const ADVANCE_MODULES = [ 50 | Angulartics2Module.forRoot([ Angulartics2GoogleAnalytics ]), 51 | ConfigModule.forRoot({ 52 | provide: ConfigLoader, 53 | useFactory: (configFactory) 54 | }), 55 | CoreModule.forRoot([ 56 | { provide: WindowService, useFactory: (win) }, 57 | { provide: ConsoleService, useFactory: (cons) } 58 | ]), 59 | routerModule, 60 | AnalyticsModule, 61 | MultilingualModule.forRoot([{ 62 | provide: TranslateLoader, 63 | deps: [Http], 64 | useFactory: (translateLoaderFactory) 65 | }]), 66 | SampleModule, 67 | StoreModule.provideStore(AppReducer), 68 | StoreDevtoolsModule.instrumentOnlyWithExtension(), 69 | EffectsModule.run(MultilingualEffects), 70 | EffectsModule.run(NameListEffects) 71 | ]; 72 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | const AppConfig: any = { 2 | i18n: { 3 | defaultLanguage: { 4 | code: 'en', 5 | title: 'English' 6 | }, 7 | availableLanguages: [ 8 | { 9 | code: 'en', 10 | title: 'English' 11 | }, 12 | { 13 | code: 'fr', 14 | title: 'French' 15 | }, 16 | { 17 | code: 'es', 18 | title: 'Spanish' 19 | }, 20 | { 21 | code: 'bg', 22 | title: 'Bulgarian' 23 | }, 24 | { 25 | code: 'ru', 26 | title: 'Russian' 27 | } 28 | ] 29 | }, 30 | logging: { 31 | DEBUG: { 32 | LEVEL_1: false, 33 | LEVEL_2: false, 34 | LEVEL_3: false, 35 | LEVEL_4: true 36 | } 37 | } 38 | }; 39 | 40 | export { AppConfig }; 41 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { FormsModule } from '@angular/forms'; 3 | import { HttpModule } from '@angular/http'; 4 | import { 5 | NgModule, 6 | ApplicationRef 7 | } from '@angular/core'; 8 | import { 9 | removeNgStyles, 10 | createNewHosts, 11 | createInputTransfer 12 | } from '@angularclass/hmr'; 13 | import { 14 | RouterModule, 15 | PreloadAllModules 16 | } from '@angular/router'; 17 | 18 | /* 19 | * Platform and Environment providers/directives/pipes 20 | */ 21 | import { ENV_PROVIDERS } from './environment'; 22 | import { ROUTES } from './app.routes'; 23 | // App is our top level component 24 | import { AppComponent } from './components/app.component'; 25 | import { APP_RESOLVER_PROVIDERS } from './app.resolver'; 26 | import { AppState, InternalStateType } from './app.service'; 27 | 28 | // Advance 29 | import { ADVANCE_MODULES } from './app.advance'; 30 | // App 31 | import { HomeModule } from 'components/home/home.module'; 32 | 33 | import '../styles/styles.scss'; 34 | import '../styles/headings.css'; 35 | 36 | // Application wide providers 37 | const APP_PROVIDERS = [ 38 | ...APP_RESOLVER_PROVIDERS, 39 | AppState 40 | ]; 41 | 42 | type StoreType = { 43 | state: InternalStateType, 44 | restoreInputValues: () => void, 45 | disposeOldHosts: () => void 46 | }; 47 | 48 | /** 49 | * `AppModule` is the main entry point into Angular2's bootstraping process 50 | */ 51 | @NgModule({ 52 | bootstrap: [ AppComponent ], 53 | declarations: [ 54 | AppComponent 55 | ], 56 | imports: [ // import Angular's modules 57 | BrowserModule, 58 | FormsModule, 59 | HttpModule, 60 | ...ADVANCE_MODULES, 61 | HomeModule 62 | ], 63 | providers: [ // expose our Services and Providers into Angular's dependency injection 64 | ENV_PROVIDERS, 65 | APP_PROVIDERS 66 | ] 67 | }) 68 | export class AppModule { 69 | 70 | constructor( 71 | public appRef: ApplicationRef, 72 | public appState: AppState 73 | ) {} 74 | 75 | public hmrOnInit(store: StoreType) { 76 | if (!store || !store.state) { 77 | return; 78 | } 79 | console.log('HMR store', JSON.stringify(store, null, 2)); 80 | // set state 81 | this.appState._state = store.state; 82 | // set input values 83 | if ('restoreInputValues' in store) { 84 | let restoreInputValues = store.restoreInputValues; 85 | setTimeout(restoreInputValues); 86 | } 87 | 88 | this.appRef.tick(); 89 | delete store.state; 90 | delete store.restoreInputValues; 91 | } 92 | 93 | public hmrOnDestroy(store: StoreType) { 94 | const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement); 95 | // save state 96 | const state = this.appState._state; 97 | store.state = state; 98 | // recreate root elements 99 | store.disposeOldHosts = createNewHosts(cmpLocation); 100 | // save input values 101 | store.restoreInputValues = createInputTransfer(); 102 | // remove styles 103 | removeNgStyles(); 104 | } 105 | 106 | public hmrAfterDestroy(store: StoreType) { 107 | // display new elements 108 | store.disposeOldHosts(); 109 | delete store.disposeOldHosts; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/app/app.resolver.ts: -------------------------------------------------------------------------------- 1 | import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs/Observable'; 4 | import 'rxjs/add/observable/of'; 5 | 6 | @Injectable() 7 | export class DataResolver implements Resolve { 8 | public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { 9 | return Observable.of({ 10 | res: 11 | /* tslint:disable */ 12 | `Angular 2 Seed Advanced is a starter project that implements best practices in coding, building and testing Angular 2 apps. 13 | Additionally it adds various enhancements and integrations for large global projects.` 14 | /* tslint:enable */ 15 | }); 16 | } 17 | } 18 | 19 | // an array of services to resolve routes with data 20 | export const APP_RESOLVER_PROVIDERS = [ 21 | DataResolver 22 | ]; 23 | -------------------------------------------------------------------------------- /src/app/app.routerModule.desktop.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { RouterModule, PreloadAllModules } from '@angular/router'; 3 | 4 | import { ROUTES } from './app.routes'; 5 | 6 | export let routerModule = RouterModule.forRoot(ROUTES, { 7 | useHash: true, 8 | preloadingStrategy: PreloadAllModules 9 | }); 10 | -------------------------------------------------------------------------------- /src/app/app.routerModule.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { RouterModule, PreloadAllModules } from '@angular/router'; 3 | 4 | import { ROUTES } from './app.routes'; 5 | 6 | export let routerModule = RouterModule.forRoot(ROUTES, { 7 | preloadingStrategy: PreloadAllModules 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Routes } from '@angular/router'; 3 | 4 | export const ROUTES: Routes = [ 5 | { path: '', redirectTo: 'home', pathMatch: 'full'}, 6 | { 7 | path: 'about', 8 | loadChildren: './components/about/about.module#AboutModule' 9 | } 10 | ]; 11 | -------------------------------------------------------------------------------- /src/app/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | export type InternalStateType = { 4 | [key: string]: any 5 | }; 6 | 7 | @Injectable() 8 | export class AppState { 9 | 10 | public _state: InternalStateType = { }; 11 | 12 | // already return a clone of the current state 13 | public get state() { 14 | return this._state = this._clone(this._state); 15 | } 16 | // never allow mutation 17 | public set state(value) { 18 | throw new Error('do not mutate the `.state` directly'); 19 | } 20 | 21 | public get(prop?: any) { 22 | // use our state getter for the clone 23 | const state = this.state; 24 | return state.hasOwnProperty(prop) ? state[prop] : state; 25 | } 26 | 27 | public set(prop: string, value: any) { 28 | // internally mutate our state 29 | return this._state[prop] = value; 30 | } 31 | 32 | private _clone(object: InternalStateType) { 33 | // simple object clone 34 | return JSON.parse(JSON.stringify( object )); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/app/components/about/about.component.e2e.ts: -------------------------------------------------------------------------------- 1 | import { t } from 'shared/test/index'; 2 | 3 | declare var browser: any; 4 | declare var element: any; 5 | declare var by: any; 6 | 7 | t.describe('About', () => { 8 | 9 | t.be(() => { 10 | browser.get('/about'); 11 | }); 12 | 13 | t.it('should have correct feature heading', () => { 14 | browser.wait(element(by.css('sd-about h2')).isPresent(), 20000); 15 | let el = element(by.css('sd-about h2')); 16 | t.e(el.getText()).toEqual('Features'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/app/components/about/about.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Angular 2 Seed Advanced is a starter project that implements best practices in 4 | coding, building and testing Angular 2 apps. Additionally it adds various enhancements 5 | and integrations for large global projects. 6 |

7 | 8 |

Features

9 |
    10 |
  • Ready to go, statically typed build system using Gulp for working with TypeScript.
  • 11 |
  • Production and development builds.
  • 12 |
  • Sample unit tests with Jasmine and Karma including code coverage via Istanbul.
  • 13 |
  • End-to-end tests with Protractor.
  • 14 |
  • Development server with live reload.
  • 15 |
  • TypeScript definition management using Typings.
  • 16 |
  • Basic Service Worker, which implements "Cache then network strategy".
  • 17 |
  • Integration with lodash.
  • 18 |
  • RxJS powered state management (Redux) via ngrx/store.
  • 19 |
  • i18n with ng2-translate.
  • 20 |
  • Native cross platform app development with NativeScript.
  • 21 |
22 |
-------------------------------------------------------------------------------- /src/app/components/about/about.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding: 0 16px; 4 | 5 | h2 { 6 | font-size: 20px; 7 | font-weight: 500; 8 | letter-spacing: 0.005em; 9 | margin-bottom: 0; 10 | margin-top: 0.83em; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/app/components/about/about.component.spec.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Component } from '@angular/core'; 3 | import { TestBed, async } from '@angular/core/testing'; 4 | 5 | // app 6 | import { t } from 'shared/test/index'; 7 | import { AboutComponent } from './about.component'; 8 | 9 | // test module configuration for each test 10 | const testModuleConfig = () => { 11 | TestBed.configureTestingModule({ 12 | declarations: [AboutComponent, TestComponent] 13 | }); 14 | }; 15 | 16 | export function main() { 17 | t.describe('@Component: AboutComponent', () => { 18 | 19 | t.be(testModuleConfig); 20 | 21 | t.it('should work', 22 | async(() => { 23 | TestBed.compileComponents() 24 | .then(() => { 25 | let fixture = TestBed.createComponent(TestComponent); 26 | fixture.detectChanges(); 27 | let aboutDOMEl = fixture.debugElement.children[0].nativeElement; 28 | 29 | t.e(aboutDOMEl.querySelectorAll('h2')[0].textContent).toEqual('Features'); 30 | }); 31 | })); 32 | }); 33 | } 34 | 35 | @Component({ 36 | selector: 'test-cmp', 37 | template: '' 38 | }) 39 | class TestComponent { } 40 | -------------------------------------------------------------------------------- /src/app/components/about/about.component.tns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/app/components/about/about.component.tns.scss: -------------------------------------------------------------------------------- 1 | .feature-list .body { 2 | font-size: 16; 3 | color: #555; 4 | margin: 0 0 5 0; 5 | } 6 | 7 | .h1 { 8 | color: #106cc8; 9 | font-size: 24; 10 | } 11 | 12 | .h4 { 13 | color: #999; 14 | font-size: 18; 15 | } -------------------------------------------------------------------------------- /src/app/components/about/about.component.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 3 | 4 | @Component({ 5 | selector: 'sd-about', 6 | templateUrl: 'about.component.html', 7 | styleUrls: ['about.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush 9 | }) 10 | export class AboutComponent { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/app/components/about/about.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { AboutComponent } from './about.component'; 4 | import { routing } from './about.routing'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | routing 9 | ], 10 | declarations: [ 11 | AboutComponent 12 | ] 13 | }) 14 | export class AboutModule { } 15 | -------------------------------------------------------------------------------- /src/app/components/about/about.routing.ts: -------------------------------------------------------------------------------- 1 | import { ModuleWithProviders } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { AboutComponent } from './about.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: AboutComponent 9 | } 10 | ]; 11 | 12 | export const routing: ModuleWithProviders = RouterModule.forChild(routes); 13 | -------------------------------------------------------------------------------- /src/app/components/about/index.ts: -------------------------------------------------------------------------------- 1 | export * from './about.module'; 2 | export * from './about.component'; 3 | export * from './about.routing'; 4 | -------------------------------------------------------------------------------- /src/app/components/app.component.e2e.ts: -------------------------------------------------------------------------------- 1 | import { t } from '../shared/test/index'; 2 | 3 | declare var browser: any; 4 | declare var element: any; 5 | declare var by: any; 6 | 7 | t.describe('App', () => { 8 | 9 | t.be(() => { 10 | browser.get('/'); 11 | }); 12 | 13 | t.it('should have a title', () => { 14 | t.e(browser.getTitle()).toEqual('Angular2 Webpack Advance Starter'); 15 | }); 16 | 17 | t.it('should have