├── .github ├── CONTRIBUTING.md └── ISSUE_TEMPLATE.md ├── .gitignore ├── .stylelintrc ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── gulpfile.ts ├── karma.conf.js ├── nativescript ├── .vscode │ └── launch.json ├── package.json ├── src │ ├── App_Resources │ │ ├── Android │ │ │ ├── AndroidManifest.xml │ │ │ ├── app.gradle │ │ │ ├── drawable-hdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-ldpi │ │ │ │ └── icon.png │ │ │ ├── drawable-mdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-nodpi │ │ │ │ └── splashscreen.9.png │ │ │ ├── drawable │ │ │ │ └── splash_logo.png │ │ │ └── values │ │ │ │ ├── material_colors.xml │ │ │ │ └── splash_settings.xml │ │ └── iOS │ │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon-29.png │ │ │ │ ├── icon-29@2x.png │ │ │ │ ├── icon-29@3x.png │ │ │ │ ├── icon-40.png │ │ │ │ ├── icon-40@2x.png │ │ │ │ ├── icon-40@3x.png │ │ │ │ ├── icon-50.png │ │ │ │ ├── icon-50@2x.png │ │ │ │ ├── icon-57.png │ │ │ │ ├── icon-57@2x.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 │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.launchimage │ │ │ │ ├── Contents.json │ │ │ │ ├── Default-568h@2x.png │ │ │ │ ├── Default-667h@2x.png │ │ │ │ ├── Default-736h@3x.png │ │ │ │ ├── Default-Landscape.png │ │ │ │ ├── Default-Landscape@2x.png │ │ │ │ ├── Default-Landscape@3x.png │ │ │ │ ├── Default-Portrait.png │ │ │ │ ├── Default-Portrait@2x.png │ │ │ │ ├── Default.png │ │ │ │ └── Default@2x.png │ │ │ ├── LaunchScreen.AspectFill.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchScreen-AspectFill.png │ │ │ │ └── LaunchScreen-AspectFill@2x.png │ │ │ └── LaunchScreen.Center.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchScreen-Center.png │ │ │ │ └── LaunchScreen-Center@2x.png │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ └── build.xcconfig │ ├── app.aot.ts │ ├── app.css │ ├── app.ts │ ├── components.module.ts │ ├── mobile │ │ └── core │ │ │ ├── index.ts │ │ │ ├── services │ │ │ ├── ns-app.service.ts │ │ │ └── window-native.service.ts │ │ │ └── utils │ │ │ └── actionbar.util.ts │ ├── native.module.ts │ ├── package.json │ ├── references.d.ts │ ├── tsconfig.json │ ├── vendor-platform.android.ts │ ├── vendor-platform.ios.ts │ └── vendor.ts ├── tools │ └── webpack │ │ └── tns-loader.js ├── tsconfig.aot.json ├── tsconfig.json ├── webpack.android.js ├── webpack.common.js ├── webpack.ios.js └── yarn.lock ├── package.json ├── src └── client │ ├── app │ └── shared │ │ ├── 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 │ │ ├── tokens.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 │ │ └── sample │ │ ├── components │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.tns.html │ │ │ ├── app.component.ts │ │ │ └── app.routes.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.tns.html │ │ │ ├── home.component.ts │ │ │ ├── home.css │ │ │ ├── home.routes.ts │ │ │ └── home.tns.css │ │ └── index.ts │ │ ├── index.ts │ │ ├── models │ │ └── sample.model.ts │ │ ├── routes.ts │ │ ├── sample.module.ts │ │ └── services │ │ ├── app-config.ts │ │ ├── index.ts │ │ └── sample.service.ts │ ├── assets │ ├── data.json │ ├── favicon │ │ ├── favicon-DEV.ico │ │ └── favicon-PROD.ico │ ├── logo.icns │ ├── logo.ico │ └── svg │ │ ├── more.svg │ │ └── smile.svg │ ├── index.html │ ├── main.desktop.ts │ ├── main.web.prod.ts │ ├── main.web.ts │ ├── package.json │ ├── system-config.ts │ ├── tokens.web.ts │ ├── tsconfig.json │ └── web.module.ts ├── tools ├── README.md ├── config.ts ├── config │ ├── banner-256.txt │ ├── banner.txt │ ├── project.config.ts │ ├── project.tasks.json │ ├── seed-advanced.config.ts │ ├── seed.config.interfaces.ts │ ├── seed.config.ts │ ├── seed.tasks.json │ └── seed.tslint.json ├── debug.ts ├── env │ ├── base.ts │ ├── dev.ts │ ├── env-config.interface.ts │ └── prod.ts ├── install.js ├── manual_typings │ ├── project │ │ └── sample.package.d.ts │ └── seed │ │ ├── autoprefixer.d.ts │ │ ├── cssnano.d.ts │ │ ├── express-history-api-fallback.d.ts │ │ ├── istream.d.ts │ │ ├── karma.d.ts │ │ ├── merge-stream.d.ts │ │ ├── open.d.ts │ │ ├── operators.d.ts │ │ ├── slash.d.ts │ │ ├── systemjs-builder.d.ts │ │ └── tildify.d.ts ├── tasks │ ├── assets_task.ts │ ├── css_task.ts │ ├── project │ │ ├── desktop.build.ts │ │ ├── desktop.libs.ts │ │ ├── desktop.package.linux.ts │ │ ├── desktop.package.mac.ts │ │ ├── desktop.package.windows.ts │ │ └── desktop.watch.ts │ ├── seed │ │ ├── build.assets.dev.ts │ │ ├── build.assets.prod.ts │ │ ├── build.assets.tns.ts │ │ ├── build.bundle.rxjs.ts │ │ ├── build.bundles.app.aot.ts │ │ ├── build.bundles.app.rollup.aot.ts │ │ ├── build.bundles.app.ts │ │ ├── build.bundles.ts │ │ ├── build.docs.ts │ │ ├── build.html_css.ts │ │ ├── build.index.dev.ts │ │ ├── build.index.prod.ts │ │ ├── build.js.dev.ts │ │ ├── build.js.e2e.ts │ │ ├── build.js.prod.aot.ts │ │ ├── build.js.prod.rollup.aot.ts │ │ ├── build.js.prod.ts │ │ ├── build.js.test.ts │ │ ├── build.js.tns.ts │ │ ├── build.tns_html_css.ts │ │ ├── build.tools.ts │ │ ├── check.tools.ts │ │ ├── check.versions.ts │ │ ├── clean.all.src.js.ts │ │ ├── clean.all.ts │ │ ├── clean.coverage.ts │ │ ├── clean.dev.ts │ │ ├── clean.e2e.ts │ │ ├── clean.prod.ts │ │ ├── clean.tns.ts │ │ ├── clean.tools.ts │ │ ├── clear.files.ts │ │ ├── compile.ahead.prod.ts │ │ ├── copy.prod.rollup.aot.ts │ │ ├── copy.prod.ts │ │ ├── e2e.ts │ │ ├── generate.manifest.ts │ │ ├── karma.run.ts │ │ ├── karma.run.with_coverage.ts │ │ ├── karma.watch.ts │ │ ├── minify.bundles.ts │ │ ├── noop.ts │ │ ├── print.banner.ts │ │ ├── serve.coverage.ts │ │ ├── serve.coverage.watch.ts │ │ ├── serve.docs.ts │ │ ├── server.prod.ts │ │ ├── server.start.ts │ │ ├── start.deving.ts │ │ ├── transpile.bundles.rollup.aot.ts │ │ ├── tslint.tns.ts │ │ ├── tslint.ts │ │ ├── watch.dev.ts │ │ ├── watch.e2e.ts │ │ ├── watch.test.ts │ │ ├── watch.tns.ts │ │ └── webdriver.ts │ ├── task.ts │ └── typescript_task.ts ├── utils.ts └── utils │ ├── project.utils.ts │ ├── project │ └── sample_util.ts │ ├── seed.utils.ts │ └── seed │ ├── clean.ts │ ├── code_change_tools.ts │ ├── karma.start.ts │ ├── server.ts │ ├── tasks_tools.ts │ ├── template_locals.ts │ ├── tsproject.ts │ └── watch.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Submitting Pull Requests 2 | 3 | **Please follow these basic steps to simplify pull request reviews - if you don't you'll probably just be asked to anyway.** 4 | 5 | * Please rebase your branch against the current master 6 | * Run ```npm install``` to make sure your development dependencies are up-to-date 7 | * Please ensure that the test suite passes **and** that code is lint free before submitting a PR by running: 8 | * ```npm test``` 9 | * If you've added new functionality, **please** include tests which validate its behaviour 10 | * Make reference to possible [issues](https://github.com/mgechev/angular2-seed/issues) on PR comment 11 | 12 | ## Submitting bug reports 13 | 14 | * Please detail the affected browser(s) and operating system(s) 15 | * Please be sure to state which version of node **and** npm you're using 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **IMPORTANT**: This repository's issues are reserved for feature requests and bug reports. Do not submit support requests here. 2 | 3 | 4 | **Steps to reproduce and a minimal demo of the problem** 5 | 6 | _What steps should we try in your demo to see the problem?_ 7 | 8 | **Current behavior** 9 | 10 | 11 | **Expected/desired behavior** 12 | 13 | 14 | **Other information** 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | 3 | node_modules/ 4 | 5 | npm-debug.log 6 | 7 | src/**/*.js 8 | src/**/*.js.map 9 | nativescript/app 10 | nativescript/hooks 11 | nativescript/node_modules 12 | nativescript/platforms 13 | nativescript/src/app 14 | nativescript/src/**/*.js 15 | nativescript/src/**/*.js.map 16 | nativescript/*.d.ts 17 | !nativescript/src/references.d.ts 18 | desktop 19 | gulpfile.js 20 | gulpfile.js.map 21 | 22 | typings/ -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "rules": { 4 | "block-no-empty": null, 5 | "at-rule-empty-line-before": null, 6 | "rule-non-nested-empty-line-before": null, 7 | "selector-pseudo-class-no-unknown" : [ true, { 8 | "ignorePseudoClasses": [ 9 | "host" 10 | ] 11 | }] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 5 4 | - 6 5 | 6 | sudo: false 7 | 8 | os: 9 | - linux 10 | - osx 11 | 12 | matrix: 13 | exclude: 14 | - os: osx 15 | node_js: 4 16 | - os: osx 17 | node_js: 5 18 | 19 | before_install: 20 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi 21 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew outdated xctool || brew upgrade xctool; fi 22 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CHROME_BIN=chromium-browser; fi # Karma CI 23 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew cask install google-chrome; fi # Karma CI 24 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export DISPLAY=:99.0; fi 25 | 26 | before_script: 27 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh -e /etc/init.d/xvfb start; fi 28 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then nohup bash -c "webdriver-manager start 2>&1 &"; fi # Protractor CI 29 | 30 | after_failure: 31 | - cat /home/travis/build/NathanWalker/angular2-seed-advanced/npm-debug.log 32 | 33 | branches: 34 | only: master 35 | 36 | notifications: 37 | email: true 38 | webhooks: 39 | on_success: change # options: [always|never|change] default: always 40 | on_failure: always # options: [always|never|change] default: always 41 | on_start: never # options: [always|never|change] default: always 42 | 43 | env: 44 | global: 45 | # https://github.com/DefinitelyTyped/tsd#tsdrc 46 | # Token has no scope (read-only access to public information) 47 | - TSD_GITHUB_TOKEN=51b0c1347cfd8c2c90ba0f60db7898171cbb17c8 48 | 49 | cache: 50 | directories: node_modules 51 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch localhost with sourcemaps", 6 | "type": "chrome", 7 | "request": "launch", 8 | "url": "http://localhost:5555/", 9 | "sourceMaps": true, 10 | "webRoot": "${workspaceRoot}/dist/dev", 11 | "runtimeArgs": [ 12 | "--remote-debugging-port=9222", //Open in port 9222 (standard chrome debug port) 13 | "--user-data-dir=${workspaceRoot}\\ChromeDebugger-UserData\\", //Can be any directory. Makes chrome load in a different directory so that it opens in a new instance. 14 | //"--user-data-dir=${env.LOCALAPPDATA}\\Google\\Chrome\\User Data\\", //CHROME DEFAULT 15 | "--new-window" //Open in new window 16 | ] 17 | }, 18 | { 19 | "name": "Launch Electron App", 20 | "type": "node", 21 | "program": "${workspaceRoot}/dist/dev/main.desktop.js", // important 22 | "stopOnEntry": false, 23 | "args": [], 24 | "cwd": "${workspaceRoot}/dist/dev/", 25 | // next line is very important 26 | "runtimeExecutable": "${env.APPDATA}/npm/node_modules/electron-prebuilt/dist/electron.exe", 27 | "runtimeArgs": [], 28 | "env": { }, 29 | "sourceMaps": true 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "**/nativescript/platforms": true, 5 | "src/client/**/*.js": true, 6 | "nativescript/app": true, 7 | "nativescript/src/**/*.js": true, 8 | "ChromeDebugger-UserData/**/*": true 9 | }, 10 | "search.exclude": { 11 | "**/coverage_js": true, 12 | "**/coverage": true, 13 | "**/dist": true, 14 | "**/nativescript/platforms": true, 15 | "src/client/**/*.js": true, 16 | "nativescript/app": true, 17 | "nativescript/src/**/*.js": true, 18 | "ChromeDebugger-UserData/**/*": true 19 | }, 20 | "typescript.tsdk": "node_modules/typescript/lib" 21 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "npm", 4 | "isShellCommand": true, 5 | "showOutput": "always", 6 | "args": ["run"], 7 | "echoCommand": true, 8 | "tasks": [ 9 | { 10 | "taskName": "reinstall", 11 | "isBuildCommand": false, 12 | "showOutput": "always", 13 | "isWatching": false, 14 | "isTestCommand": false 15 | }, 16 | { 17 | "taskName": "start", 18 | "isBuildCommand": true, 19 | "showOutput": "always", 20 | "isWatching": true, 21 | "isTestCommand": false 22 | }, 23 | { 24 | "taskName": "start.desktop", 25 | "isBuildCommand": false, 26 | "showOutput": "always", 27 | "isWatching": true, 28 | "isTestCommand": false 29 | }, 30 | { 31 | "taskName": "start.desktop.windows", 32 | "isBuildCommand": false, 33 | "showOutput": "always", 34 | "isWatching": true, 35 | "isTestCommand": false 36 | }, 37 | { 38 | "taskName": "start.livesync.desktop", 39 | "isBuildCommand": false, 40 | "showOutput": "always", 41 | "isWatching": true, 42 | "isTestCommand": false 43 | }, 44 | { 45 | "taskName": "start.livesync.desktop.windows", 46 | "isBuildCommand": false, 47 | "showOutput": "always", 48 | "isWatching": true, 49 | "isTestCommand": false 50 | }, 51 | { 52 | "taskName": "start.ios", 53 | "isBuildCommand": false, 54 | "showOutput": "always", 55 | "isWatching": true, 56 | "isTestCommand": false 57 | }, 58 | { 59 | "taskName": "start.livesync.ios", 60 | "isBuildCommand": false, 61 | "showOutput": "always", 62 | "isWatching": true, 63 | "isTestCommand": false 64 | }, 65 | { 66 | "taskName": "start.livesync.ios.device", 67 | "isBuildCommand": false, 68 | "showOutput": "always", 69 | "isWatching": true, 70 | "isTestCommand": false 71 | }, 72 | { 73 | "taskName": "start.android", 74 | "isBuildCommand": false, 75 | "showOutput": "always", 76 | "isWatching": true, 77 | "isTestCommand": false 78 | }, 79 | { 80 | "taskName": "start.livesync.android", 81 | "isBuildCommand": false, 82 | "showOutput": "always", 83 | "isWatching": true, 84 | "isTestCommand": false 85 | }, 86 | { 87 | "taskName": "start.livesync.android.device", 88 | "isBuildCommand": false, 89 | "showOutput": "always", 90 | "isWatching": true, 91 | "isTestCommand": false 92 | }, 93 | { 94 | "taskName": "test", 95 | "isBuildCommand": false, 96 | "showOutput": "always", 97 | "isWatching": true, 98 | "isTestCommand": true 99 | } 100 | ] 101 | } 102 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Submitting Pull Requests 2 | 3 | **Please follow these basic steps to simplify pull request reviews - if you don't you'll probably just be asked to anyway.** 4 | 5 | * Please rebase your branch against the current master 6 | * Run ```npm install``` to make sure your development dependencies are up-to-date 7 | * Please ensure that the test suite passes **and** that code is lint free before submitting a PR by running: 8 | * ```npm test``` 9 | * If you've added new functionality, **please** include tests which validate its behaviour 10 | * Make reference to possible [issues](https://github.com/NathanWalker/angular-seed-advanced/issues) on PR comment 11 | 12 | ## Submitting bug reports 13 | 14 | * Please detail the affected browser(s) and operating system(s) 15 | * Please be sure to state which version of node **and** npm you're using 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Minko Gechev 4 | Copyright (c) 2016 Nathan Walker 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Multi-Platform Starter 2 | 3 | ## This project is no longer maintained. Please visit https://github.com/TeamMaestro/angular-native-seed for a different way to build for NativeScript, the web, and Electron in the future. 4 | 5 | The Angular Multi-Platform Starter is a cloneable template for building apps for the web, for native mobile with [NativeScript](https://www.nativescript.org/), and for desktop with [Electron](http://electron.atom.io/). The template contains a series of npm scripts for running your apps in these environments, as well as a set of conventions for sharing and forking your code for each ecosystem—web, native mobile, and desktop. It is a basic version of Nathan Walker's [Advanced Angular Seed](https://github.com/NathanWalker/angular-seed-advanced). 6 | 7 | Visit our [**documentation hub**](https://jlooper.github.io/angular-starter/) for detailed information on this starter. 8 | 9 | ![](http://i.imgur.com/FWnAygt.png) 10 | -------------------------------------------------------------------------------- /gulpfile.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as util from 'gulp-util'; 3 | import * as runSequence from 'run-sequence'; 4 | 5 | import Config from './tools/config'; 6 | import { loadTasks, loadCompositeTasks } from './tools/utils'; 7 | 8 | 9 | loadTasks(Config.SEED_TASKS_DIR); 10 | loadTasks(Config.PROJECT_TASKS_DIR); 11 | 12 | loadCompositeTasks(Config.SEED_COMPOSITE_TASKS, Config.PROJECT_COMPOSITE_TASKS); 13 | 14 | 15 | // -------------- 16 | // Clean dev/coverage that will only run once 17 | // this prevents karma watchers from being broken when directories are deleted 18 | let firstRun = true; 19 | gulp.task('clean.once', (done: any) => { 20 | if (firstRun) { 21 | firstRun = false; 22 | runSequence('check.tools', 'clean.dev', 'clean.coverage', done); 23 | } else { 24 | util.log('Skipping clean on rebuild'); 25 | done(); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /nativescript/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch on iOS Device", 6 | "type": "nativescript", 7 | "platform": "ios", 8 | "request": "launch", 9 | "appRoot": "${workspaceRoot}", 10 | "sourceMaps": true, 11 | "diagnosticLogging": false, 12 | "emulator": false 13 | }, 14 | { 15 | "name": "Attach on iOS Device", 16 | "type": "nativescript", 17 | "platform": "ios", 18 | "request": "attach", 19 | "appRoot": "${workspaceRoot}", 20 | "sourceMaps": true, 21 | "diagnosticLogging": false, 22 | "emulator": false 23 | }, 24 | { 25 | "name": "Launch on iOS Emulator", 26 | "type": "nativescript", 27 | "platform": "ios", 28 | "request": "launch", 29 | "appRoot": "${workspaceRoot}", 30 | "sourceMaps": true, 31 | "diagnosticLogging": false, 32 | "emulator": true 33 | }, 34 | { 35 | "name": "Attach on iOS Emulator", 36 | "type": "nativescript", 37 | "platform": "ios", 38 | "request": "attach", 39 | "appRoot": "${workspaceRoot}", 40 | "sourceMaps": true, 41 | "diagnosticLogging": false, 42 | "emulator": true 43 | }, 44 | { 45 | "name": "Launch on Android Device", 46 | "type": "nativescript", 47 | "platform": "android", 48 | "request": "launch", 49 | "appRoot": "${workspaceRoot}", 50 | "sourceMaps": true, 51 | "diagnosticLogging": false, 52 | "emulator": false 53 | }, 54 | { 55 | "name": "Launch on Android Emulator", 56 | "type": "nativescript", 57 | "platform": "android", 58 | "request": "launch", 59 | "appRoot": "${workspaceRoot}", 60 | "sourceMaps": true, 61 | "diagnosticLogging": false, 62 | "emulator": true 63 | }, 64 | { 65 | "name": "Attach on Android Device", 66 | "type": "nativescript", 67 | "platform": "android", 68 | "request": "attach", 69 | "appRoot": "${workspaceRoot}", 70 | "sourceMaps": false, 71 | "diagnosticLogging": false, 72 | "emulator": false 73 | }, 74 | { 75 | "name": "Attach on Android Emulator", 76 | "type": "nativescript", 77 | "platform": "android", 78 | "request": "attach", 79 | "appRoot": "${workspaceRoot}", 80 | "sourceMaps": false, 81 | "diagnosticLogging": false, 82 | "emulator": true 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /nativescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed-advanced", 3 | "main": "app.js", 4 | "version": "0.0.0", 5 | "nativescript": { 6 | "id": "com.yourdomain.nativescript", 7 | "tns-ios": { 8 | "version": "2.5.0" 9 | }, 10 | "tns-android": { 11 | "version": "2.5.0" 12 | } 13 | }, 14 | "scripts": { 15 | "preinstall": "mkdirp app", 16 | "clean": "rimraf platforms node_modules lib hooks app && mkdirp app", 17 | "ns-bundle": "ns-bundle", 18 | "start-android-bundle": "npm run ns-bundle --android --start-app", 19 | "start-ios-bundle": "npm run ns-bundle --ios --start-app", 20 | "build-android-bundle": "npm run ns-bundle --android --build-app", 21 | "build-ios-bundle": "npm run ns-bundle --ios --build-app" 22 | }, 23 | "dependencies": { 24 | "@angular/animations": "~4.0.0", 25 | "@angular/common": "~4.0.0", 26 | "@angular/compiler": "~4.0.0", 27 | "@angular/core": "~4.0.0", 28 | "@angular/forms": "~4.0.0", 29 | "@angular/http": "~4.0.0", 30 | "@angular/platform-browser": "~4.0.0", 31 | "@angular/platform-browser-dynamic": "~4.0.0", 32 | "@angular/router": "~4.0.0", 33 | "lodash": "^4.17.4", 34 | "nativescript-angular": "1.5.0", 35 | "nativescript-dev-webpack": "^0.3.1", 36 | "nativescript-theme-core": "^1.0.3", 37 | "reflect-metadata": "^0.1.8", 38 | "rxjs": "~5.2.0", 39 | "tns-core-modules": "~2.5.2", 40 | "url": "0.10.3", 41 | "zone.js": "~0.8.2" 42 | }, 43 | "devDependencies": { 44 | "@angular/compiler-cli": "~4.0.0", 45 | "@ngtools/webpack": "~1.3.0", 46 | "@types/jasmine": "^2.5.35", 47 | "babel-traverse": "6.20.0", 48 | "babel-types": "6.20.0", 49 | "babylon": "6.14.1", 50 | "copy-webpack-plugin": "~4.0.1", 51 | "extract-text-webpack-plugin": "~2.1.0", 52 | "fs-extra": "^1.0.0", 53 | "htmlparser2": "^3.9.2", 54 | "lazy": "1.0.11", 55 | "nativescript-css-loader": "~0.26.1", 56 | "nativescript-dev-android-snapshot": "^0.*.*", 57 | "nativescript-dev-webpack": "^0.3.6", 58 | "raw-loader": "~0.5.1", 59 | "resolve-url-loader": "~2.0.2", 60 | "typescript": "~2.1.4", 61 | "webpack": "2.3.2", 62 | "webpack-sources": "~0.2.3" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/app.gradle: -------------------------------------------------------------------------------- 1 | // Add your native dependencies here: 2 | 3 | // Uncomment to add recyclerview-v7 dependency 4 | //dependencies { 5 | // compile 'com.android.support:recyclerview-v7:+' 6 | //} 7 | 8 | android { 9 | defaultConfig { 10 | generatedDensities = [] 11 | applicationId = "__PACKAGE__" 12 | } 13 | aaptOptions { 14 | additionalParameters "--no-version-vectors" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/Android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/Android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/Android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/drawable-nodpi/splashscreen.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/Android/drawable-nodpi/splashscreen.9.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/drawable/splash_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/Android/drawable/splash_logo.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/Android/values/splash_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NativeScript Splash 4 | 5 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "icon-29.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "icon-29@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon-29@3x.png", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "icon-40@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon-40@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "57x57", 35 | "idiom" : "iphone", 36 | "filename" : "icon-57.png", 37 | "scale" : "1x" 38 | }, 39 | { 40 | "size" : "57x57", 41 | "idiom" : "iphone", 42 | "filename" : "icon-57@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon-60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "icon-60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "29x29", 59 | "idiom" : "ipad", 60 | "filename" : "icon-29.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "icon-29@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "40x40", 71 | "idiom" : "ipad", 72 | "filename" : "icon-40.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "icon-40@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "50x50", 83 | "idiom" : "ipad", 84 | "filename" : "icon-50.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "50x50", 89 | "idiom" : "ipad", 90 | "filename" : "icon-50@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "72x72", 95 | "idiom" : "ipad", 96 | "filename" : "icon-72.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "72x72", 101 | "idiom" : "ipad", 102 | "filename" : "icon-72@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "icon-76.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "icon-76@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "83.5x83.5", 119 | "idiom" : "ipad", 120 | "filename" : "icon-83.5@2x.png", 121 | "scale" : "2x" 122 | } 123 | ], 124 | "info" : { 125 | "version" : 1, 126 | "author" : "xcode" 127 | } 128 | } -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "Default-736h@3x.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "736h", 16 | "filename" : "Default-Landscape@3x.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "landscape", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "extent" : "full-screen", 23 | "idiom" : "iphone", 24 | "subtype" : "667h", 25 | "filename" : "Default-667h@2x.png", 26 | "minimum-system-version" : "8.0", 27 | "orientation" : "portrait", 28 | "scale" : "2x" 29 | }, 30 | { 31 | "orientation" : "portrait", 32 | "idiom" : "iphone", 33 | "filename" : "Default@2x.png", 34 | "extent" : "full-screen", 35 | "minimum-system-version" : "7.0", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "extent" : "full-screen", 40 | "idiom" : "iphone", 41 | "subtype" : "retina4", 42 | "filename" : "Default-568h@2x.png", 43 | "minimum-system-version" : "7.0", 44 | "orientation" : "portrait", 45 | "scale" : "2x" 46 | }, 47 | { 48 | "orientation" : "portrait", 49 | "idiom" : "ipad", 50 | "filename" : "Default-Portrait.png", 51 | "extent" : "full-screen", 52 | "minimum-system-version" : "7.0", 53 | "scale" : "1x" 54 | }, 55 | { 56 | "orientation" : "landscape", 57 | "idiom" : "ipad", 58 | "filename" : "Default-Landscape.png", 59 | "extent" : "full-screen", 60 | "minimum-system-version" : "7.0", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "orientation" : "portrait", 65 | "idiom" : "ipad", 66 | "filename" : "Default-Portrait@2x.png", 67 | "extent" : "full-screen", 68 | "minimum-system-version" : "7.0", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "orientation" : "landscape", 73 | "idiom" : "ipad", 74 | "filename" : "Default-Landscape@2x.png", 75 | "extent" : "full-screen", 76 | "minimum-system-version" : "7.0", 77 | "scale" : "2x" 78 | }, 79 | { 80 | "orientation" : "portrait", 81 | "idiom" : "iphone", 82 | "filename" : "Default.png", 83 | "extent" : "full-screen", 84 | "scale" : "1x" 85 | }, 86 | { 87 | "orientation" : "portrait", 88 | "idiom" : "iphone", 89 | "filename" : "Default@2x.png", 90 | "extent" : "full-screen", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "orientation" : "portrait", 95 | "idiom" : "iphone", 96 | "filename" : "Default-568h@2x.png", 97 | "extent" : "full-screen", 98 | "subtype" : "retina4", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "orientation" : "portrait", 103 | "idiom" : "ipad", 104 | "extent" : "to-status-bar", 105 | "scale" : "1x" 106 | }, 107 | { 108 | "orientation" : "portrait", 109 | "idiom" : "ipad", 110 | "filename" : "Default-Portrait.png", 111 | "extent" : "full-screen", 112 | "scale" : "1x" 113 | }, 114 | { 115 | "orientation" : "landscape", 116 | "idiom" : "ipad", 117 | "extent" : "to-status-bar", 118 | "scale" : "1x" 119 | }, 120 | { 121 | "orientation" : "landscape", 122 | "idiom" : "ipad", 123 | "filename" : "Default-Landscape.png", 124 | "extent" : "full-screen", 125 | "scale" : "1x" 126 | }, 127 | { 128 | "orientation" : "portrait", 129 | "idiom" : "ipad", 130 | "extent" : "to-status-bar", 131 | "scale" : "2x" 132 | }, 133 | { 134 | "orientation" : "portrait", 135 | "idiom" : "ipad", 136 | "filename" : "Default-Portrait@2x.png", 137 | "extent" : "full-screen", 138 | "scale" : "2x" 139 | }, 140 | { 141 | "orientation" : "landscape", 142 | "idiom" : "ipad", 143 | "extent" : "to-status-bar", 144 | "scale" : "2x" 145 | }, 146 | { 147 | "orientation" : "landscape", 148 | "idiom" : "ipad", 149 | "filename" : "Default-Landscape@2x.png", 150 | "extent" : "full-screen", 151 | "scale" : "2x" 152 | } 153 | ], 154 | "info" : { 155 | "version" : 1, 156 | "author" : "xcode" 157 | } 158 | } -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchScreen-AspectFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchScreen-AspectFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchScreen-Center.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchScreen-Center@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiresFullScreen 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | NSAppTransportSecurity 47 | 48 | 49 | NSAllowsArbitraryLoads 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /nativescript/src/App_Resources/iOS/build.xcconfig: -------------------------------------------------------------------------------- 1 | // You can add custom settings here 2 | // for example you can uncomment the following line to force distribution code signing 3 | // CODE_SIGN_IDENTITY = iPhone Distribution 4 | // To build for device with Xcode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html 5 | // DEVELOPMENT_TEAM = YOUR_TEAM_ID; 6 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 7 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 8 | -------------------------------------------------------------------------------- /nativescript/src/app.aot.ts: -------------------------------------------------------------------------------- 1 | // this import should be first in order to load some required settings (like globals and reflect-metadata) 2 | import { platformNativeScript } from 'nativescript-angular/platform-static'; 3 | 4 | import { NativeModuleNgFactory } from './native.module.ngfactory'; 5 | import { enableProdMode } from '@angular/core'; 6 | 7 | enableProdMode(); 8 | 9 | platformNativeScript().bootstrapModuleFactory(NativeModuleNgFactory); 10 | -------------------------------------------------------------------------------- /nativescript/src/app.css: -------------------------------------------------------------------------------- 1 | @import 'nativescript-theme-core/css/core.light.css'; 2 | 3 | .link { 4 | border-width: 0; 5 | background-color: transparent; 6 | } 7 | .odd { 8 | background-color: #efefef; 9 | } 10 | .even { 11 | background-color: #fff; 12 | } -------------------------------------------------------------------------------- /nativescript/src/app.ts: -------------------------------------------------------------------------------- 1 | // nativescript 2 | import { platformNativeScriptDynamic } from 'nativescript-angular'; 3 | 4 | // app 5 | import { NativeModule } from './native.module'; 6 | 7 | platformNativeScriptDynamic().bootstrapModule(NativeModule); 8 | -------------------------------------------------------------------------------- /nativescript/src/components.module.ts: -------------------------------------------------------------------------------- 1 | // nativescript 2 | import { NativeScriptModule } from 'nativescript-angular/nativescript.module'; 3 | import { NativeScriptFormsModule } from 'nativescript-angular/forms'; 4 | import { NativeScriptHttpModule } from 'nativescript-angular/http'; 5 | import { NativeScriptRouterModule } from 'nativescript-angular/router'; 6 | import { Http } from '@angular/http'; 7 | 8 | // angular 9 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; 10 | 11 | // app 12 | import { AppComponent } from './app/shared/sample/components/app/app.component'; 13 | import { HomeComponent } from './app/shared/sample/components/home/home.component'; 14 | import { routes } from './app/shared/sample/components/app/app.routes'; 15 | 16 | // feature modules 17 | import { CoreModule } from './app/shared/core/core.module'; 18 | import { SampleModule } from './app/shared/sample/sample.module'; 19 | 20 | // intermediate component module 21 | // helps encapsulate custom native modules in with the components 22 | // note: couple ways this could be done, just one option presented here... 23 | @NgModule({ 24 | imports: [ 25 | NativeScriptModule, 26 | NativeScriptFormsModule, 27 | NativeScriptHttpModule, 28 | NativeScriptRouterModule, 29 | CoreModule, 30 | SampleModule 31 | ], 32 | declarations: [ 33 | AppComponent, 34 | HomeComponent 35 | ], 36 | schemas: [ 37 | NO_ERRORS_SCHEMA, 38 | CUSTOM_ELEMENTS_SCHEMA 39 | ], 40 | exports: [ 41 | NativeScriptModule, 42 | NativeScriptFormsModule, 43 | NativeScriptHttpModule, 44 | NativeScriptRouterModule, 45 | AppComponent, 46 | CoreModule, 47 | SampleModule 48 | ] 49 | }) 50 | export class ComponentsModule { } 51 | 52 | // For AoT compilation to work: 53 | export function cons() { 54 | return console; 55 | } 56 | -------------------------------------------------------------------------------- /nativescript/src/mobile/core/index.ts: -------------------------------------------------------------------------------- 1 | // services 2 | export * from './services/window-native.service'; 3 | export * from './services/ns-app.service'; 4 | 5 | // utils 6 | export * from './utils/actionbar.util'; 7 | -------------------------------------------------------------------------------- /nativescript/src/mobile/core/services/ns-app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { NSLocationStrategy } from 'nativescript-angular/router/ns-location-strategy'; 4 | 5 | // nativescript 6 | import * as nsApp from 'application'; 7 | import { isAndroid, isIOS } from 'platform'; 8 | 9 | if (isIOS) { 10 | /* 11 | nsApp.ios.delegate = require('../PATH/TO/DELEGATE').CustomAppDelegate; 12 | */ 13 | } 14 | 15 | // app 16 | import { AppService } from '../../../app/shared/core/services/app.service'; 17 | import { Config } from '../../../app/shared/core/utils'; 18 | import { LogService, WindowService, RouterExtensions } from '../../../app/shared/core/index'; 19 | import { ActionBarUtil } from '../utils/actionbar.util'; 20 | 21 | declare var android: any; 22 | 23 | @Injectable() 24 | export class NSAppService extends AppService { 25 | nsApp = nsApp; 26 | 27 | // Remember to update iOS and android constructors if you change dependencies 28 | // @Inject decorator is used on injectables here since this component merely extends AppComponent 29 | // Since @Component decorator is not used here, this ensures metadata will be generated 30 | constructor(public log: LogService, 31 | public router: Router, 32 | public locationstrategy: NSLocationStrategy, 33 | public window: WindowService 34 | ) { 35 | super(log); 36 | 37 | this.log.debug('NSAppService constructor'); 38 | 39 | /** 40 | * Top status bar on iOS and/or Android 41 | * iOs {number} 42 | * 0: default 43 | * 1: light 44 | * Android {string} 45 | * hex value 46 | */ 47 | ActionBarUtil.STATUSBAR_STYLE( 48 | isIOS ? 1 : '#3280CF' 49 | ); 50 | 51 | if (String('<%= BUILD_TYPE %>') !== 'prod') { 52 | log.debug('NSAppCmp ----'); 53 | 54 | router.events.subscribe((e) => { 55 | this.log.debug(`Router Event: ${e.toString()}`); 56 | }); 57 | } 58 | 59 | // Fix: Reset all nsApp events before subscribing to avoid Duplicate events. 60 | // this.unsubscribeAll(); 61 | 62 | nsApp.on(nsApp.launchEvent, (eventData: nsApp.LaunchEventData) => { 63 | this.log.info('TNS Application - Launched!'); 64 | }); 65 | 66 | nsApp.on(nsApp.suspendEvent, (eventData: nsApp.ApplicationEventData) => { 67 | this.log.info('TNS Application - Suspended'); 68 | }); 69 | 70 | nsApp.on(nsApp.resumeEvent, (eventData: nsApp.ApplicationEventData) => { 71 | this.log.info('TNS Application - Resumed'); 72 | }); 73 | 74 | nsApp.on(nsApp.lowMemoryEvent, (eventData: nsApp.ApplicationEventData) => { 75 | this.log.warn('TNS Application - !!! LOW MEMORY !!!'); 76 | }); 77 | 78 | nsApp.on(nsApp.exitEvent, (eventData: any) => { 79 | this.log.info('TNS Application - EXIT'); 80 | this.unsubscribeAll(); 81 | }); 82 | 83 | this.setupAndroid(); 84 | this.setupIOS(); 85 | } 86 | 87 | protected handleUncaughtError(err: any, platform: 'android' | 'ios') { 88 | this.log.info(`TNS Application - Uncaught Error: ${err.message}`); 89 | 90 | const errorDescription: any = { 91 | message: err.message, 92 | android: platform === 'android', 93 | ios: platform === 'ios', 94 | stackTrace: err.stackTrace, 95 | nativeException: err.nativeException, 96 | }; 97 | 98 | for (const key of Object.keys(errorDescription)) { 99 | if (errorDescription[key]) { 100 | console.log(`**** START - errorDescription.${key} - ****\n\n\n${errorDescription[key]}\n\n\n*** END - ${key} - ****`); 101 | } 102 | } 103 | } 104 | 105 | private unsubscribeAll() { 106 | nsApp.off(nsApp.launchEvent); 107 | nsApp.off(nsApp.suspendEvent); 108 | nsApp.off(nsApp.resumeEvent); 109 | nsApp.off(nsApp.lowMemoryEvent); 110 | nsApp.off(nsApp.exitEvent); 111 | nsApp.off(nsApp.uncaughtErrorEvent); 112 | } 113 | 114 | private setupAndroid() { 115 | if (!isAndroid) { 116 | return; 117 | } 118 | 119 | // Android specific code goes here 120 | 121 | this.nsApp.android.on(this.nsApp.AndroidApplication.activityBackPressedEvent, (args) => { 122 | const states = this.locationstrategy._getStates(); 123 | this.log.info(`Event: ${args.eventName}\nActivity: ${args.activity}\nstates: ${JSON.stringify(states)}`); 124 | }); 125 | 126 | this.nsApp.android.on(this.nsApp.AndroidApplication.activityResumedEvent, (args) => { 127 | if (args.activity.getIntent().getAction() === android.content.Intent.ACTION_VIEW) { 128 | const intentData = args.activity.getIntent().getData(); 129 | console.log(`Android received VIEW intent, with data: ${intentData}`); 130 | } 131 | }); 132 | 133 | this.nsApp.on(this.nsApp.uncaughtErrorEvent, (err) => { 134 | this.handleUncaughtError(err.android, 'android'); 135 | }); 136 | } 137 | 138 | private setupIOS() { 139 | if (!isIOS) { 140 | return; 141 | } 142 | 143 | this.nsApp.on(this.nsApp.uncaughtErrorEvent, (err) => { 144 | this.handleUncaughtError(err.ios, 'ios'); 145 | }); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /nativescript/src/mobile/core/services/window-native.service.ts: -------------------------------------------------------------------------------- 1 | // nativescript 2 | import * as dialogs from 'ui/dialogs'; 3 | import { device } from 'platform'; 4 | 5 | // app 6 | import { IWindow } from '../../../app/shared/core/interfaces/iwindow'; 7 | 8 | export class WindowNative implements IWindow { 9 | public get navigator(): any { 10 | return { 11 | language: device.language, 12 | userAgent: 'nativescript' 13 | }; 14 | } 15 | public get location(): any { 16 | return { 17 | host: 'nativescript' 18 | }; 19 | } 20 | public alert(msg: string): Promise { 21 | return dialogs.alert(msg); 22 | } 23 | public confirm(msg: string): Promise { 24 | return dialogs.confirm(msg); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /nativescript/src/mobile/core/utils/actionbar.util.ts: -------------------------------------------------------------------------------- 1 | import { topmost } from 'ui/frame'; 2 | import { ActionItem, ActionItems } from 'ui/action-bar'; 3 | import * as app from 'application'; 4 | import { device, isAndroid } from 'platform'; 5 | import { Color } from 'color'; 6 | declare var android; 7 | 8 | declare var UIBarStyle: any; 9 | 10 | export class ActionBarUtil { 11 | public static SET_TITLE(title: string) { 12 | var actionBar = topmost().currentPage.actionBar; 13 | actionBar.title = title; 14 | } 15 | public static ADD_BUTTON(button: ActionItem) { 16 | // NOTE: This MUST be called BEFORE SET_TITLE on start 17 | topmost().currentPage.actionBar.actionItems.addItem(button); 18 | } 19 | public static HIDE_BACK_BUTTON() { 20 | if (topmost().ios) { 21 | topmost().ios.controller.visibleViewController.navigationItem.setHidesBackButtonAnimated(true, false); 22 | } 23 | } 24 | public static EMPTY_ITEMS() { 25 | var actionBar = topmost().currentPage.actionBar; 26 | var actionItems = actionBar.actionItems.getItems(); 27 | actionItems.forEach((item) => { 28 | actionBar.actionItems.removeItem(item); 29 | }); 30 | } 31 | public static STATUSBAR_STYLE(style: number | string) { 32 | if (topmost().ios) { 33 | let navigationBar = topmost().ios.controller.navigationBar; 34 | // 0: default 35 | // 1: light 36 | navigationBar.barStyle = style; 37 | } else if (isAndroid) { 38 | if (app.android && device.sdkVersion >= '21') { 39 | try { 40 | let LayoutParams = android.view.WindowManager.LayoutParams; 41 | let win: any; 42 | if (app.android.foregroundActivity) { 43 | win = app.android.foregroundActivity.getWindow(); 44 | } else { 45 | win = app.android.startActivity.getWindow(); 46 | } 47 | 48 | win.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 49 | win.setStatusBarColor(new Color(style || '#3280CF').android); 50 | } catch (err) { 51 | console.log(err); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /nativescript/src/native.module.ts: -------------------------------------------------------------------------------- 1 | // nativescript 2 | import { 3 | NativeScriptRouterModule, 4 | RouterExtensions as TNSRouterExtensions 5 | } from 'nativescript-angular/router'; 6 | 7 | // angular 8 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; 9 | 10 | // app 11 | import { 12 | WindowService, 13 | ConsoleService, 14 | RouterExtensions, 15 | AppService 16 | } from './app/shared/core/index'; 17 | import { AppComponent } from './app/shared/sample/components/app/app.component'; 18 | import { routes } from './app/shared/sample/components/app/app.routes'; 19 | 20 | // feature modules 21 | import { CoreModule } from './app/shared/core/core.module'; 22 | import { ComponentsModule, cons } from './components.module'; 23 | 24 | // {N} custom app specific 25 | import { WindowNative, NSAppService } from './mobile/core/index'; 26 | 27 | /** 28 | * Config 29 | * Seed provided configuration options 30 | */ 31 | import { Config } from './app/shared/core/index'; 32 | import { Page } from 'ui/page'; 33 | Config.PageClass = Page; 34 | 35 | // (required) platform target (allows component decorators to use the right view template) 36 | Config.PLATFORM_TARGET = Config.PLATFORMS.MOBILE_NATIVE; 37 | 38 | // (optional) log level - defaults to no logging if not set 39 | Config.DEBUG.LEVEL_4 = true; 40 | 41 | // (optional) custom i18n language support 42 | // example of how you can configure your own language sets 43 | // you can use the AppConfig class or build something similar into your own framework 44 | import { AppConfig } from './app/shared/sample/services/app-config'; 45 | 46 | @NgModule({ 47 | imports: [ 48 | CoreModule.forRoot([ 49 | { provide: WindowService, useClass: WindowNative }, 50 | { provide: ConsoleService, useFactory: (cons) }, 51 | ]), 52 | ComponentsModule, 53 | NativeScriptRouterModule.forRoot(routes) 54 | ], 55 | providers: [ 56 | { provide: RouterExtensions, useClass: TNSRouterExtensions }, 57 | { provide: AppService, useClass: NSAppService }, 58 | ], 59 | schemas: [ 60 | NO_ERRORS_SCHEMA, 61 | CUSTOM_ELEMENTS_SCHEMA 62 | ], 63 | bootstrap: [AppComponent] 64 | }) 65 | export class NativeModule { } 66 | -------------------------------------------------------------------------------- /nativescript/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tns-template-hello-world", 3 | "main": "app.js", 4 | "version": "1.2.0", 5 | "author": "Telerik ", 6 | "description": "Nativescript hello-world project template", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/NativeScript/template-hello-world.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/NativeScript/template-hello-world/issues" 14 | }, 15 | "homepage": "https://github.com/NativeScript/template-hello-world" 16 | } 17 | -------------------------------------------------------------------------------- /nativescript/src/references.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /nativescript/src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "lib": [ 11 | "es6", 12 | "dom", 13 | "es2015.iterable" 14 | ], 15 | "sourceMap": true, 16 | "pretty": true, 17 | "noEmitHelpers": true, 18 | "allowUnreachableCode": false, 19 | "allowUnusedLabels": false, 20 | "noImplicitAny": false, 21 | "noImplicitReturns": true, 22 | "noImplicitUseStrict": false, 23 | "noFallthroughCasesInSwitch": true, 24 | "typeRoots": [ 25 | "../node_modules/@types", 26 | "../node_modules" 27 | ], 28 | "types": [ 29 | "jasmine" 30 | ] 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | "platforms", 35 | "*.aot.ts" 36 | ], 37 | "compileOnSave": false 38 | } -------------------------------------------------------------------------------- /nativescript/src/vendor-platform.android.ts: -------------------------------------------------------------------------------- 1 | //Resolve JavaScript classes that extend a Java class, and need to resolve 2 | //their JavaScript module from a bundled script. For example: 3 | //NativeScriptApplication, NativeScriptActivity, etc. 4 | // 5 | //This module gets bundled together with the rest of the app code and the 6 | //`require` calls get resolved to the correct bundling import call. 7 | // 8 | //At runtime the module gets loaded *before* the rest of the app code, so code 9 | //placed here needs to be careful about its dependencies. 10 | 11 | require('application'); 12 | require('ui/frame'); 13 | require('ui/frame/activity'); 14 | 15 | if (global.TNS_WEBPACK) { 16 | global.__requireOverride = function (name, dir) { 17 | if (name === './tns_modules/application/application.js') { 18 | return require('application'); 19 | } else if (name === './tns_modules/ui/frame/frame.js') { 20 | return require('ui/frame'); 21 | } else if (name === './tns_modules/ui/frame/activity.js') { 22 | return require('ui/frame/activity'); 23 | } 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /nativescript/src/vendor-platform.ios.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/nativescript/src/vendor-platform.ios.ts -------------------------------------------------------------------------------- /nativescript/src/vendor.ts: -------------------------------------------------------------------------------- 1 | require('./vendor-platform'); 2 | 3 | require('reflect-metadata'); 4 | require('@angular/platform-browser'); 5 | require('@angular/core'); 6 | require('@angular/common'); 7 | require('@angular/forms'); 8 | require('@angular/http'); 9 | require('@angular/router'); 10 | 11 | require('nativescript-angular/platform-static'); 12 | require('nativescript-angular/forms'); 13 | require('nativescript-angular/http'); 14 | require('nativescript-angular/router'); 15 | -------------------------------------------------------------------------------- /nativescript/tools/webpack/tns-loader.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const loaderUtils = require('loader-utils');; 3 | const _ = require('lodash'); 4 | const template = _.template; 5 | 6 | const htmlCssRegexp = /\.component\.(html|css)/; 7 | const htmlCssReplaceStr = '.component.tns.\$1'; 8 | const componentRegexp = /\.component\.(ts|js)/; 9 | const componentFactoryRegexp = /\.component\.ngfactory\.(ts|js)/; 10 | 11 | const ng2TemplateUrlRegex = /templateUrl *:(.*)$/gm; 12 | const ng2StyleUrlsRegex = /styleUrls *:(\s*\[[^\]]*?\])/g; 13 | const ng2StringReplaceRegexp = /(['"])((?:[^\\]\\\1|.)*?)\1/g; 14 | const ng2ModuleIdRegexp = /(moduleId *: *module\.id,)$/gm; 15 | 16 | function replaceStringsWithRequires(string) { 17 | return string.replace(ng2StringReplaceRegexp, function (match, quote, url) { 18 | if (url.charAt(0) !== '.') { 19 | url = './' + url; 20 | } 21 | 22 | const tnsPath = url.replace(htmlCssRegexp, htmlCssReplaceStr); 23 | if (fs.existsSync(tnsPath)) { 24 | return 'require(\'' + tnsPath + '\')'; 25 | } 26 | 27 | return 'require(\'' + url + '\')'; 28 | }); 29 | } 30 | 31 | function injectTemplateVariables(loaderContext, source) { 32 | // Inject template variables via lodash.template 33 | // Note: We only support the '' syntax (default matches and breaks on es6 string literals). 34 | const query = loaderUtils.getOptions(loaderContext); 35 | 36 | const tpl = template(source, { 37 | interpolate: /<%=([\s\S]+?)%>/g, 38 | }); 39 | 40 | return tpl(query.data); 41 | } 42 | 43 | module.exports = function tnsLoader(source) { 44 | if (this.resourcePath.match(htmlCssRegexp)) { 45 | // If a tns-version of the html/css file exists, replace the source with the content of that file. 46 | const tnsPath = this.resourcePath.replace(htmlCssRegexp, htmlCssReplaceStr); 47 | if (fs.existsSync(tnsPath)) { 48 | const tnsSource = fs.readFileSync(tnsPath, 'UTF-8'); 49 | source = 'module.exports = ' + JSON.stringify(tnsSource); 50 | } 51 | } else if (this.resourcePath.match(componentRegexp)) { 52 | // For ng2 components cnnvert: 53 | // styleUrls = ['file1', ..., fileN] => styles = [require('file1'), ..., require('fileN')] 54 | // templateUrl: 'file' => template: require('file') 55 | // 56 | // Removes moduleId 57 | const styleProperty = 'styles'; 58 | const templateProperty = 'template'; 59 | 60 | source = source.replace(ng2TemplateUrlRegex, function replaceTemplateUrl(match, url) { 61 | return templateProperty + ':' + replaceStringsWithRequires(url); 62 | }) 63 | .replace(ng2StyleUrlsRegex, function replaceStyleUrls(match, urls) { 64 | return styleProperty + ':' + replaceStringsWithRequires(urls); 65 | }) 66 | .replace(ng2ModuleIdRegexp, function moduleId(match, moduleId) { 67 | return '/* ' + moduleId + ' */'; 68 | }); 69 | } else if (this.resourcePath.match(componentFactoryRegexp)) { 70 | // TODO: should/could we do something with the NgFactory files? 71 | } 72 | 73 | return injectTemplateVariables(this, source); 74 | }; -------------------------------------------------------------------------------- /nativescript/tsconfig.aot.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false, 11 | "noEmitHelpers": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "types": [], 14 | "baseUrl": ".", 15 | "paths": { 16 | "ui/*": ["node_modules/tns-core-modules/ui/*"], 17 | "platform": ["node_modules/tns-core-modules/platform"], 18 | "image-source": ["node_modules/tns-core-modules/image-source"], 19 | "xml": ["node_modules/tns-core-modules/xml"], 20 | "xhr": ["node_modules/tns-core-modules/xhr"], 21 | "text": ["node_modules/tns-core-modules/text"], 22 | "data": ["node_modules/tns-core-modules/data"], 23 | "fetch": ["node_modules/tns-core-modules/fetch"], 24 | "trace": ["node_modules/tns-core-modules/trace"], 25 | "fps-meter": ["node_modules/tns-core-modules/fps-meter"], 26 | "color": ["node_modules/tns-core-modules/color"], 27 | "application-settings": ["node_modules/tns-core-modules/application-settings"], 28 | "http": ["node_modules/tns-core-modules/http"], 29 | "camera": ["node_modules/tns-core-modules/camera"], 30 | "console": ["node_modules/tns-core-modules/console"], 31 | "timer": ["node_modules/tns-core-modules/timer"], 32 | "utils": ["node_modules/tns-core-modules/utils"], 33 | "location": ["node_modules/tns-core-modules/location"], 34 | "file-system": ["node_modules/tns-core-modules/file-system"], 35 | "application": ["node_modules/tns-core-modules/application"], 36 | "image-asset": ["node_modules/tns-core-modules/image-asset"], 37 | "connectivity": ["node_modules/tns-core-modules/connectivity"], 38 | "globals": ["node_modules/tns-core-modules/globals"] 39 | } 40 | }, 41 | "exclude": [ 42 | "node_modules", 43 | "platforms", 44 | "src" 45 | ], 46 | "angularCompilerOptions": { 47 | "skipMetadataEmit": true, 48 | "genDir": "./" 49 | } 50 | } -------------------------------------------------------------------------------- /nativescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "declaration": false, 7 | "removeComments": true, 8 | "noLib": false, 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "lib": [ 12 | "es6", 13 | "dom", 14 | "es2015.iterable" 15 | ], 16 | "sourceMap": true, 17 | "pretty": true, 18 | "noEmitHelpers": true, 19 | "allowUnreachableCode": false, 20 | "allowUnusedLabels": false, 21 | "noImplicitAny": false, 22 | "noImplicitReturns": true, 23 | "noImplicitUseStrict": false, 24 | "noFallthroughCasesInSwitch": true, 25 | "baseUrl": ".", 26 | "paths": { 27 | "*": [ 28 | "./node_modules/tns-core-modules/*", 29 | "./node_modules/*" 30 | ] 31 | }, 32 | "typeRoots": [ 33 | "../node_modules/@types", 34 | "../node_modules" 35 | ], 36 | "types": [ 37 | "jasmine" 38 | ] 39 | }, 40 | "exclude": [ 41 | "node_modules", 42 | "platforms", 43 | "src", 44 | "**/*.aot.ts" 45 | ], 46 | "compileOnSave": false 47 | } 48 | -------------------------------------------------------------------------------- /nativescript/webpack.android.js: -------------------------------------------------------------------------------- 1 | var makeConfig = require("./webpack.common"); 2 | module.exports = makeConfig("android"); 3 | -------------------------------------------------------------------------------- /nativescript/webpack.ios.js: -------------------------------------------------------------------------------- 1 | var makeConfig = require("./webpack.common"); 2 | module.exports = makeConfig("ios"); 3 | -------------------------------------------------------------------------------- /src/client/app/shared/core/core.module.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { NgModule, ModuleWithProviders, Optional, SkipSelf } from '@angular/core'; 3 | import { CommonModule } from '@angular/common'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { RouterModule } from '@angular/router'; 6 | import { HttpModule } from '@angular/http'; 7 | 8 | // module 9 | import { CORE_DIRECTIVES } from './directives/index'; 10 | import { CORE_PROVIDERS } from './services/index'; 11 | import { Config } from './utils/index'; 12 | 13 | interface ICoreModuleOptions { 14 | window?: any; 15 | console?: any; 16 | } 17 | 18 | /** 19 | * Do not specify providers for modules that might be imported by a lazy loaded module. 20 | */ 21 | 22 | @NgModule({ 23 | imports: [ 24 | CommonModule, 25 | RouterModule, 26 | HttpModule 27 | ], 28 | declarations: [ 29 | CORE_DIRECTIVES 30 | ], 31 | exports: [ 32 | CommonModule, 33 | FormsModule, 34 | RouterModule, 35 | HttpModule, 36 | CORE_DIRECTIVES 37 | ], 38 | providers: [ 39 | CORE_PROVIDERS 40 | ] 41 | }) 42 | export class CoreModule { 43 | // configuredProviders: *required to configure WindowService and ConsoleService per platform 44 | static forRoot(configuredProviders: Array): ModuleWithProviders { 45 | return { 46 | ngModule: CoreModule, 47 | providers: configuredProviders 48 | }; 49 | } 50 | constructor(@Optional() @SkipSelf() parentModule: CoreModule) { 51 | if (parentModule) { 52 | throw new Error('CoreModule already loaded; Import in root module only.'); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/client/app/shared/core/directives/index.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import { PlatformDirective } from './platform.directive'; 3 | 4 | export const CORE_DIRECTIVES: any[] = [ 5 | PlatformDirective 6 | ]; 7 | 8 | export * from './platform.directive'; 9 | -------------------------------------------------------------------------------- /src/client/app/shared/core/directives/platform.directive.spec.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { TestBed } from '@angular/core/testing'; 3 | import { Component } from '@angular/core'; 4 | 5 | // app 6 | import { t } from '../../test/index'; 7 | 8 | // module 9 | import { PlatformDirective } from './platform.directive'; 10 | import { WindowService } from '../../core/index'; 11 | import { WindowMock } from '../../core/testing/index'; 12 | 13 | const testModuleConfig = () => { 14 | TestBed.configureTestingModule({ 15 | declarations: [PlatformDirective, TestComponent] 16 | }); 17 | }; 18 | 19 | @Component({ 20 | viewProviders: [ 21 | { provide: WindowService, useClass: WindowMock } 22 | ], 23 | selector: 'test-cmp', 24 | template: `
` 25 | }) 26 | class TestComponent { } 27 | 28 | export function main() { 29 | t.describe('core: PlatformDirective', () => { 30 | 31 | t.be(testModuleConfig); 32 | 33 | t.it('should add platform class', 34 | t.async(() => { 35 | TestBed.compileComponents() 36 | .then(() => { 37 | let fixture = TestBed.createComponent(TestComponent); 38 | fixture.detectChanges(); 39 | let compDOMEl = fixture.debugElement.children[0].nativeElement; 40 | t.e(compDOMEl.getAttribute('class')).toBe('web'); 41 | }); 42 | })); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /src/client/app/shared/core/directives/platform.directive.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Directive, ElementRef, Renderer } from '@angular/core'; 3 | 4 | // module 5 | import { WindowService } from '../services/window.service'; 6 | 7 | @Directive({ 8 | selector: '[platform]' 9 | }) 10 | export class PlatformDirective { 11 | 12 | constructor(private el: ElementRef, private renderer: Renderer, private win: WindowService) { 13 | let platformClass = 'web'; 14 | let agent = win.navigator.userAgent.toLowerCase(); 15 | if (agent.indexOf('electron') > -1) { 16 | platformClass = 'desktop'; 17 | } else if (agent.indexOf('nativescript') > -1) { 18 | platformClass = 'nativescript'; 19 | } 20 | renderer.setElementClass(el.nativeElement, platformClass, true); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/client/app/shared/core/index.ts: -------------------------------------------------------------------------------- 1 | // utilities 2 | // generally static helpers (non-injectables) 3 | export * from './utils/index'; 4 | 5 | // interfaces 6 | export * from './interfaces/index'; 7 | 8 | // services 9 | export * from './services/index'; 10 | 11 | // directives 12 | export * from './directives/index'; 13 | -------------------------------------------------------------------------------- /src/client/app/shared/core/interfaces/iconsole.ts: -------------------------------------------------------------------------------- 1 | // standard console interface 2 | export interface IConsole { 3 | log(m: any): void; 4 | debug(m: any): void; 5 | error(m: any): void; 6 | warn(m: any): void; 7 | info(m: any): void; 8 | } 9 | -------------------------------------------------------------------------------- /src/client/app/shared/core/interfaces/ilang.ts: -------------------------------------------------------------------------------- 1 | // standard language interface 2 | export interface ILang { 3 | code: string; 4 | title: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/client/app/shared/core/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './iconsole'; 2 | export * from './ilang'; 3 | export * from './iwindow'; 4 | -------------------------------------------------------------------------------- /src/client/app/shared/core/interfaces/iwindow.ts: -------------------------------------------------------------------------------- 1 | // standard window interface 2 | export interface IWindow { 3 | navigator: any; 4 | location: any; 5 | alert(msg: string): void; 6 | confirm(msg: string): void; 7 | } 8 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | // app 4 | import { LogService } from './log.service'; 5 | import { Config } from '../utils/config'; 6 | 7 | @Injectable() 8 | export class AppService { 9 | constructor(public log: LogService) { 10 | this.log.debug(`AppService -> Config env: ${Config.ENVIRONMENT().ENV}`); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/console.service.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Injectable } from '@angular/core'; 3 | 4 | // module 5 | import { IConsole } from '../interfaces/iconsole'; 6 | 7 | @Injectable() 8 | export class ConsoleService implements IConsole { 9 | 10 | public log(m: any): void { return; } 11 | public debug(m: any): void { return; } 12 | public error(m: any): void { return; } 13 | public warn(m: any): void { return; } 14 | public info(m: any): void { return; } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/index.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import { ConsoleService } from './console.service'; 3 | import { LogService } from './log.service'; 4 | import { RouterExtensions } from './router-extensions.service'; 5 | import { WindowService } from './window.service'; 6 | import { AppService } from './app.service'; 7 | 8 | export const CORE_PROVIDERS: any[] = [ 9 | AppService, 10 | ConsoleService, 11 | LogService, 12 | RouterExtensions, 13 | WindowService 14 | ]; 15 | 16 | export * from './app.service'; 17 | export * from './console.service'; 18 | export * from './log.service'; 19 | export * from './router-extensions.service'; 20 | export * from './window.service'; 21 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/log.service.spec.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { TestBed } from '@angular/core/testing'; 3 | 4 | // app 5 | import { t } from '../../test/index'; 6 | 7 | // module 8 | import { Config, ConsoleService, LogService } from '../index'; 9 | 10 | const providers: Array = [ 11 | { provide: ConsoleService, useValue: console }, 12 | LogService 13 | ]; 14 | 15 | export function main() { 16 | t.describe('core: LogService', () => { 17 | 18 | t.be(() => { 19 | // ensure statics are in default state 20 | Config.RESET(); 21 | // spy 22 | t.spyOn(console, 'log'); 23 | t.spyOn(console, 'error'); 24 | t.spyOn(console, 'warn'); 25 | t.spyOn(console, 'info'); 26 | 27 | TestBed.configureTestingModule({ 28 | providers: providers 29 | }); 30 | }); 31 | 32 | t.describe('api', () => { 33 | 34 | t.it('sanity', t.inject([LogService], (log: LogService) => { 35 | t.e(log.debug).toBeDefined(); 36 | t.e(log.error).toBeDefined(); 37 | t.e(log.warn).toBeDefined(); 38 | t.e(log.info).toBeDefined(); 39 | })); 40 | 41 | t.it('should not log anything by default', t.inject([LogService], (log: LogService) => { 42 | log.debug('debug'); 43 | t.e(console.log).not.toHaveBeenCalledWith('debug'); 44 | log.error('error'); 45 | t.e(console.error).not.toHaveBeenCalledWith('error'); 46 | log.warn('warn'); 47 | t.e(console.warn).not.toHaveBeenCalledWith('warn'); 48 | log.info('info'); 49 | t.e(console.info).not.toHaveBeenCalledWith('info'); 50 | })); 51 | }); 52 | 53 | t.describe('debug levels', () => { 54 | 55 | t.be(() => { 56 | Config.RESET(); 57 | }); 58 | 59 | t.it('LEVEL_4: everything', t.inject([LogService], (log: LogService) => { 60 | Config.DEBUG.LEVEL_4 = true; 61 | 62 | log.debug('debug'); 63 | t.e(console.log).toHaveBeenCalledWith('debug'); 64 | log.error('error'); 65 | t.e(console.error).toHaveBeenCalledWith('error'); 66 | log.warn('warn'); 67 | t.e(console.warn).toHaveBeenCalledWith('warn'); 68 | log.info('info'); 69 | t.e(console.info).toHaveBeenCalledWith('info'); 70 | })); 71 | 72 | t.it('LEVEL_3: error only', t.inject([LogService], (log: LogService) => { 73 | Config.DEBUG.LEVEL_3 = true; 74 | 75 | log.debug('debug'); 76 | t.e(console.log).not.toHaveBeenCalledWith('debug'); 77 | log.error('error'); 78 | t.e(console.error).toHaveBeenCalledWith('error'); 79 | log.warn('warn'); 80 | t.e(console.warn).not.toHaveBeenCalledWith('warn'); 81 | log.info('info'); 82 | t.e(console.info).not.toHaveBeenCalledWith('info'); 83 | 84 | // always overrides lower levels and allows them to come through 85 | Config.DEBUG.LEVEL_4 = true; 86 | 87 | log.debug('debug w/level_4'); 88 | t.e(console.log).toHaveBeenCalledWith('debug w/level_4'); 89 | log.error('error w/level_4'); 90 | t.e(console.error).toHaveBeenCalledWith('error w/level_4'); 91 | log.warn('warn w/level_4'); 92 | t.e(console.warn).toHaveBeenCalledWith('warn w/level_4'); 93 | log.info('info w/level_4'); 94 | t.e(console.info).toHaveBeenCalledWith('info w/level_4'); 95 | })); 96 | 97 | t.it('LEVEL_2: warn only', t.inject([LogService], (log: LogService) => { 98 | Config.DEBUG.LEVEL_2 = true; 99 | 100 | log.debug('debug'); 101 | t.e(console.log).not.toHaveBeenCalledWith('debug'); 102 | log.error('error'); 103 | t.e(console.error).not.toHaveBeenCalledWith('error'); 104 | log.warn('warn'); 105 | t.e(console.warn).toHaveBeenCalledWith('warn'); 106 | log.info('info'); 107 | t.e(console.info).not.toHaveBeenCalledWith('info'); 108 | })); 109 | 110 | t.it('LEVEL_1: info only', t.inject([LogService], (log: LogService) => { 111 | Config.DEBUG.LEVEL_1 = true; 112 | 113 | log.debug('debug'); 114 | t.e(console.log).not.toHaveBeenCalledWith('debug'); 115 | log.error('error'); 116 | t.e(console.error).not.toHaveBeenCalledWith('error'); 117 | log.warn('warn'); 118 | t.e(console.warn).not.toHaveBeenCalledWith('warn'); 119 | log.info('info'); 120 | t.e(console.info).toHaveBeenCalledWith('info'); 121 | })); 122 | }); 123 | }); 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/log.service.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Injectable, Inject, forwardRef } from '@angular/core'; 3 | 4 | // module 5 | import { Config } from '../utils/config'; 6 | import { ConsoleService } from './console.service'; 7 | 8 | @Injectable() 9 | export class LogService { 10 | 11 | constructor(@Inject(forwardRef(() => ConsoleService)) public logger: ConsoleService) {} 12 | 13 | // debug (standard output) 14 | public debug(msg: any) { 15 | if (Config.DEBUG.LEVEL_4) { 16 | // console.debug does not work on {N} apps... use `log` 17 | this.logger.log(msg); 18 | } 19 | } 20 | 21 | // error 22 | public error(err: any) { 23 | if (Config.DEBUG.LEVEL_4 || Config.DEBUG.LEVEL_3) { 24 | this.logger.error(err); 25 | } 26 | } 27 | 28 | // warn 29 | public warn(err: any) { 30 | if (Config.DEBUG.LEVEL_4 || Config.DEBUG.LEVEL_2) { 31 | this.logger.warn(err); 32 | } 33 | } 34 | 35 | // info 36 | public info(err: any) { 37 | if (Config.DEBUG.LEVEL_4 || Config.DEBUG.LEVEL_1) { 38 | this.logger.info(err); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/router-extensions.service.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Injectable } from '@angular/core'; 3 | import { LocationStrategy } from '@angular/common'; 4 | import { Router, UrlTree, NavigationExtras } from '@angular/router'; 5 | 6 | export interface ExtendedNavigationExtras extends NavigationExtras { 7 | // Options for nativescript 8 | clearHistory?: boolean; 9 | animated?: boolean; 10 | transition?: { // See -> https://docs.nativescript.org/api-reference/interfaces/_ui_frame_.navigationtransition.html 11 | name?: string; 12 | instance?: any; 13 | duration?: number; 14 | curve?: any; 15 | }; 16 | // END - Options for nativescript 17 | } 18 | 19 | export interface IRouterExtensions { 20 | navigate(commands: Array, extras?: ExtendedNavigationExtras): Promise; 21 | navigateByUrl(url: string | UrlTree, options?: ExtendedNavigationExtras): Promise; 22 | back(): void; 23 | } 24 | 25 | @Injectable() 26 | export class RouterExtensions implements IRouterExtensions { 27 | 28 | constructor(public router: Router, private locationStrategy: LocationStrategy) { } 29 | 30 | public navigate(commands: Array, extras?: ExtendedNavigationExtras): Promise { 31 | return this.router.navigate(commands, extras); 32 | } 33 | 34 | public navigateByUrl(url: string | UrlTree, options?: ExtendedNavigationExtras): Promise { 35 | return this.router.navigateByUrl(url); 36 | } 37 | 38 | public back() { 39 | this.locationStrategy.back(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/client/app/shared/core/services/window.service.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { Injectable } from '@angular/core'; 3 | 4 | // module 5 | import { IWindow } from '../interfaces/iwindow'; 6 | 7 | @Injectable() 8 | export class WindowService implements IWindow { 9 | 10 | public navigator: any = {}; 11 | public location: any = {}; 12 | public alert(msg: string): void { return; } 13 | public confirm(msg: string): void { return; } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/client/app/shared/core/tokens.ts: -------------------------------------------------------------------------------- 1 | import {OpaqueToken} from '@angular/core'; 2 | 3 | export const FRAME: OpaqueToken = new OpaqueToken('Frame'); 4 | 5 | 6 | export const TOKENS_SHARED: Array = [ 7 | { provide: FRAME, useValue: {} } 8 | ]; -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/config.spec.ts: -------------------------------------------------------------------------------- 1 | // libs 2 | import * as _ from 'lodash'; 3 | 4 | // app 5 | import { t } from '../../test/index'; 6 | 7 | // module 8 | import { Config } from './config'; 9 | 10 | export function main() { 11 | t.describe('core: Config', () => { 12 | t.be(() => Config.RESET()); 13 | 14 | t.it('ENVIRONMENT', () => { 15 | t.e(Config.ENVIRONMENT).toBeDefined(); 16 | }); 17 | t.it('PLATFORMS', () => { 18 | t.e(_.keys(Config.PLATFORMS).length).toBe(4); 19 | t.e(Config.PLATFORM_TARGET).toBeDefined(); 20 | t.e(Config.PLATFORMS.WEB).toBe('web'); 21 | t.e(Config.PLATFORMS.MOBILE_NATIVE).toBe('mobile_native'); 22 | t.e(Config.PLATFORMS.MOBILE_HYBRID).toBe('mobile_hybrid'); 23 | t.e(Config.PLATFORMS.DESKTOP).toBe('desktop'); 24 | 25 | t.e(Config.IS_WEB).toBeDefined(); 26 | t.e(Config.IS_MOBILE_NATIVE).toBeDefined(); 27 | t.e(Config.IS_MOBILE_HYBRID).toBeDefined(); 28 | t.e(Config.IS_DESKTOP).toBeDefined(); 29 | }); 30 | t.it('DEBUG', () => { 31 | t.e(Config.DEBUG.LEVEL_1).toBe(false); 32 | t.e(Config.DEBUG.LEVEL_2).toBe(false); 33 | t.e(Config.DEBUG.LEVEL_3).toBe(false); 34 | t.e(Config.DEBUG.LEVEL_4).toBe(false); 35 | t.e(Config.IS_DEBUG_MODE()).toBe(false); 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/config.ts: -------------------------------------------------------------------------------- 1 | // Feel free to extend this interface 2 | // depending on your app specific config. 3 | export interface EnvConfig { 4 | API?: string; 5 | ENV?: string; 6 | } 7 | 8 | export interface IPlatforms { 9 | WEB: string; 10 | MOBILE_NATIVE: string; 11 | MOBILE_HYBRID: string; 12 | DESKTOP: string; 13 | } 14 | 15 | export class Config { 16 | 17 | public static PageClass: any; 18 | 19 | public static DEBUG: any = { 20 | LEVEL_1: false, // .info only 21 | LEVEL_2: false, // .warn only 22 | LEVEL_3: false, // .error only 23 | LEVEL_4: false // .log + all the above 24 | }; 25 | 26 | // supported platforms 27 | public static PLATFORMS: IPlatforms = { 28 | WEB: 'web', 29 | MOBILE_NATIVE: 'mobile_native', 30 | MOBILE_HYBRID: 'mobile_hybrid', 31 | DESKTOP: 'desktop' 32 | }; 33 | 34 | // current target (defaults to web) 35 | public static PLATFORM_TARGET: string = Config.PLATFORMS.WEB; 36 | 37 | // convenient platform checks 38 | public static IS_WEB(): boolean { 39 | return Config.PLATFORM_TARGET === Config.PLATFORMS.WEB; 40 | } 41 | 42 | public static IS_MOBILE_NATIVE(): boolean { 43 | return Config.PLATFORM_TARGET === Config.PLATFORMS.MOBILE_NATIVE; 44 | } 45 | 46 | public static IS_MOBILE_HYBRID(): boolean { 47 | return Config.PLATFORM_TARGET === Config.PLATFORMS.MOBILE_HYBRID; 48 | } 49 | 50 | public static IS_DESKTOP(): boolean { 51 | return Config.PLATFORM_TARGET === Config.PLATFORMS.DESKTOP; 52 | } 53 | 54 | public static ENVIRONMENT(): EnvConfig { 55 | try { 56 | return JSON.parse('<%= ENV_CONFIG %>'); 57 | } catch (exp) { 58 | return {}; 59 | } 60 | } 61 | 62 | public static IS_DEBUG_MODE(): boolean { 63 | for (let key in Config.DEBUG) { 64 | if (Config.DEBUG[key]) { 65 | // if any level is on, debug mode is on 66 | return true; 67 | } 68 | } 69 | return false; 70 | } 71 | 72 | // reset debug defaults 73 | public static RESET() { 74 | for (let key in Config.DEBUG) { 75 | Config.DEBUG[key] = false; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config'; 2 | export * from './type'; 3 | export * from './view-broker'; 4 | -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/type.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This function coerces a string into a string literal type. 3 | * Using tagged union types in TypeScript 2.0, this enables 4 | * powerful typechecking of our reducers. 5 | * 6 | * Since every action label passes through this function it 7 | * is a good place to ensure all of our action labels 8 | * are unique. 9 | */ 10 | 11 | let typeCache: { [label: string]: boolean } = {}; 12 | export function type(label: T | ''): T { 13 | if (typeCache[label]) { 14 | throw new Error(`Action type "${label}" is not unqiue"`); 15 | } 16 | 17 | typeCache[label] = true; 18 | 19 | return label; 20 | } 21 | -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/view-broker.spec.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import { t } from '../../test/index'; 3 | 4 | // module 5 | import { Config } from './config'; 6 | import { ViewBroker } from './view-broker'; 7 | 8 | export function main() { 9 | t.describe('utilities: ViewBroker', () => { 10 | 11 | t.it('TEMPLATE_URL: web', () => { 12 | Config.PLATFORM_TARGET = Config.PLATFORMS.WEB; 13 | t.e(ViewBroker.TEMPLATE_URL('./app/components/home/home.html')).toBe('./app/components/home/home.html'); 14 | }); 15 | t.it('TEMPLATE_URL: mobile_native', () => { 16 | Config.PLATFORM_TARGET = Config.PLATFORMS.MOBILE_NATIVE; 17 | t.e(ViewBroker.TEMPLATE_URL('./app/components/home/home.html')).toBe('./app/components/home/home.tns.html'); 18 | }); 19 | t.it('TEMPLATE_URL: mobile_hybrid', () => { 20 | Config.PLATFORM_TARGET = Config.PLATFORMS.MOBILE_HYBRID; 21 | t.e(ViewBroker.TEMPLATE_URL('./app/components/home/home.html')).toBe('./app/components/home/home.html'); 22 | }); 23 | t.it('TEMPLATE_URL: desktop', () => { 24 | Config.PLATFORM_TARGET = Config.PLATFORMS.DESKTOP; 25 | t.e(ViewBroker.TEMPLATE_URL('./app/components/home/home.html')).toBe('./app/components/home/home.html'); 26 | }); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/client/app/shared/core/utils/view-broker.ts: -------------------------------------------------------------------------------- 1 | // module 2 | import { Config } from './config'; 3 | 4 | export class ViewBroker { 5 | 6 | public static TEMPLATE_URL(path: string): string { 7 | if (Config.IS_MOBILE_NATIVE()) { 8 | let paths = path.split('.'); 9 | paths.splice(-1); 10 | return `${paths.join('.')}.tns.html`; 11 | } else { 12 | return path; 13 | } 14 | } 15 | 16 | public static STYLE_URLS(paths: string[]): string[] { 17 | if (Config.IS_MOBILE_NATIVE()) { 18 | return paths.map((path) => { 19 | let parts = path.split('.'); 20 | parts.splice(-1); 21 | return `${parts.join('.')}.tns.css`; 22 | }); 23 | } else { 24 | return paths; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/client/app/shared/electron/index.ts: -------------------------------------------------------------------------------- 1 | // services 2 | export * from './services/event.service'; 3 | 4 | // utils 5 | export * from './utils/desktop-config'; 6 | -------------------------------------------------------------------------------- /src/client/app/shared/electron/services/event.service.ts: -------------------------------------------------------------------------------- 1 | // libs 2 | import { Observable } from 'rxjs/Observable'; 3 | import 'rxjs/add/observable/fromEvent'; 4 | 5 | declare var window: any; 6 | 7 | export class ElectronEventService { 8 | 9 | public static on(name: string): Observable { 10 | return Observable.fromEvent(window, name); 11 | } 12 | 13 | // TODO: add more helpers for menu setup and more... 14 | } 15 | -------------------------------------------------------------------------------- /src/client/app/shared/electron/utils/desktop-config.spec.ts: -------------------------------------------------------------------------------- 1 | import { t } from '../../test/index'; 2 | import { DesktopConfig } from './desktop-config'; 3 | 4 | export function main() { 5 | t.describe('electron: DesktopConfig', () => { 6 | 7 | t.it('SUPPORTED_LANGUAGES', () => { 8 | t.e(DesktopConfig.SUPPORTED_LANGUAGES.length).toBe(5); 9 | t.e(DesktopConfig.SUPPORTED_LANGUAGES[0].code).toBe('en'); 10 | t.e(DesktopConfig.SUPPORTED_LANGUAGES[1].code).toBe('es'); 11 | t.e(DesktopConfig.SUPPORTED_LANGUAGES[2].code).toBe('fr'); 12 | t.e(DesktopConfig.SUPPORTED_LANGUAGES[3].code).toBe('ru'); 13 | t.e(DesktopConfig.SUPPORTED_LANGUAGES[4].code).toBe('bg'); 14 | }); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /src/client/app/shared/electron/utils/desktop-config.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import { ILang } from '../../core/index'; 3 | 4 | export class DesktopConfig { 5 | 6 | public static SUPPORTED_LANGUAGES: Array = [ 7 | { code: 'en', title: 'English' }, 8 | { code: 'es', title: 'Spanish' }, 9 | { code: 'fr', title: 'French' }, 10 | { code: 'ru', title: 'Russian' }, 11 | { code: 'bg', title: 'Bulgarian' } 12 | ]; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
-------------------------------------------------------------------------------- /src/client/app/shared/sample/components/app/app.component.tns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/app/app.component.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import {Component} from '@angular/core'; 3 | 4 | // app 5 | 6 | @Component({ 7 | moduleId: module.id, 8 | selector: 'sd-app', 9 | templateUrl: 'app.component.html', 10 | }) 11 | export class AppComponent {} 12 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import {HomeRoutes} from '../../components/home/home.routes'; 3 | 4 | export const routes: Array = [ 5 | ...HomeRoutes 6 | ]; 7 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.component.html: -------------------------------------------------------------------------------- 1 |

Your App

2 |
3 |

Tap the button

4 | 5 |

{{ message }}

6 |
-------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.component.tns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'sd-home', 6 | templateUrl: 'home.component.html', 7 | styleUrls: ['home.css'] 8 | }) 9 | export class HomeComponent implements OnInit { 10 | private counter: number; 11 | private message: string; 12 | 13 | constructor() {} 14 | 15 | ngOnInit() { 16 | this.counter = 42; 17 | this.updateMessage(); 18 | } 19 | 20 | updateCounter() { 21 | this.counter--; 22 | this.updateMessage(); 23 | } 24 | 25 | private updateMessage() { 26 | if (this.counter <= 0) { 27 | this.message = 'Hoorraaay! You unlocked the NativeScript clicker achievement!'; 28 | } else { 29 | this.message = `${this.counter} taps left`; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.css: -------------------------------------------------------------------------------- 1 | button { 2 | background-color: #30BCFF; 3 | color: white; 4 | padding: 0.5em 1em; 5 | border: none; 6 | font-size: 1.5em; 7 | } -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.routes.ts: -------------------------------------------------------------------------------- 1 | import { Route } from '@angular/router'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | export const HomeRoutes: Route[] = [ 6 | { 7 | path: '', 8 | component: HomeComponent 9 | }, 10 | ]; 11 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/home/home.tns.css: -------------------------------------------------------------------------------- 1 | .btn { 2 | font-size: 30; 3 | } -------------------------------------------------------------------------------- /src/client/app/shared/sample/components/index.ts: -------------------------------------------------------------------------------- 1 | import { HomeComponent } from './home/home.component'; 2 | 3 | 4 | // for routes 5 | export const APP_COMPONENTS: any[] = [ 6 | HomeComponent 7 | ]; 8 | 9 | export * from './app/app.component'; 10 | export * from './home/home.component'; 11 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/index.ts: -------------------------------------------------------------------------------- 1 | // components 2 | export * from './components/index'; 3 | 4 | // directives 5 | // export * from './directives/index'; 6 | 7 | // services 8 | export * from './services/index'; 9 | 10 | // routes 11 | export * from './routes'; 12 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/models/sample.model.ts: -------------------------------------------------------------------------------- 1 | export class SampleModel { 2 | } -------------------------------------------------------------------------------- /src/client/app/shared/sample/routes.ts: -------------------------------------------------------------------------------- 1 | import {HomeRoutes} from './components/home/home.routes'; 2 | 3 | export const routes: Array = [ 4 | ...HomeRoutes 5 | ]; 6 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/sample.module.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { NgModule, ModuleWithProviders, Optional, SkipSelf } from '@angular/core'; 3 | 4 | // app 5 | import { CoreModule } from '../core/core.module'; 6 | import { TOKENS_SHARED } from '../core/tokens'; 7 | import { SAMPLE_PROVIDERS } from './services/index'; 8 | 9 | 10 | /** 11 | * Do not specify providers for modules that might be imported by a lazy loaded module. 12 | */ 13 | 14 | @NgModule({ 15 | imports: [ 16 | CoreModule 17 | ], 18 | providers: [ 19 | SAMPLE_PROVIDERS, 20 | TOKENS_SHARED 21 | ] 22 | }) 23 | export class SampleModule { 24 | static forRoot(configuredProviders: Array): ModuleWithProviders { 25 | return { 26 | ngModule: SampleModule, 27 | providers: configuredProviders 28 | }; 29 | } 30 | constructor( @Optional() @SkipSelf() parentModule: SampleModule) { 31 | console.log(`SampleModule constructor`); 32 | if (parentModule) { 33 | throw new Error('SampleModule already loaded; Import in root module only.'); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/services/app-config.ts: -------------------------------------------------------------------------------- 1 | // app 2 | import { ILang } from '../../core/index'; 3 | 4 | export class AppConfig { 5 | 6 | public static SUPPORTED_LANGUAGES: Array = [ 7 | { code: 'en', title: 'English' }, 8 | { code: 'es', title: 'Spanish' }, 9 | { code: 'fr', title: 'French' }, 10 | { code: 'ru', title: 'Russian' }, 11 | { code: 'bg', title: 'Bulgarian' } 12 | ]; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/client/app/shared/sample/services/index.ts: -------------------------------------------------------------------------------- 1 | import {SampleService} from './sample.service'; 2 | 3 | export const SAMPLE_PROVIDERS: Array = [ 4 | SampleService 5 | ]; 6 | 7 | export * from './sample.service'; -------------------------------------------------------------------------------- /src/client/app/shared/sample/services/sample.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {LogService} from '../../core/services/log.service'; 3 | import {Config} from '../../core/utils/config'; 4 | import {Observable} from 'rxjs/Observable'; 5 | import {BehaviorSubject} from 'rxjs/BehaviorSubject'; 6 | import 'rxjs/add/operator/share'; 7 | import {SampleModel} from '../models/sample.model'; 8 | 9 | @Injectable() 10 | export class SampleService { 11 | 12 | constructor( 13 | private logger: LogService) { 14 | logger.debug(`SampleService initializing...`); 15 | 16 | if (Config.IS_MOBILE_NATIVE()) { 17 | //initialize your service for NativeScript 18 | } else { 19 | //initialize it for web 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/client/assets/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Edsger Dijkstra", 3 | "Donald Knuth", 4 | "Alan Turing", 5 | "Grace Hopper" 6 | ] 7 | -------------------------------------------------------------------------------- /src/client/assets/favicon/favicon-DEV.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/src/client/assets/favicon/favicon-DEV.ico -------------------------------------------------------------------------------- /src/client/assets/favicon/favicon-PROD.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/src/client/assets/favicon/favicon-PROD.ico -------------------------------------------------------------------------------- /src/client/assets/logo.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/src/client/assets/logo.icns -------------------------------------------------------------------------------- /src/client/assets/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlooper/angular-starter/b76aa75485e9222c1dc7f4ad8730b9e19582bcd6/src/client/assets/logo.ico -------------------------------------------------------------------------------- /src/client/assets/svg/more.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /src/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= APP_TITLE %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% if (TARGET_DESKTOP) { %> 16 | 17 | 18 | <% } %> 19 | 20 | 21 | 22 | 23 | Loading... 24 | 25 | 29 | 30 | <% if (!TARGET_DESKTOP) { %> 31 | 32 | 33 | <% } %> 34 | 35 | <% if (BUILD_TYPE === 'dev') { %> 36 | 37 | <% } %> 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | <% if (BUILD_TYPE === 'dev') { %> 46 | 53 | <% } %> 54 | 55 | <% if (TARGET_DESKTOP && BUILD_TYPE !== 'prod') { %> 56 | 57 | <% } %> 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/client/main.web.prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstraps the application and makes the ROUTER_PROVIDERS and the APP_BASE_HREF available to it. 3 | * @see https://angular.io/docs/ts/latest/api/platform-browser-dynamic/index/bootstrap-function.html 4 | */ 5 | import { enableProdMode } from '@angular/core'; 6 | import { platformBrowser } from '@angular/platform-browser'; 7 | 8 | import { WebModuleNgFactory } from './web.module.ngfactory'; 9 | 10 | enableProdMode(); 11 | 12 | platformBrowser().bootstrapModuleFactory(WebModuleNgFactory); 13 | 14 | // In order to start the Service Worker located at "./worker.js" 15 | // uncomment this line. More about Service Workers here 16 | // https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers 17 | // 18 | // if ('serviceWorker' in navigator) { 19 | // (navigator).serviceWorker.register('./worker.js').then((registration: any) => 20 | // console.log('ServiceWorker registration successful with scope: ', registration.scope)) 21 | // .catch((err: any) => 22 | // console.log('ServiceWorker registration failed: ', err)); 23 | // } 24 | -------------------------------------------------------------------------------- /src/client/main.web.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstraps the application and makes the ROUTER_PROVIDERS and the APP_BASE_HREF available to it. 3 | * @see https://angular.io/docs/ts/latest/api/platform-browser-dynamic/index/bootstrap-function.html 4 | */ 5 | import { enableProdMode } from '@angular/core'; 6 | // The browser platform with a compiler 7 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 8 | // Load i18n providers 9 | // import { TranslationProviders } from './i18n.providers'; 10 | 11 | // platfrom module 12 | import { WebModule } from './web.module'; 13 | 14 | // example of how to use build variables to determine environment 15 | if (String('<%= BUILD_TYPE %>') === 'prod' || String('<%= TARGET_DESKTOP_BUILD %>') === 'true') { 16 | enableProdMode(); 17 | } 18 | 19 | // NOTE: Commented lines come from parent (angular-seed) 20 | // TODO: In future, may pivot from ng2-translate to parent seed implementation 21 | // Compile and launch the module with i18n providers 22 | // let TP = new TranslationProviders(); 23 | // TP.getTranslationFile().then((providers: any) => { 24 | // const options: any = { providers }; 25 | platformBrowserDynamic().bootstrapModule(WebModule/*, options*/); 26 | // }); 27 | -------------------------------------------------------------------------------- /src/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed-advanced", 3 | "version": "1.0.0", 4 | "main": "main.desktop.js" 5 | } 6 | -------------------------------------------------------------------------------- /src/client/system-config.ts: -------------------------------------------------------------------------------- 1 | declare var System: SystemJSLoader.System; 2 | 3 | System.config(JSON.parse('<%= SYSTEM_CONFIG_DEV %>')); 4 | -------------------------------------------------------------------------------- /src/client/tokens.web.ts: -------------------------------------------------------------------------------- 1 | 2 | export const TOKENS_WEB: Array = [ 3 | ]; -------------------------------------------------------------------------------- /src/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "lib": ["es2016", "dom"], 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "sourceMap": true, 12 | "pretty": true, 13 | "allowUnreachableCode": false, 14 | "allowUnusedLabels": false, 15 | "noImplicitAny": false, 16 | "noImplicitReturns": true, 17 | "noImplicitUseStrict": false, 18 | "noFallthroughCasesInSwitch": true, 19 | "allowSyntheticDefaultImports": true, 20 | "typeRoots": [ 21 | "../../node_modules/@types", 22 | "../../node_modules" 23 | ], 24 | "types": [ 25 | "node", 26 | "jasmine", 27 | "protractor", 28 | "systemjs" 29 | ] 30 | }, 31 | "exclude": [ 32 | "desktop", 33 | "nativescript", 34 | "node_modules", 35 | "dist", 36 | "src" 37 | ], 38 | "compileOnSave": false 39 | } 40 | -------------------------------------------------------------------------------- /src/client/web.module.ts: -------------------------------------------------------------------------------- 1 | // angular 2 | import { NgModule } from '@angular/core'; 3 | import { APP_BASE_HREF } from '@angular/common'; 4 | import { BrowserModule } from '@angular/platform-browser'; 5 | import { RouterModule } from '@angular/router'; 6 | import { Http } from '@angular/http'; 7 | 8 | // app 9 | import { APP_COMPONENTS, AppComponent } from './app/shared/sample/components/index'; 10 | import { routes } from './app/shared/sample/components/app/app.routes'; 11 | 12 | // feature modules 13 | import { CoreModule } from './app/shared/core/core.module'; 14 | import { SampleModule } from './app/shared/sample/sample.module'; 15 | 16 | // config 17 | import { Config, WindowService, ConsoleService } from './app/shared/core/index'; 18 | Config.PLATFORM_TARGET = Config.PLATFORMS.WEB; 19 | if (String('<%= BUILD_TYPE %>') === 'dev') { 20 | // only output console logging in dev mode 21 | Config.DEBUG.LEVEL_4 = true; 22 | } 23 | 24 | // sample config (extra) 25 | import { AppConfig } from './app/shared/sample/services/app-config'; 26 | 27 | let routerModule = RouterModule.forRoot(routes); 28 | 29 | if (String('<%= TARGET_DESKTOP %>') === 'true') { 30 | Config.PLATFORM_TARGET = Config.PLATFORMS.DESKTOP; 31 | // desktop (electron) must use hash 32 | routerModule = RouterModule.forRoot(routes, {useHash: true}); 33 | } 34 | 35 | declare var window, console; 36 | 37 | // For AoT compilation to work: 38 | export function win() { 39 | return window; 40 | } 41 | export function cons() { 42 | return console; 43 | } 44 | 45 | let DEV_IMPORTS: any[] = []; 46 | 47 | if (String('<%= BUILD_TYPE %>') === 'dev') { 48 | DEV_IMPORTS = [ 49 | ...DEV_IMPORTS 50 | ]; 51 | } 52 | 53 | @NgModule({ 54 | imports: [ 55 | BrowserModule, 56 | CoreModule.forRoot([ 57 | { provide: WindowService, useFactory: (win) }, 58 | { provide: ConsoleService, useFactory: (cons) } 59 | ]), 60 | routerModule, 61 | SampleModule, 62 | DEV_IMPORTS 63 | ], 64 | declarations: [ 65 | APP_COMPONENTS, 66 | AppComponent 67 | ], 68 | providers: [ 69 | { 70 | provide: APP_BASE_HREF, 71 | useValue: '<%= APP_BASE %>' 72 | } 73 | ], 74 | bootstrap: [AppComponent] 75 | }) 76 | 77 | export class WebModule { } 78 | -------------------------------------------------------------------------------- /tools/config.ts: -------------------------------------------------------------------------------- 1 | import { ProjectConfig } from './config/project.config'; 2 | 3 | const config: ProjectConfig = new ProjectConfig(); 4 | export default config; 5 | -------------------------------------------------------------------------------- /tools/config/banner.txt: -------------------------------------------------------------------------------- 1 | Welcome to _ _ 2 | __ _ _ __ __ _ _ _| | __ _ _ __ ___ ___ ___ __| | 3 | / _` | '_ \ / _` | | | | |/ _` | '__|____/ __|/ _ \/ _ \/ _` | 4 | | (_| | | | | (_| | |_| | | (_| | | |_____\__ \ __/ __/ (_| | 5 | \__,_|_| |_|\__, |\__,_|_|\__,_|_| |___/\___|\___|\__,_| 6 | |___/ 7 | -------------------------------------------------------------------------------- /tools/config/project.config.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { SeedAdvancedConfig } from './seed-advanced.config'; 3 | // import { ExtendPackages } from './seed.config.interfaces'; 4 | 5 | /** 6 | * This class extends the basic seed configuration, allowing for project specific overrides. A few examples can be found 7 | * below. 8 | */ 9 | export class ProjectConfig extends SeedAdvancedConfig { 10 | 11 | PROJECT_TASKS_DIR = join(process.cwd(), this.TOOLS_DIR, 'tasks', 'project'); 12 | 13 | constructor() { 14 | super(); 15 | // this.APP_TITLE = 'Put name of your app here'; 16 | 17 | /* Enable typeless compiler runs (faster) between typed compiler runs. */ 18 | // this.TYPED_COMPILE_INTERVAL = 5; 19 | 20 | // Add `NPM` third-party libraries to be injected/bundled. 21 | this.NPM_DEPENDENCIES = [ 22 | ...this.NPM_DEPENDENCIES, 23 | // {src: 'jquery/dist/jquery.min.js', inject: 'libs'}, 24 | ]; 25 | 26 | // Add `local` third-party libraries to be injected/bundled. 27 | this.APP_ASSETS = [ 28 | ...this.APP_ASSETS, 29 | // {src: `${this.APP_SRC}/your-path-to-lib/libs/jquery-ui.js`, inject: true, vendor: false} 30 | // {src: `${this.CSS_SRC}/path-to-lib/test-lib.css`, inject: true, vendor: false}, 31 | ]; 32 | 33 | // Add packages (e.g. ng2-translate) 34 | // ng2-translate is already added with the advanced seed - here for example only 35 | // let additionalPackages: ExtendPackages[] = [{ 36 | // name: 'ng2-translate', 37 | // // Path to the package's bundle 38 | // path: 'node_modules/ng2-translate/bundles/ng2-translate.umd.js' 39 | // }]; 40 | // 41 | // this.addPackagesBundles(additionalPackages); 42 | 43 | /* Add to or override NPM module configurations: */ 44 | // this.mergeObject(this.PLUGIN_CONFIGS['browser-sync'], { ghostMode: false }); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tools/config/project.tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": [ 3 | "tslint", 4 | "build.test", 5 | "karma.run" 6 | ] 7 | } 8 | 9 | -------------------------------------------------------------------------------- /tools/config/seed-advanced.config.ts: -------------------------------------------------------------------------------- 1 | import { argv } from 'yargs'; 2 | import { SeedConfig } from './seed.config'; 3 | import * as path from 'path'; 4 | import { ExtendPackages } from './seed.config.interfaces'; 5 | 6 | export class SeedAdvancedConfig extends SeedConfig { 7 | /** 8 | * The base folder of the nativescript applications source files. 9 | * @type {string} 10 | */ 11 | TNS_BASE_DIR = 'nativescript'; 12 | 13 | srcSubdir = 'src'; 14 | destSubdir = 'app'; 15 | 16 | TNS_APP_SRC = `${this.TNS_BASE_DIR}/${this.srcSubdir}`; 17 | 18 | TNS_APP_DEST = `${this.TNS_BASE_DIR}/${this.destSubdir}`; 19 | 20 | TNS_CONFIG = { 21 | ANALYTICS_TRACKING_ID: '', 22 | }; 23 | 24 | /** 25 | * Holds added packages for desktop build. 26 | */ 27 | DESKTOP_PACKAGES: ExtendPackages[] = []; 28 | 29 | constructor() { 30 | super(); 31 | 32 | let arg: string; 33 | if (argv && argv._) { 34 | arg = argv._[0]; 35 | if (arg.indexOf('desktop') > -1) { 36 | this.TARGET_DESKTOP = true; 37 | if (arg.indexOf('.mac') > -1 || arg.indexOf('.windows') > -1 || arg.indexOf('.linux') > -1) { 38 | this.TARGET_DESKTOP_BUILD = true; 39 | } 40 | } else if (arg.indexOf('hybrid') > -1) { 41 | this.TARGET_MOBILE_HYBRID = true; 42 | } 43 | } 44 | let bootstrap = 'main.web'; 45 | if (this.TARGET_MOBILE_HYBRID) { 46 | // Perhaps Ionic or Cordova 47 | // This is not implemented in the seed but here to show you way forward if you wanted to add 48 | bootstrap = 'main.mobile.hybrid'; 49 | } 50 | 51 | if (argv['analytics']) { 52 | this.TNS_CONFIG.ANALYTICS_TRACKING_ID = argv['analytics']; 53 | } 54 | 55 | // Override seed defaults 56 | this.BOOTSTRAP_DIR = argv['app'] ? (argv['app'] + '/') : ''; 57 | this.BOOTSTRAP_MODULE = `${this.BOOTSTRAP_DIR}${bootstrap}`; 58 | this.NG_FACTORY_FILE = `${bootstrap}.prod`; 59 | this.BOOTSTRAP_PROD_MODULE = `${this.BOOTSTRAP_DIR}${bootstrap}`; 60 | this.BOOTSTRAP_FACTORY_PROD_MODULE = `${this.BOOTSTRAP_DIR}${bootstrap}.prod`; 61 | 62 | this.APP_TITLE = 'Angular Seed Advanced'; 63 | this.APP_BASE = ''; // paths must remain relative 64 | 65 | // Advanced seed packages 66 | let additionalPackages: ExtendPackages[] = [ 67 | { 68 | name: 'lodash', 69 | path: `${this.APP_BASE}node_modules/lodash/lodash.js`, 70 | packageMeta: { 71 | main: 'index.js', 72 | defaultExtension: 'js' 73 | } 74 | } 75 | ]; 76 | 77 | /** 78 | * Need to duplicate this in the project.config.ts to 79 | * pick up packages there too. 80 | */ 81 | this.DESKTOP_PACKAGES = [ 82 | ...this.DESKTOP_PACKAGES, 83 | ...additionalPackages, 84 | ]; 85 | 86 | this.addPackagesBundles(additionalPackages); 87 | 88 | // Settings for building sass (include ./srs/client/scss in includes) 89 | // Needed because for components you cannot use ../../../ syntax 90 | this.PLUGIN_CONFIGS['gulp-sass'] = { 91 | includePaths: [ 92 | './src/client/scss/', 93 | './node_modules/', 94 | './' 95 | ] 96 | }; 97 | 98 | // Settings for building sass for tns modules 99 | this.PLUGIN_CONFIGS['gulp-sass-tns'] = { 100 | includePaths: [ 101 | this.srcSubdir, 102 | './node_modules/', 103 | './node_modules/nativescript-theme-core/scss/' 104 | ].map((dir) => path.resolve(this.TNS_BASE_DIR, dir)), 105 | }; 106 | 107 | // Fix up path to bootstrap module 108 | this.SYSTEM_CONFIG.paths[this.BOOTSTRAP_MODULE] = `${this.APP_BASE}${this.BOOTSTRAP_MODULE}`; 109 | 110 | /** Production **/ 111 | 112 | delete this.SYSTEM_BUILDER_CONFIG['packageConfigPaths']; // not all libs are distributed the same 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tools/config/seed.config.interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface InjectableDependency { 2 | src: string; 3 | inject: string | boolean; 4 | vendor?: boolean; 5 | buildType?: string[] | string; 6 | 7 | // @deprecated 8 | env?: string[] | string; 9 | } 10 | 11 | export interface BuildType { 12 | DEVELOPMENT: string; 13 | PRODUCTION: string; 14 | [key: string]: string; 15 | } 16 | 17 | export interface ExtendPackages { 18 | name: string; 19 | path?: string; 20 | packageMeta?: any; 21 | } 22 | -------------------------------------------------------------------------------- /tools/config/seed.tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "initialize": [ 3 | "noop" 4 | ], 5 | 6 | "build.dev": [ 7 | "initialize", 8 | "clean.once", 9 | "build.assets.dev", 10 | "build.html_css", 11 | "build.js.dev", 12 | "build.index.dev" 13 | ], 14 | 15 | "build.dev.watch": [ 16 | "build.dev", 17 | "watch.dev" 18 | ], 19 | 20 | "build.e2e": [ 21 | "initialize", 22 | "clean.e2e", 23 | "tslint", 24 | "build.js.e2e" 25 | ], 26 | 27 | "build.prod": [ 28 | "initialize", 29 | "check.tools", 30 | "clean.prod", 31 | "tslint", 32 | "build.assets.prod", 33 | "build.html_css", 34 | "copy.prod", 35 | "build.js.prod", 36 | "build.bundles", 37 | "build.bundles.app", 38 | "minify.bundles", 39 | "build.index.prod" 40 | ], 41 | 42 | "build.prod.aot": [ 43 | "initialize", 44 | "check.tools", 45 | "clean.prod", 46 | "tslint", 47 | "build.assets.prod", 48 | "build.html_css", 49 | "copy.prod", 50 | "compile.ahead.prod", 51 | "build.js.prod.aot", 52 | "build.bundles", 53 | "build.bundles.app.aot", 54 | "minify.bundles", 55 | "build.index.prod" 56 | ], 57 | 58 | "build.prod.rollup.aot": [ 59 | "initialize", 60 | "check.tools", 61 | "clean.prod", 62 | "tslint", 63 | "build.assets.prod", 64 | "build.html_css", 65 | "copy.prod.rollup.aot", 66 | "compile.ahead.prod", 67 | "build.js.prod.rollup.aot", 68 | "build.bundles", 69 | "build.bundles.app.rollup.aot", 70 | "transpile.bundles.rollup.aot", 71 | "minify.bundles", 72 | "build.index.prod" 73 | ], 74 | 75 | "build.tns": [ 76 | "build.assets.tns", 77 | "build.tns_html_css", 78 | "build.js.tns" 79 | ], 80 | 81 | "build.prod.tns": [ 82 | "clean.tns", 83 | "tslint.tns", 84 | "build.tns" 85 | ], 86 | 87 | "build.tns.watch": [ 88 | "build.tns", 89 | "watch.tns" 90 | ], 91 | 92 | "build.test": [ 93 | "initialize", 94 | "clean.dev", 95 | "build.assets.dev", 96 | "build.html_css", 97 | "build.js.dev", 98 | "build.js.test", 99 | "build.index.dev" 100 | ], 101 | 102 | "test.watch": [ 103 | "build.test", 104 | "watch.test", 105 | "karma.watch" 106 | ], 107 | 108 | "docs": [ 109 | "build.docs", 110 | "serve.docs" 111 | ], 112 | 113 | "serve.dev": [ 114 | "build.dev", 115 | "server.start", 116 | "watch.dev" 117 | ], 118 | 119 | "serve.e2e": [ 120 | "tslint", 121 | "build.dev", 122 | "build.js.e2e", 123 | "server.start", 124 | "watch.dev", 125 | "watch.e2e" 126 | ], 127 | 128 | "serve.prod": [ 129 | "build.prod", 130 | "server.prod" 131 | ], 132 | 133 | "serve.prod.aot": [ 134 | "build.prod.aot", 135 | "server.prod" 136 | ], 137 | 138 | "serve.prod.rollup.aot": [ 139 | "build.prod.rollup.aot", 140 | "server.prod" 141 | ], 142 | 143 | "test": [ 144 | "build.test", 145 | "karma.run" 146 | ], 147 | 148 | "desktop": [ 149 | "build.dev", 150 | "desktop.libs", 151 | "desktop.build" 152 | ], 153 | 154 | "desktop.mac": [ 155 | "desktop", 156 | "desktop.package.mac" 157 | ], 158 | 159 | "desktop.windows": [ 160 | "desktop", 161 | "desktop.package.windows" 162 | ], 163 | 164 | "desktop.linux": [ 165 | "desktop", 166 | "desktop.package.linux" 167 | ] 168 | } 169 | -------------------------------------------------------------------------------- /tools/config/seed.tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "../../node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "class-name": true, 7 | "curly": false, 8 | "eofline": true, 9 | "indent": [true, "spaces"], 10 | "max-line-length": [true, 600], 11 | "member-ordering": [true, 12 | "public-before-private", 13 | "static-before-instance", 14 | "variables-before-functions" 15 | ], 16 | "no-arg": true, 17 | "no-construct": true, 18 | "no-duplicate-variable": true, 19 | "no-empty": true, 20 | "no-eval": true, 21 | "no-trailing-whitespace": false, 22 | "no-unused-expression": true, 23 | "no-use-before-declare": true, 24 | "one-line": [ 25 | true, 26 | "check-open-brace", 27 | "check-catch", 28 | "check-else", 29 | "check-whitespace" 30 | ], 31 | "quotemark": [ 32 | true, 33 | "single" 34 | ], 35 | "semicolon": [ 36 | true, 37 | "always" 38 | ], 39 | "trailing-comma": true, 40 | "triple-equals": true, 41 | "variable-name": false, 42 | "directive-selector": [true, "attribute", [], "camelCase"], 43 | "component-selector": [true, "element", [], "kebab-case"], 44 | "use-input-property-decorator": true, 45 | "use-output-property-decorator": true, 46 | "use-host-property-decorator": true 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tools/debug.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { argv } from 'yargs'; 3 | 4 | require('../gulpfile'); 5 | 6 | const TASK = argv['task']; 7 | 8 | if (!TASK) { 9 | throw new Error('You must specify a task name.'); 10 | } 11 | 12 | console.log('**********************'); 13 | console.log('* angular-seed tools '); 14 | console.log('* debugging task:', TASK); 15 | console.log('**********************'); 16 | 17 | gulp.start(TASK); 18 | -------------------------------------------------------------------------------- /tools/env/base.ts: -------------------------------------------------------------------------------- 1 | import { EnvConfig } from './env-config.interface'; 2 | 3 | const BaseConfig: EnvConfig = { 4 | // Sample API url 5 | API: 'https://demo.com' 6 | }; 7 | 8 | export = BaseConfig; 9 | 10 | -------------------------------------------------------------------------------- /tools/env/dev.ts: -------------------------------------------------------------------------------- 1 | import { EnvConfig } from './env-config.interface'; 2 | 3 | const DevConfig: EnvConfig = { 4 | ENV: 'DEV' 5 | }; 6 | 7 | export = DevConfig; 8 | 9 | -------------------------------------------------------------------------------- /tools/env/env-config.interface.ts: -------------------------------------------------------------------------------- 1 | export { EnvConfig } from '../../src/client/app/shared/core/utils/config'; 2 | -------------------------------------------------------------------------------- /tools/env/prod.ts: -------------------------------------------------------------------------------- 1 | import { EnvConfig } from './env-config.interface'; 2 | 3 | const ProdConfig: EnvConfig = { 4 | ENV: 'PROD' 5 | }; 6 | 7 | export = ProdConfig; 8 | -------------------------------------------------------------------------------- /tools/manual_typings/project/sample.package.d.ts: -------------------------------------------------------------------------------- 1 | // declare module "moment/moment" { 2 | // export = moment; 3 | // } 4 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/autoprefixer.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'autoprefixer' { 2 | 3 | interface IOptions { 4 | browsers: string[]; 5 | } 6 | 7 | interface IAutoprefixer { 8 | (opts?: IOptions): NodeJS.ReadWriteStream; 9 | } 10 | 11 | const autoprefixer: IAutoprefixer; 12 | export = autoprefixer; 13 | } 14 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/cssnano.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'cssnano' { 2 | 3 | interface IOptions { 4 | discardComments?: { 5 | removeAll: boolean; 6 | }; 7 | discardUnused?: boolean; 8 | zindex?: boolean; 9 | reduceIdents?: boolean; 10 | } 11 | 12 | interface ICssnano { 13 | (opts?: IOptions): NodeJS.ReadWriteStream; 14 | } 15 | 16 | const cssnano: ICssnano; 17 | export = cssnano; 18 | } 19 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/express-history-api-fallback.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'express-history-api-fallback' { 2 | 3 | import { RequestHandler } from 'express'; 4 | 5 | interface IOptions { 6 | maxAge?: number; 7 | root?: string; 8 | lastModified?: number; 9 | headers?: { [key: string]: string; }; 10 | dotfiles?: boolean; 11 | } 12 | 13 | function fallback(index: string, options?: IOptions): RequestHandler; 14 | 15 | module fallback {} 16 | 17 | export = fallback; 18 | } 19 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/istream.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'isstream' { 2 | function istream(stream: any): boolean; 3 | interface Istream { 4 | isReadable(stream: any): boolean; 5 | isWritable(stream: any): boolean; 6 | isDuplex(stream: any): boolean; 7 | } 8 | module istream {} 9 | export = istream; 10 | } 11 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/karma.d.ts: -------------------------------------------------------------------------------- 1 | // Use this minimalistic definition file as bluebird dependency 2 | // generate a lot of errors. 3 | 4 | declare module 'karma' { 5 | var karma: IKarma; 6 | export = karma; 7 | interface IKarma { 8 | server: { 9 | start(options: any, callback: Function): void 10 | }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/merge-stream.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'merge-stream' { 2 | function mergeStream(...streams: NodeJS.ReadWriteStream[]): MergeStream; 3 | interface MergeStream extends NodeJS.ReadWriteStream { 4 | add(stream: NodeJS.ReadWriteStream): MergeStream; 5 | } 6 | module mergeStream {} 7 | export = mergeStream; 8 | } 9 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/open.d.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/borisyankov/DefinitelyTyped/tree/master/open 2 | // Does not support ES2015 import (import * as open from 'open'). 3 | 4 | declare module 'open' { 5 | function open(target: string, app?: string): void; 6 | module open {} 7 | export = open; 8 | } 9 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/operators.d.ts: -------------------------------------------------------------------------------- 1 | import '../../../src/client/app/operators'; 2 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/slash.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'slash' { 2 | function slash(path: string): string; 3 | module slash {} 4 | export = slash; 5 | } 6 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/systemjs-builder.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'systemjs-builder' { 2 | class Builder { 3 | constructor(configObject?: any, baseUrl?: string, configPath?: string); 4 | bundle(source: string, target: string, options?: any): Promise; 5 | buildStatic(source: string, target: string, options?: any): Promise; 6 | } 7 | 8 | module Builder {} 9 | export = Builder; 10 | } 11 | -------------------------------------------------------------------------------- /tools/manual_typings/seed/tildify.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tildify' { 2 | function tildify(path: string): string; 3 | module tildify {} 4 | export = tildify; 5 | } 6 | -------------------------------------------------------------------------------- /tools/tasks/assets_task.ts: -------------------------------------------------------------------------------- 1 | import { Task } from './task'; 2 | 3 | export abstract class AssetsTask extends Task { 4 | shallRun(files: String[]) { 5 | return files.reduce((a, f) => { 6 | return a || (!f.endsWith('.css') && !f.endsWith('.sass') && 7 | !f.endsWith('.scss') && !f.endsWith('.ts')); 8 | }, false); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tools/tasks/css_task.ts: -------------------------------------------------------------------------------- 1 | import { Task } from './task'; 2 | import Config from '../config'; 3 | 4 | export abstract class CssTask extends Task { 5 | 6 | shallRun(files: String[]) { 7 | return Config.ENABLE_SCSS || files.some(f => 8 | f.endsWith('.css') || f.endsWith('.sass') || f.endsWith('.scss')); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.build.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { join } from 'path'; 3 | var newer = require('gulp-newer'); 4 | 5 | import Config from '../../config'; 6 | 7 | export = () => { 8 | let src = [ 9 | join(Config.APP_SRC, 'package.json') 10 | ]; 11 | return gulp.src(src) 12 | .pipe(newer({ 13 | dest: Config.APP_DEST, 14 | map: function(path: String) { return path.replace('.ts', '.js').replace('.scss', '.css'); } 15 | })) 16 | .pipe(gulp.dest(Config.APP_DEST)); 17 | }; 18 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.libs.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { ExtendPackages } from '../../config/seed.config.interfaces'; 3 | import { relative, join } from 'path'; 4 | import Config from '../../config'; 5 | var newer = require('gulp-newer'); 6 | 7 | export = () => { 8 | let src = [ 9 | 'node_modules/@angular/**/*', 10 | 'node_modules/rxjs/**/*' 11 | ]; 12 | 13 | let additionalPkgs: ExtendPackages[] = Config.DESKTOP_PACKAGES; 14 | additionalPkgs.forEach((pkg) => { 15 | if (typeof(pkg.name) !== 'undefined') { 16 | src.push(`node_modules/${pkg.name}/**/*`); 17 | } 18 | }); 19 | 20 | src.push(...Config.NPM_DEPENDENCIES.map(x => relative(Config.PROJECT_ROOT, x.src))); 21 | 22 | return gulp.src(src, { base: 'node_modules' }) 23 | .pipe(newer({ 24 | dest: join(Config.APP_DEST + '/node_modules'), 25 | map: function (path: String) { return path.replace('.ts', '.js').replace('.scss', '.css'); } 26 | })) 27 | .pipe(gulp.dest(join(Config.APP_DEST + '/node_modules'))); 28 | }; 29 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.package.linux.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | var symdest = require('gulp-symdest'); 3 | var electron = require('gulp-atom-electron'); 4 | 5 | export = () => { 6 | let src = [ 7 | 'dist/dev/**/*' 8 | ]; 9 | return gulp.src(src, { base: 'dist/dev' }) 10 | .pipe(electron({ version: '0.37.2', platform: 'linux' })) 11 | .pipe(symdest('desktop/linux')); 12 | }; 13 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.package.mac.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | var symdest = require('gulp-symdest'); 3 | var electron = require('gulp-atom-electron'); 4 | 5 | export = () => { 6 | let src = [ 7 | 'dist/dev/**/*' 8 | ]; 9 | return gulp.src(src, { base: 'dist/dev' }) 10 | .pipe(electron({ version: '0.37.2', platform: 'darwin', darwinIcon: 'src/client/assets/logo.icns' })) 11 | .pipe(symdest('desktop/mac')); 12 | }; 13 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.package.windows.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | var symdest = require('gulp-symdest'); 3 | var electron = require('gulp-atom-electron'); 4 | 5 | export = () => { 6 | let src = [ 7 | 'dist/dev/**/*' 8 | ]; 9 | return gulp.src(src, { base: 'dist/dev' }) 10 | .pipe(electron({ version: '0.37.2', platform: 'win32', winIcon: 'src/client/assets/logo.ico' })) 11 | .pipe(symdest('desktop/windows')); 12 | }; 13 | -------------------------------------------------------------------------------- /tools/tasks/project/desktop.watch.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as runSequence from 'run-sequence'; 3 | 4 | const electron = require('electron-connect').server.create({ 'path': 'dist/dev' }); 5 | 6 | export = () => { 7 | electron.start(); 8 | gulp.watch(['./src/**/*'], reload); 9 | }; 10 | 11 | function reload() { 12 | runSequence('desktop', electron.reload); 13 | } 14 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.assets.dev.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { join } from 'path'; 3 | 4 | import { AssetsTask } from '../assets_task'; 5 | import Config from '../../config'; 6 | 7 | /** 8 | * Executes the build process, copying the assets located in `src/client` over to the appropriate 9 | * `dist/dev` directory. 10 | */ 11 | export = 12 | class BuildAssetsTask extends AssetsTask { 13 | run(done: any) { 14 | let paths: string[] = [ 15 | join(Config.APP_SRC, '**'), 16 | '!' + join(Config.APP_SRC, '**', '*.ts'), 17 | '!' + join(Config.APP_SRC, '**', '*.scss'), 18 | '!' + join(Config.APP_SRC, '**', '*.sass') 19 | ].concat(Config.TEMP_FILES.map((p) => { return '!' + p; })); 20 | 21 | return gulp.src(paths) 22 | .pipe(gulp.dest(Config.APP_DEST)); 23 | } 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.assets.prod.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { join } from 'path'; 3 | 4 | import Config from '../../config'; 5 | 6 | // TODO There should be more elegant to prevent empty directories from copying 7 | var onlyDirs = function (es: any) { 8 | return es.map(function (file: any, cb: any) { 9 | if (file.stat.isFile()) { 10 | return cb(null, file); 11 | } else { 12 | return cb(); 13 | } 14 | }); 15 | }; 16 | 17 | /** 18 | * Executes the build process, copying the assets located in `src/client` over to the appropriate 19 | * `dist/prod` directory. 20 | */ 21 | export = () => { 22 | let es: any = require('event-stream'); 23 | return gulp.src([ 24 | join(Config.APP_SRC, '**'), 25 | '!' + join(Config.APP_SRC, 'tsconfig.json'), 26 | '!' + join(Config.APP_SRC, '**', '*.ts'), 27 | '!' + join(Config.APP_SRC, '**', '*.css'), 28 | '!' + join(Config.APP_SRC, '**', '*.html'), 29 | '!' + join(Config.APP_SRC, '**', '*.scss'), 30 | '!' + join(Config.APP_SRC, '**', '*.sass'), 31 | '!' + join(Config.ASSETS_SRC, '**', '*.js') 32 | ].concat(Config.TEMP_FILES.map((p) => { return '!' + p; }))) 33 | .pipe(onlyDirs(es)) 34 | .pipe(gulp.dest(Config.APP_DEST)); 35 | }; 36 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.assets.tns.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as merge from 'merge-stream'; 3 | import { join } from 'path'; 4 | import * as newer from 'gulp-newer'; 5 | 6 | import { AssetsTask } from '../assets_task'; 7 | import Config from '../../config'; 8 | 9 | function copyFiles(paths: string[], subdir: string) { 10 | const dest = join(Config.TNS_APP_DEST, subdir); 11 | 12 | return gulp.src(paths) 13 | .pipe(newer(dest)) 14 | .pipe(gulp.dest(dest)); 15 | } 16 | 17 | function copyAssets() { 18 | const paths: string[] = [ 19 | join(Config.APP_SRC, 'assets', '**'), 20 | '!' + join(Config.APP_SRC, 'assets', 'icons', '**', '*'), 21 | ].concat(Config.TEMP_FILES.map((p) => { return '!' + p; })); 22 | 23 | return copyFiles(paths, 'assets'); 24 | } 25 | 26 | function copyAppResources() { 27 | const paths: string[] = [ 28 | join(Config.TNS_APP_SRC, 'App_Resources', '**'), 29 | ]; 30 | 31 | return copyFiles(paths, 'App_Resources'); 32 | } 33 | 34 | function copyAppFonts() { 35 | const paths: string[] = [ 36 | join(Config.TNS_APP_SRC, 'fonts', '**', '*.otf'), 37 | join(Config.TNS_APP_SRC, 'fonts', '**', '*.ttf'), 38 | ]; 39 | 40 | return copyFiles(paths, 'fonts'); 41 | } 42 | 43 | export = 44 | class BuildTNSAssetsTask extends AssetsTask { 45 | run() { 46 | return merge( 47 | copyAssets(), 48 | copyAppResources(), 49 | copyAppFonts(), 50 | copyFiles([join(Config.TNS_APP_SRC, 'package.json')], ''), 51 | ); 52 | } 53 | }; 54 | 55 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.bundle.rxjs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Temporary fix. See https://github.com/angular/angular/issues/9359 3 | */ 4 | 5 | const Builder = require('systemjs-builder'); 6 | 7 | export = (done: any) => { 8 | const options = { 9 | normalize: true, 10 | runtime: false, 11 | sourceMaps: true, 12 | sourceMapContents: true, 13 | minify: true, 14 | mangle: false 15 | }; 16 | var builder = new Builder('./'); 17 | builder.config({ 18 | paths: { 19 | 'n:*': 'node_modules/*', 20 | 'rxjs/*': 'node_modules/rxjs/*.js', 21 | }, 22 | map: { 23 | 'rxjs': 'n:rxjs', 24 | }, 25 | packages: { 26 | 'rxjs': {main: 'Rx.js', defaultExtension: 'js'}, 27 | } 28 | }); 29 | builder.bundle('rxjs', 'node_modules/.tmp/Rx.min.js', options) 30 | .then(() => done()) 31 | .catch((error:any) => done(error)); 32 | }; 33 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.bundles.app.aot.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import * as Builder from 'systemjs-builder'; 3 | 4 | import Config from '../../config'; 5 | 6 | const BUNDLER_OPTIONS = { 7 | format: 'cjs', 8 | minify: true, 9 | mangle: false 10 | }; 11 | 12 | /** 13 | * Executes the build process, bundling the JavaScript files using the SystemJS builder. 14 | */ 15 | export = (done: any) => { 16 | let builder = new Builder(Config.SYSTEM_BUILDER_CONFIG); 17 | builder 18 | .buildStatic(join(Config.TMP_DIR, Config.BOOTSTRAP_FACTORY_PROD_MODULE), 19 | join(Config.JS_DEST, Config.JS_PROD_APP_BUNDLE), 20 | BUNDLER_OPTIONS) 21 | .then(() => done()) 22 | .catch((err: any) => done(err)); 23 | }; 24 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.bundles.app.rollup.aot.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { writeFile } from 'fs'; 3 | import { join } from 'path'; 4 | 5 | const nodeResolve = require('rollup-plugin-node-resolve'); 6 | const commonjs = require('rollup-plugin-commonjs'); 7 | const includePaths = require('rollup-plugin-includepaths'); 8 | const rollup = require('rollup'); 9 | 10 | const config = { 11 | entry: join(Config.TMP_DIR, Config.BOOTSTRAP_FACTORY_PROD_MODULE), 12 | sourceMap: true, 13 | treeshake: true, 14 | moduleName: 'main', 15 | plugins: [ 16 | includePaths({ 17 | include: {}, 18 | paths: [join(Config.TMP_DIR, 'app')], 19 | external: [], 20 | extensions: ['.js', '.json', '.html', '.ts'] 21 | }), 22 | nodeResolve({ 23 | jsnext: true, main: true, module: true 24 | }), 25 | commonjs({ 26 | include: 'node_modules/**', 27 | namedExports: { 28 | // 'node_modules/immutable/dist/immutable.js': [ 'Map', 'Set', 'List', 'fromJS' ], 29 | // 'node_modules/ng2-dragula/ng2-dragula.js': [ 'DragulaModule', 'DragulaService' ] 30 | } 31 | }) 32 | ] 33 | }; 34 | 35 | 36 | export = (done: any) => { 37 | rollup.rollup(config) 38 | .then((bundle: any) => { 39 | const result = bundle.generate({ 40 | format: 'iife' 41 | }); 42 | const path = join(Config.TMP_DIR, 'bundle.js'); 43 | writeFile(path, result.code, (error: any) => { 44 | if (error) { 45 | console.error(error); 46 | process.exit(0); 47 | } 48 | done(); 49 | }); 50 | }) 51 | .catch((error: any) => { 52 | console.error(error); 53 | process.exit(0); 54 | }); 55 | }; 56 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.bundles.app.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import * as Builder from 'systemjs-builder'; 3 | 4 | import Config from '../../config'; 5 | 6 | const BUNDLER_OPTIONS = { 7 | format: 'cjs', 8 | minify: true, 9 | mangle: false 10 | }; 11 | 12 | /** 13 | * Executes the build process, bundling the JavaScript files using the SystemJS builder. 14 | */ 15 | export = (done: any) => { 16 | let builder = new Builder(Config.SYSTEM_BUILDER_CONFIG); 17 | builder 18 | .buildStatic(join(Config.TMP_DIR, Config.BOOTSTRAP_PROD_MODULE), 19 | join(Config.JS_DEST, Config.JS_PROD_APP_BUNDLE), 20 | BUNDLER_OPTIONS) 21 | .then(() => done()) 22 | .catch((err: any) => done(err)); 23 | }; 24 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.bundles.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import * as merge from 'merge-stream'; 4 | 5 | import Config from '../../config'; 6 | 7 | const plugins = gulpLoadPlugins(); 8 | 9 | /** 10 | * Executes the build process, bundling the shim files. 11 | */ 12 | export = () => merge(bundleShims()); 13 | 14 | /** 15 | * Returns the shim files to be injected. 16 | */ 17 | function getShims() { 18 | let libs = Config.DEPENDENCIES 19 | .filter(d => /\.js$/.test(d.src)); 20 | 21 | return libs.filter(l => l.inject === 'shims') 22 | .concat(libs.filter(l => l.inject === 'libs')) 23 | .concat(libs.filter(l => l.inject === true)) 24 | .map(l => l.src); 25 | } 26 | 27 | /** 28 | * Bundles the shim files. 29 | */ 30 | function bundleShims() { 31 | return gulp.src(getShims()) 32 | .pipe(plugins.concat(Config.JS_PROD_SHIMS_BUNDLE)) 33 | // Strip the first (global) 'use strict' added by reflect-metadata, but don't strip any others to avoid unintended scope leaks. 34 | .pipe(plugins.replace(/('|")use strict\1;var Reflect;/, 'var Reflect;')) 35 | .pipe(gulp.dest(Config.JS_DEST)); 36 | } 37 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.docs.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | 7 | const plugins = gulpLoadPlugins(); 8 | 9 | /** 10 | * Executes the build process, building the documentation for the TypeScript 11 | * files (excluding spec and e2e-spec files) using `typedoc`. 12 | */ 13 | export = () => { 14 | 15 | let src = [ 16 | 'typings/index.d.ts', 17 | join(Config.APP_SRC, '**/*.ts'), 18 | '!' + join(Config.APP_SRC, '**/*.spec.ts'), 19 | '!' + join(Config.APP_SRC, '**/*.e2e-spec.ts') 20 | ]; 21 | 22 | return gulp.src(src) 23 | .pipe(plugins.typedoc({ 24 | // TypeScript options (see typescript docs) 25 | module: 'commonjs', 26 | target: 'es5', 27 | excludeExternals: true, 28 | includeDeclarations: true, 29 | // Output options (see typedoc docs) 30 | out: Config.DOCS_DEST, 31 | json: join(Config.DOCS_DEST, 'data/docs.json'), 32 | name: Config.APP_TITLE, 33 | ignoreCompilerErrors: false, 34 | experimentalDecorators: true, 35 | version: true 36 | })); 37 | }; 38 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.index.dev.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | import * as slash from 'slash'; 5 | 6 | import Config from '../../config'; 7 | import { TemplateLocalsBuilder } from '../../utils'; 8 | 9 | const plugins = gulpLoadPlugins(); 10 | 11 | 12 | /** 13 | * Executes the build process, injecting the shims and libs into the `index.hml` for the development environment. 14 | */ 15 | export = () => { 16 | return gulp.src(join(Config.APP_SRC, 'index.html')) 17 | .pipe(inject('shims')) 18 | .pipe(inject('libs')) 19 | .pipe(inject()) 20 | .pipe(plugins.template(new TemplateLocalsBuilder().wihtoutStringifiedEnvConfig().build())) 21 | .pipe(gulp.dest(Config.APP_DEST)); 22 | }; 23 | 24 | /** 25 | * Injects the file with the given name. 26 | * @param {string} name - The file to be injected. 27 | */ 28 | function inject(name?: string) { 29 | return plugins.inject(gulp.src(getInjectablesDependenciesRef(name), { read: false }), { 30 | name, 31 | transform: transformPath() 32 | }); 33 | } 34 | 35 | /** 36 | * Returns the injectable dependency, mapping its filename to its path. 37 | * @param {string} name - The dependency to be mapped. 38 | */ 39 | function getInjectablesDependenciesRef(name?: string) { 40 | return Config.DEPENDENCIES 41 | .filter(dep => dep['inject'] && dep['inject'] === (name || true)) 42 | .map(mapPath); 43 | } 44 | 45 | /** 46 | * Maps the path of the given dependency to its path according to the applications environment. 47 | * @param {any} dep - The dependency to be mapped. 48 | */ 49 | function mapPath(dep: any) { 50 | let envPath = dep.src; 51 | if (envPath.startsWith(Config.APP_SRC) && !envPath.endsWith('.scss')) { 52 | envPath = join(Config.APP_DEST, envPath.replace(Config.APP_SRC, '')); 53 | } else if (envPath.startsWith(Config.APP_SRC) && envPath.endsWith('.scss')) { 54 | envPath = envPath.replace(Config.ASSETS_SRC, Config.CSS_DEST).replace('.scss', '.css'); 55 | } 56 | return envPath; 57 | } 58 | 59 | /** 60 | * Transform the path of a dependency to its location within the `dist` directory according to the applications 61 | * environment. 62 | */ 63 | function transformPath() { 64 | return function (filepath: string) { 65 | if (filepath.startsWith(`/${Config.APP_DEST}`)) { 66 | filepath = filepath.replace(`/${Config.APP_DEST}`, ''); 67 | } 68 | if (Config.TARGET_DESKTOP) { 69 | let path = join(Config.APP_BASE, filepath); 70 | if (path.indexOf('dist/dev') > -1 || path.indexOf('dist\\dev') > -1) { 71 | path = path.replace(/(dist\/dev\/)|(dist\\dev\\)/g, ''); 72 | } 73 | arguments[0] = path.substring(1) + `?${Date.now()}`; 74 | } else { 75 | arguments[0] = join(Config.APP_BASE, filepath) + `?${Date.now()}`; 76 | } 77 | return slash(plugins.inject.transform.apply(plugins.inject.transform, arguments)); 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.index.prod.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join, sep, normalize } from 'path'; 4 | import * as slash from 'slash'; 5 | 6 | import Config from '../../config'; 7 | import { TemplateLocalsBuilder } from '../../utils'; 8 | 9 | const plugins = gulpLoadPlugins(); 10 | 11 | /** 12 | * Executes the build process, injecting the JavaScript and CSS dependencies into the `index.html` for the production 13 | * environment. 14 | */ 15 | export = () => { 16 | return gulp.src(join(Config.APP_SRC, 'index.html')) 17 | .pipe(injectJs()) 18 | .pipe(injectCss()) 19 | .pipe(plugins.template(new TemplateLocalsBuilder().wihtoutStringifiedEnvConfig().build())) 20 | .pipe(gulp.dest(Config.APP_DEST)); 21 | }; 22 | 23 | /** 24 | * Injects the given file array and transforms the path of the files. 25 | * @param {Array} files - The files to be injected. 26 | */ 27 | function inject(...files: Array) { 28 | return plugins.inject(gulp.src(files, { read: false }), { 29 | files, 30 | transform: transformPath() 31 | }); 32 | } 33 | 34 | /** 35 | * Injects the bundled JavaScript shims and application bundles for the production environment. 36 | */ 37 | function injectJs() { 38 | return inject(join(Config.JS_DEST, Config.JS_PROD_SHIMS_BUNDLE), join(Config.JS_DEST, Config.JS_PROD_APP_BUNDLE)); 39 | } 40 | 41 | /** 42 | * Injects the bundled CSS files for the production environment. 43 | */ 44 | function injectCss() { 45 | return inject(join(Config.CSS_DEST, Config.CSS_PROD_BUNDLE)); 46 | } 47 | 48 | /** 49 | * Transform the path of a dependency to its location within the `dist` directory according to the applications 50 | * environment. 51 | */ 52 | function transformPath() { 53 | return function(filepath: string) { 54 | let path: Array = normalize(filepath).split(sep); 55 | let slice_after = path.indexOf(Config.APP_DEST); 56 | if (slice_after > -1) { 57 | slice_after++; 58 | } else { 59 | slice_after = 3; 60 | } 61 | arguments[0] = Config.APP_BASE + path.slice(slice_after, path.length).join(sep) + `?${Date.now()}`; 62 | return slash(plugins.inject.transform.apply(plugins.inject.transform, arguments)); 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.dev.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import * as merge from 'merge-stream'; 4 | import * as util from 'gulp-util'; 5 | import { join/*, sep, relative*/ } from 'path'; 6 | 7 | import Config from '../../config'; 8 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 9 | import { TypeScriptTask } from '../typescript_task'; 10 | 11 | const plugins = gulpLoadPlugins(); 12 | 13 | let typedBuildCounter = Config.TYPED_COMPILE_INTERVAL; // Always start with the typed build. 14 | 15 | /** 16 | * Executes the build process, transpiling the TypeScript files (except the spec and e2e-spec files) for the development 17 | * environment. 18 | */ 19 | export = 20 | class BuildJsDev extends TypeScriptTask { 21 | run() { 22 | let tsProject: any; 23 | let typings = gulp.src([ 24 | Config.TOOLS_DIR + '/manual_typings/**/*.d.ts' 25 | ]); 26 | let src = [ 27 | join(Config.APP_SRC, '**/*.ts'), 28 | '!' + join(Config.APP_SRC, '**/*.spec.ts'), 29 | '!' + join(Config.APP_SRC, '**/*.e2e-spec.ts'), 30 | '!' + join(Config.APP_SRC, `**/${Config.NG_FACTORY_FILE}.ts`) 31 | ]; 32 | 33 | let projectFiles = gulp.src(src); 34 | let result: any; 35 | let isFullCompile = true; 36 | 37 | // Only do a typed build every X builds, otherwise do a typeless build to speed things up 38 | if (typedBuildCounter < Config.TYPED_COMPILE_INTERVAL) { 39 | isFullCompile = false; 40 | tsProject = makeTsProject({ isolatedModules: true }); 41 | projectFiles = projectFiles.pipe(plugins.cached()); 42 | util.log('Performing typeless TypeScript compile.'); 43 | } else { 44 | tsProject = makeTsProject(); 45 | projectFiles = merge(typings, projectFiles); 46 | } 47 | 48 | result = projectFiles 49 | .pipe(plugins.plumber()) 50 | .pipe(plugins.sourcemaps.init()) 51 | .pipe(tsProject()) 52 | .on('error', () => { 53 | typedBuildCounter = Config.TYPED_COMPILE_INTERVAL; 54 | }); 55 | 56 | if (isFullCompile) { 57 | typedBuildCounter = 0; 58 | } else { 59 | typedBuildCounter++; 60 | } 61 | 62 | return result.js 63 | .pipe(plugins.sourcemaps.write()) 64 | // Use for debugging with Webstorm/IntelliJ 65 | // https://github.com/mgechev/angular-seed/issues/1220 66 | // .pipe(plugins.sourcemaps.write('.', { 67 | // includeContent: false, 68 | // sourceRoot: (file: any) => 69 | // relative(file.path, Config.PROJECT_ROOT + '/' + Config.APP_SRC).replace(sep, '/') + '/' + Config.APP_SRC 70 | // })) 71 | .pipe(plugins.template(new TemplateLocalsBuilder().withStringifiedSystemConfigDev().build())) 72 | .pipe(gulp.dest(Config.APP_DEST)); 73 | } 74 | }; 75 | 76 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.e2e.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | /** 11 | * Executes the build process, transpiling the TypeScript files (including the e2e-spec files, excluding the spec files) 12 | * for the e2e environment. 13 | */ 14 | export = () => { 15 | let tsProject = makeTsProject({ 'target': 'es2015' }, Config.E2E_SRC); 16 | let src = [ 17 | Config.TOOLS_DIR + '/manual_typings/**/*.d.ts', 18 | join(Config.E2E_SRC, '**/*.ts') 19 | ]; 20 | let result = gulp.src(src) 21 | .pipe(plugins.plumber()) 22 | .pipe(plugins.sourcemaps.init()) 23 | .pipe(tsProject()); 24 | 25 | return result.js 26 | .pipe(plugins.sourcemaps.write()) 27 | .pipe(plugins.template(new TemplateLocalsBuilder().withStringifiedSystemConfigDev().build())) 28 | .pipe(gulp.dest(Config.E2E_DEST)); 29 | }; 30 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.prod.aot.ts: -------------------------------------------------------------------------------- 1 | import { readdirSync, lstatSync } from 'fs'; 2 | import * as gulp from 'gulp'; 3 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 4 | import { join } from 'path'; 5 | 6 | import Config from '../../config'; 7 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 8 | 9 | const plugins = gulpLoadPlugins(); 10 | 11 | /** 12 | * Executes the build process, transpiling the TypeScript files for the production environment. 13 | */ 14 | 15 | export = () => { 16 | let tsProject = makeTsProject({}, Config.TMP_DIR); 17 | let toIgnore = readdirSync(Config.TMP_DIR).filter((f: string) => 18 | lstatSync(join(Config.TMP_DIR, f)).isDirectory() && f !== Config.BOOTSTRAP_DIR) 19 | .map((f: string) => '!' + join(Config.TMP_DIR, f, Config.NG_FACTORY_FILE + '.ts')); 20 | 21 | let src = [ 22 | Config.TOOLS_DIR + '/manual_typings/**/*.d.ts', 23 | join(Config.TMP_DIR, '**/*.ts'), 24 | join(Config.TMP_DIR, `${Config.BOOTSTRAP_FACTORY_PROD_MODULE}.ts`), 25 | ...toIgnore 26 | ]; 27 | let result = gulp.src(src) 28 | .pipe(plugins.plumber()) 29 | .pipe(tsProject()) 30 | .once('error', function(e: any) { 31 | this.once('finish', () => process.exit(1)); 32 | }); 33 | 34 | return result.js 35 | .pipe(plugins.template(new TemplateLocalsBuilder().build())) 36 | .pipe(gulp.dest(Config.TMP_DIR)) 37 | .on('error', (e: any) => { 38 | console.log(e); 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.prod.rollup.aot.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | /** 11 | * Executes the build process, transpiling the TypeScript files for the production environment. 12 | */ 13 | 14 | export = () => { 15 | const tsProject = makeTsProject({ 16 | target: 'es2015', 17 | module: 'es2015', 18 | moduleResolution: 'node' 19 | }, Config.TMP_DIR); 20 | const src = [ 21 | join(Config.TOOLS_DIR, '/manual_typings/**/*.d.ts'), 22 | join(Config.TMP_DIR, '**/*.ts') 23 | ]; 24 | const result = gulp.src(src) 25 | .pipe(plugins.plumber()) 26 | .pipe(tsProject()) 27 | .once('error', () => { 28 | this.once('finish', () => process.exit(1)); 29 | }); 30 | 31 | return result.js 32 | .pipe(plugins.template(new TemplateLocalsBuilder().build(), {interpolate: /<%=([\s\S]+?)%>/g})) 33 | .pipe(gulp.dest(Config.TMP_DIR)) 34 | .on('error', (e: any) => { 35 | console.log(e); 36 | }); 37 | }; 38 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.prod.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | const INLINE_OPTIONS = { 11 | base: Config.TMP_DIR, 12 | target: 'es5', 13 | useRelativePaths: true, 14 | removeLineBreaks: true 15 | }; 16 | 17 | /** 18 | * Executes the build process, transpiling the TypeScript files for the production environment. 19 | */ 20 | 21 | export = () => { 22 | let tsProject = makeTsProject({}, Config.TMP_DIR); 23 | let src = [ 24 | Config.TOOLS_DIR + '/manual_typings/**/*.d.ts', 25 | join(Config.TMP_DIR, '**/*.ts'), 26 | '!' + join(Config.TMP_DIR, `**/${Config.NG_FACTORY_FILE}.ts`) 27 | ]; 28 | let result = gulp.src(src) 29 | .pipe(plugins.plumber()) 30 | .pipe(plugins.inlineNg2Template(INLINE_OPTIONS)) 31 | .pipe(tsProject()) 32 | .once('error', function(e: any) { 33 | this.once('finish', () => process.exit(1)); 34 | }); 35 | 36 | 37 | return result.js 38 | .pipe(plugins.template(new TemplateLocalsBuilder().build())) 39 | .pipe(gulp.dest(Config.TMP_DIR)) 40 | .on('error', (e: any) => { 41 | console.log(e); 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.test.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import * as gulp from 'gulp'; 3 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 4 | import * as merge from 'merge-stream'; 5 | import * as util from 'gulp-util'; 6 | import { join } from 'path'; 7 | 8 | import Config from '../../config'; 9 | import { makeTsProject } from '../../utils'; 10 | import { TypeScriptTask } from '../typescript_task'; 11 | 12 | const plugins = gulpLoadPlugins(); 13 | 14 | let typedBuildCounter = Config.TYPED_COMPILE_INTERVAL; // Always start with the typed build. 15 | 16 | /** 17 | * Executes the build process, transpiling the TypeScript files (excluding the spec and e2e-spec files) for the test 18 | * environment. 19 | */ 20 | export = 21 | class BuildJsTest extends TypeScriptTask { 22 | run() { 23 | let tsProject: any; 24 | let typings = gulp.src( [ 25 | Config.TOOLS_DIR + '/manual_typings/**/*.d.ts' 26 | ] ); 27 | let src = [ 28 | join(Config.APP_SRC, '**/*.spec.ts') 29 | ]; 30 | 31 | let projectFiles = gulp.src(src); 32 | let result: any; 33 | let isFullCompile = true; 34 | 35 | // Only do a typed build every X builds, otherwise do a typeless build to speed things up 36 | if (typedBuildCounter < Config.TYPED_COMPILE_INTERVAL) { 37 | isFullCompile = false; 38 | tsProject = makeTsProject({isolatedModules: true}); 39 | projectFiles = projectFiles.pipe(plugins.cached()); 40 | util.log('Performing typeless TypeScript compile of specs.'); 41 | } else { 42 | tsProject = makeTsProject(); 43 | projectFiles = merge(typings, projectFiles); 44 | } 45 | 46 | //noinspection TypeScriptUnresolvedFunction 47 | result = projectFiles 48 | .pipe(plugins.plumber()) 49 | .pipe(plugins.sourcemaps.init()) 50 | .pipe(tsProject()) 51 | .on('error', () => { 52 | typedBuildCounter = Config.TYPED_COMPILE_INTERVAL; 53 | }); 54 | 55 | if (isFullCompile) { 56 | typedBuildCounter = 0; 57 | } else { 58 | typedBuildCounter++; 59 | } 60 | 61 | return result.js 62 | .pipe(plugins.sourcemaps.write()) 63 | // Use for debugging with Webstorm/IntelliJ 64 | // https://github.com/mgechev/angular-seed/issues/1220 65 | // .pipe(plugins.sourcemaps.write('.', { 66 | // includeContent: false, 67 | // sourceRoot: (file: any) => 68 | // relative(file.path, PROJECT_ROOT + '/' + APP_SRC).replace(sep, '/') + '/' + APP_SRC 69 | // })) 70 | .pipe(gulp.dest(Config.APP_DEST)); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.js.tns.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import * as merge from 'merge-stream'; 4 | import * as fs from 'fs'; 5 | import * as path from 'path'; 6 | 7 | import Config from '../../config'; 8 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 9 | import { TypeScriptTask } from '../typescript_task'; 10 | 11 | const plugins = gulpLoadPlugins(); 12 | 13 | const jsonSystemConfig = JSON.stringify(Config.TNS_CONFIG); 14 | 15 | /** 16 | * Executes the build process, transpiling the TypeScript files (except the spec and e2e-spec files) for the development 17 | * environment. 18 | */ 19 | export = 20 | class BuildJsDev extends TypeScriptTask { 21 | run() { 22 | const src = [ 23 | '**/*.ts', 24 | 'app/**/*.ts', 25 | '!**/*.spec.ts', 26 | '!app/**/*.spec.ts', 27 | '!**/*.e2e-spec.ts', 28 | '!app/**/*.e2e-spec.ts', 29 | '!app/shared/test/**/*', 30 | `!**/${Config.NG_FACTORY_FILE}.ts`, 31 | ]; 32 | 33 | const tsProject = makeTsProject({}, Config.TNS_APP_SRC); 34 | 35 | const result = gulp.src([ 36 | ...src, 37 | '!**/*.aot.ts', 38 | ], { 39 | base: Config.TNS_APP_SRC, 40 | cwd: Config.TNS_APP_SRC, 41 | }) 42 | .pipe(plugins.sourcemaps.init()) 43 | .pipe(tsProject()); 44 | 45 | const template = (Object).assign( 46 | new TemplateLocalsBuilder().withStringifiedSystemConfigDev().build(), { 47 | SYSTEM_CONFIG_TNS: jsonSystemConfig 48 | }, 49 | ); 50 | 51 | const transpiled = result.js 52 | .pipe(plugins.sourcemaps.write()) 53 | // Use for debugging with Webstorm/IntelliJ 54 | // https://github.com/mgechev/angular-seed/issues/1220 55 | // .pipe(plugins.sourcemaps.write('.', { 56 | // includeContent: false, 57 | // sourceRoot: (file: any) => 58 | // relative(file.path, PROJECT_ROOT + '/' + APP_SRC).replace(sep, '/') + '/' + APP_SRC 59 | // })) 60 | .pipe(plugins.template(template)) 61 | .pipe(gulp.dest(Config.TNS_APP_DEST)); 62 | 63 | const copy = gulp.src(src, { 64 | base: Config.TNS_APP_SRC, 65 | cwd: Config.TNS_APP_SRC, 66 | }) 67 | .pipe(gulp.dest(Config.TNS_APP_DEST)); 68 | 69 | fs.writeFileSync(path.join(Config.TNS_APP_DEST, 'build-config.json'), JSON.stringify(template)); 70 | 71 | return merge(transpiled, copy); 72 | } 73 | }; 74 | 75 | 76 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.tns_html_css.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import * as merge from 'merge-stream'; 4 | import * as util from 'gulp-util'; 5 | import * as rename from 'gulp-rename'; 6 | 7 | import Config from '../../config'; 8 | import { CssTask } from '../css_task'; 9 | 10 | const plugins = gulpLoadPlugins(); 11 | const reportPostCssError = (e: any) => util.log(util.colors.red(e.message)); 12 | 13 | function renamer() { 14 | return rename((path: any) => { 15 | path.basename = path.basename.replace(/\.tns/, ''); 16 | }); 17 | } 18 | 19 | function prepareTemplates() { 20 | return gulp.src([ 21 | '**/*.html', 22 | 'app/**/*.html', 23 | '!app/**/*.component.html', 24 | ], { 25 | base: Config.TNS_APP_SRC, 26 | cwd: Config.TNS_APP_SRC, 27 | }) 28 | .pipe(renamer()) 29 | .pipe(gulp.dest(Config.TNS_APP_DEST)); 30 | } 31 | 32 | function processComponentStylesheets() { 33 | return Config.ENABLE_SCSS ? 34 | merge( 35 | processComponentScss(), 36 | processComponentCss()) 37 | : 38 | processComponentCss(); 39 | } 40 | 41 | function processComponentCss() { 42 | return gulp.src([ 43 | '**/*.css', 44 | 'app/**/*.css', 45 | '!app/**/*.component.css', 46 | ], { 47 | base: Config.TNS_APP_SRC, 48 | cwd: Config.TNS_APP_SRC, 49 | }) 50 | .pipe(renamer()) 51 | .on('error', reportPostCssError) 52 | .pipe(gulp.dest(Config.TNS_APP_DEST)); 53 | } 54 | 55 | /** 56 | * Process scss files referenced from Angular component `styleUrls` metadata 57 | */ 58 | function processComponentScss() { 59 | const stream = gulp.src([ 60 | '**/*.scss', 61 | 'app/**/*.scss', 62 | '!app/**/*.component.scss', 63 | ], { 64 | base: Config.TNS_APP_SRC, 65 | cwd: Config.TNS_APP_SRC, 66 | }) 67 | .pipe(plugins.sourcemaps.init()) 68 | .pipe(plugins.sass(Config.getPluginConfig('gulp-sass-tns')).on('error', plugins.sass.logError)) 69 | .pipe(plugins.sourcemaps.write()); 70 | 71 | return stream 72 | .pipe(renamer()) 73 | .pipe(gulp.dest(Config.TNS_APP_DEST)); 74 | } 75 | 76 | function handlePlatformSpecificFiles() { 77 | // Make a copy of platform specific files were ext is swapped with platform-name 78 | // This is to support both our webpack --bundle and livesync builds 79 | const platformRegexp = /(\.ios|\.android)/; 80 | 81 | return gulp.src([ 82 | '**/*.ios.css', 83 | '**/*.ios.html', 84 | '**/*.ios.js', 85 | 86 | '**/*.android.css', 87 | '**/*.android.html', 88 | '**/*.android.js', 89 | ], { 90 | base: Config.TNS_APP_DEST, 91 | cwd: Config.TNS_APP_DEST, 92 | }) 93 | .pipe(rename((path) => { 94 | const match = path.basename.match(platformRegexp); 95 | if (match) { 96 | const oldExt = path.extname; 97 | path.extname = match[1]; 98 | path.basename = path.basename.replace(platformRegexp, oldExt); 99 | } 100 | })) 101 | .pipe(gulp.dest((Config.TNS_APP_DEST))); 102 | } 103 | 104 | export = 105 | class BuildTNSCSS extends CssTask { 106 | shallRun(files: String[]) { 107 | // Only run if tns-resources 108 | return files.some((f) => 109 | // tns.html, tns.scss or tns.css under nativescript/src/app 110 | (f.indexOf('nativescript/src/app') !== -1 && !!f.match(/\.tns\.(s?css|html)$/)) || 111 | // .html, .scss or .css NOT under nativescript/src/app 112 | (f.indexOf('nativescript/src/app') === -1 && !!f.match(/\.(s?css|html)$/)) 113 | ); 114 | } 115 | 116 | run() { 117 | return merge(processComponentStylesheets(), prepareTemplates()).on('end', () => handlePlatformSpecificFiles()); 118 | } 119 | }; 120 | 121 | -------------------------------------------------------------------------------- /tools/tasks/seed/build.tools.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | import { makeTsProject, TemplateLocalsBuilder } from '../../utils'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | /** 11 | * Executes the build process, transpiling the TypeScript files within the `tools` directory. 12 | */ 13 | export = () => { 14 | 15 | let tsProject = makeTsProject(); 16 | 17 | let src = [ 18 | join(Config.PROJECT_ROOT, 'gulpfile.ts'), 19 | join(Config.TOOLS_DIR, 'manual_typings/**/*.d.ts'), 20 | join(Config.TOOLS_DIR, '**/*.ts') 21 | ]; 22 | let result = gulp.src(src, { base: './' }) 23 | .pipe(plugins.plumber()) 24 | .pipe(plugins.sourcemaps.init()) 25 | .pipe(tsProject()); 26 | 27 | return result.js 28 | .pipe(plugins.template(new TemplateLocalsBuilder().build())) 29 | .pipe(plugins.sourcemaps.write()) 30 | .pipe(gulp.dest('./')); 31 | }; 32 | -------------------------------------------------------------------------------- /tools/tasks/seed/check.tools.ts: -------------------------------------------------------------------------------- 1 | import * as util from 'gulp-util'; 2 | import { join } from 'path'; 3 | 4 | let fs = require('fs'); 5 | 6 | 7 | // if gulpfile.ts has been compiled then we need to rebuild the toolchain 8 | 9 | export = (done: any) => { 10 | 11 | let checkFile = join(process.cwd(), 'tools', 'config.js'); 12 | 13 | // need to require the build.toolchain task as it won't be able to run after we run clear.files 14 | let buildTools = require('./build.tools'); 15 | let cleanTools = require('./clean.tools'); 16 | 17 | let rebuild = false; 18 | 19 | try { 20 | fs.accessSync(checkFile, fs.F_OK); 21 | util.log('Gulpfile has previously been compiled, rebuilding toolchain'); 22 | rebuild = true; 23 | 24 | } catch (e) { 25 | util.log('Tools not compiled, skipping rebuild'); 26 | done(); 27 | } 28 | 29 | // continue here to prevent other errors being caught... 30 | if (rebuild) { 31 | util.log('Running \'clean.tools\' from check.tools'); 32 | cleanTools(); 33 | 34 | util.log('Running \'build.tools\' from check.tools'); 35 | let build = buildTools(); 36 | 37 | build.on('end', done); 38 | 39 | } 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /tools/tasks/seed/check.versions.ts: -------------------------------------------------------------------------------- 1 | import * as util from 'gulp-util'; 2 | import Config from '../../config'; 3 | 4 | function reportError(message: string) { 5 | console.error(util.colors.white.bgRed.bold(message)); 6 | process.exit(1); 7 | } 8 | 9 | /** 10 | * Executes the build process, verifying that the installed NodeJS and NPM version matches the required versions as 11 | * defined in the application configuration. 12 | */ 13 | export = () => { 14 | let exec = require('child_process').exec; 15 | let semver = require('semver'); 16 | 17 | exec('npm --version', 18 | function(error: Error, stdout: NodeBuffer, stderr: NodeBuffer) { 19 | if (error !== null) { 20 | reportError('npm preinstall error: ' + error + stderr); 21 | } 22 | 23 | if (!semver.gte(stdout, Config.VERSION_NPM)) { 24 | reportError('NPM is not in required version! Required is ' + Config.VERSION_NPM + ' and you\'re using ' + stdout); 25 | } 26 | }); 27 | 28 | exec('node --version', 29 | function(error: Error, stdout: NodeBuffer, stderr: NodeBuffer) { 30 | if (error !== null) { 31 | reportError('npm preinstall error: ' + error + stderr); 32 | } 33 | 34 | if (!semver.gte(stdout, Config.VERSION_NODE)) { 35 | reportError('NODE is not in required version! Required is ' + Config.VERSION_NODE + ' and you\'re using ' + stdout); 36 | } 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.all.src.js.ts: -------------------------------------------------------------------------------- 1 | import * as chalk from 'chalk'; 2 | import { lstatSync, readdirSync } from 'fs'; 3 | import * as util from 'gulp-util'; 4 | import * as rimraf from 'rimraf'; 5 | import { join } from 'path'; 6 | 7 | import Config from '../../config'; 8 | 9 | /** 10 | * Executes the build process, deleting all JavaScript and Source Map files (which were transpiled from the TypeScript sources) with in 11 | * the `src/client` directory. 12 | */ 13 | export = (done: any) => { 14 | deleteAndWalk(Config.APP_SRC); 15 | done(); 16 | }; 17 | 18 | /** 19 | * Recursively walks along the given path and deletes all JavaScript files. 20 | * @param {any} path - The path to walk and clean. 21 | */ 22 | function walk(path: any) { 23 | let files = readdirSync(path); 24 | for (let i = 0; i < files.length; i += 1) { 25 | let curPath = join(path, files[i]); 26 | if (lstatSync(curPath).isDirectory()) { // recurse 27 | deleteAndWalk(curPath); 28 | } 29 | } 30 | } 31 | 32 | /** 33 | * Deletes the JavaScript file with the given path. 34 | * @param {any} path - The path of the JavaScript file to be deleted. 35 | */ 36 | function deleteAndWalk(path: any) { 37 | try { 38 | rimraf.sync(join(path, '*.js')); 39 | util.log('Deleted', chalk.yellow(`${path}/*.js`)); 40 | rimraf.sync(join(path, '*.js.map')); 41 | util.log('Deleted', chalk.yellow(`${path}/*.js.map`)); 42 | } catch (e) { 43 | util.log('Error while deleting', chalk.yellow(`${path}/*.js`), e); 44 | } 45 | walk(path); 46 | } 47 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.all.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist` directory. 6 | */ 7 | export = clean([Config.DIST_DIR, Config.COVERAGE_DIR, Config.TNS_APP_DEST]); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.coverage.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist/dev` directory. 6 | */ 7 | export = clean([Config.COVERAGE_DIR, Config.COVERAGE_TS_DIR]); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.dev.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist/dev` directory. 6 | */ 7 | export = clean(Config.DEV_DEST); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.e2e.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist/dev` directory. 6 | */ 7 | export = clean(Config.E2E_DEST); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.prod.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist/dev` and `dist/tmp` directory. 6 | */ 7 | export = clean([Config.PROD_DEST, Config.TMP_DIR]); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.tns.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { clean } from '../../utils'; 3 | 4 | /** 5 | * Executes the build process, cleaning all files within the `/dist` directory. 6 | */ 7 | export = clean([Config.TNS_APP_DEST]); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/clean.tools.ts: -------------------------------------------------------------------------------- 1 | import { clean } from '../../utils'; 2 | import { join } from 'path'; 3 | 4 | import Config from '../../config'; 5 | 6 | /** 7 | * Removes all the js, js.map from the tools directories 8 | * 9 | * NB: this needs to remain syncronus, or check.tools will 10 | * need to be updated to handle the returned promise/stream 11 | * 12 | */ 13 | export = clean([ 14 | 'gulpfile.js', 15 | 'gulpfile.js.map', 16 | join(Config.TOOLS_DIR, '**/*.js'), 17 | join(Config.TOOLS_DIR, '**/*.js.map') 18 | ]); 19 | 20 | -------------------------------------------------------------------------------- /tools/tasks/seed/clear.files.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { clean } from '../../utils'; 3 | 4 | import Config from '../../config'; 5 | 6 | /** 7 | * Removes all the js, js.map and metadata.json from the src and tools directories 8 | */ 9 | export = clean([ 10 | 'gulpfile.js', 11 | 'gulpfile.js.map', 12 | join(Config.TOOLS_DIR, '**/*.js'), 13 | join(Config.TOOLS_DIR, '**/*.js.map'), 14 | join(Config.TOOLS_DIR, '**/*.metadata.json'), 15 | join(Config.APP_SRC, '**/*.js'), 16 | join(Config.APP_SRC, '**/*.js.map'), 17 | join(Config.APP_SRC, '**/*.metadata.json') 18 | ]); 19 | 20 | -------------------------------------------------------------------------------- /tools/tasks/seed/compile.ahead.prod.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import * as ts from 'typescript'; 3 | import { argv } from 'yargs'; 4 | import { join } from 'path'; 5 | import { writeFileSync, readFileSync, readdirSync } from 'fs'; 6 | import { CodeGenerator, AngularCompilerOptions, NgcCliOptions, main } from '@angular/compiler-cli'; 7 | 8 | import Config from '../../config'; 9 | 10 | function codegen( 11 | ngOptions: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program, 12 | host: ts.CompilerHost) { 13 | return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen(); 14 | } 15 | 16 | const modifyFile = (path: string, mod: any = (f: string) => f) => { 17 | const file = readFileSync(path); 18 | writeFileSync(path, mod(file.toString())); 19 | }; 20 | 21 | export = (done: any) => { 22 | // Note: dirty hack until we're able to set config easier 23 | modifyFile(join(Config.TMP_DIR, 'tsconfig.json'), (content: string) => { 24 | const parsed = JSON.parse(content); 25 | const path = join(Config.PROJECT_ROOT, Config.TOOLS_DIR, 'manual_typings', 'project'); 26 | parsed.files = parsed.files || []; 27 | parsed.files = parsed.files.concat( 28 | readdirSync(path) 29 | .filter(f => f.endsWith('d.ts')) 30 | .map(f => join(path, f))); 31 | parsed.files = parsed.files.filter((f: string, i: number) => parsed.files.indexOf(f) === i); 32 | parsed.files.push(join(Config.BOOTSTRAP_DIR, 'main.web.ts')); 33 | return JSON.stringify(parsed, null, 2); 34 | }); 35 | const args = argv; 36 | 37 | // If a translation, tell the compiler 38 | if (args.lang) { 39 | args['i18nFile'] = `./src/client/assets/locale/messages.${args.lang}.xlf`; 40 | args['locale'] = args.lang; 41 | args['i18nFormat'] = 'xlf'; 42 | } 43 | 44 | const cliOptions = new NgcCliOptions(args); 45 | main(Config.TMP_DIR, cliOptions, codegen) 46 | .then(done) 47 | .catch(e => { 48 | console.error(e.stack); 49 | console.error('Compilation failed'); 50 | process.exit(1); 51 | }); 52 | }; 53 | -------------------------------------------------------------------------------- /tools/tasks/seed/copy.prod.rollup.aot.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { join } from 'path'; 3 | import Config from '../../config'; 4 | 5 | const replace = require('gulp-replace'); 6 | 7 | /** 8 | * Executes the build task, copying all TypeScript files over to the `dist/tmp` directory. 9 | */ 10 | export = () => { 11 | return gulp.src([ 12 | join(Config.APP_SRC, '**/*.ts'), 13 | join(Config.APP_SRC, '**/*.json'), 14 | '!' + join(Config.APP_SRC, '**/*.spec.ts'), 15 | '!' + join(Config.APP_SRC, '**/*.e2e-spec.ts') 16 | ]) 17 | // import in dev mode: import * as moment from 'moment'; 18 | // import for rollup: import moment from 'moment'; 19 | // .pipe(replace('import * as moment from \'moment\';', 'import moment from \'moment\';')) 20 | // .pipe(replace('import * as uuid from \'node-uuid\';', 'import uuid from \'node-uuid\';')) 21 | .pipe(gulp.dest(Config.TMP_DIR)); 22 | }; 23 | -------------------------------------------------------------------------------- /tools/tasks/seed/copy.prod.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import { join } from 'path'; 3 | 4 | import Config from '../../config'; 5 | 6 | /** 7 | * Executes the build task, copying all TypeScript files over to the `dist/tmp` directory. 8 | */ 9 | export = () => { 10 | return gulp.src([ 11 | join(Config.APP_SRC, '**/*.ts'), 12 | join(Config.APP_SRC, '**/*.json'), 13 | '!' + join(Config.APP_SRC, '**/*.spec.ts'), 14 | '!' + join(Config.APP_SRC, '**/*.e2e-spec.ts') 15 | ]) 16 | .pipe(gulp.dest(Config.TMP_DIR)); 17 | }; 18 | -------------------------------------------------------------------------------- /tools/tasks/seed/e2e.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | import * as history from 'express-history-api-fallback'; 3 | import * as gulp from 'gulp'; 4 | import { resolve, join } from 'path'; 5 | import { protractor } from 'gulp-protractor'; 6 | import Config from '../../config'; 7 | 8 | class Protractor { 9 | server(port: number, dir: string) { 10 | let app = express(); 11 | let root = resolve(process.cwd(), dir); 12 | for (let proxy of Config.getProxyMiddleware()) { 13 | app.use(proxy); 14 | } 15 | app.use(express.static(root)); 16 | app.use(history('index.html', { root })); 17 | return new Promise((resolve, reject) => { 18 | let server = app.listen(port, () => { 19 | resolve(server); 20 | }); 21 | }); 22 | } 23 | } 24 | 25 | /** 26 | * Executes the build process, running all e2e specs using `protractor`. 27 | */ 28 | export = (done: any) => { 29 | process.env.LANG = 'en_US.UTF-8'; 30 | new Protractor() 31 | .server(Config.PORT, Config.PROD_DEST) 32 | .then((server: any) => { 33 | gulp 34 | .src(join(Config.DEV_DEST, '**/*.e2e-spec.js')) 35 | .pipe(protractor({ configFile: 'protractor.conf.js' })) 36 | .on('error', (error: string) => { throw error; }) 37 | .on('end', () => { server.close(done); }); 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /tools/tasks/seed/generate.manifest.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | 3 | import Config from '../../config'; 4 | 5 | /** 6 | * Executes the build process, generating the manifest file using `angular2-service-worker`. 7 | */ 8 | export = () => { 9 | return require('angular2-service-worker') 10 | .gulpGenManifest({ 11 | group: [{ 12 | name: 'css', 13 | sources: gulp.src(`${Config.APP_DEST}/**/*.css`) 14 | }, { 15 | name: 'js', 16 | sources: gulp.src(`${Config.APP_DEST}/**/*.js`) 17 | }] 18 | }) 19 | .pipe(gulp.dest(Config.APP_DEST)); 20 | }; 21 | -------------------------------------------------------------------------------- /tools/tasks/seed/karma.run.ts: -------------------------------------------------------------------------------- 1 | import { startKarma } from '../../utils/seed/karma.start'; 2 | import Config from '../../config'; 3 | 4 | /** 5 | * Executes the build process, running all unit tests using `karma`. 6 | */ 7 | export = (done: any) => { 8 | return startKarma(done, Config.getKarmaReporters()); 9 | }; 10 | -------------------------------------------------------------------------------- /tools/tasks/seed/karma.run.with_coverage.ts: -------------------------------------------------------------------------------- 1 | import * as karma from 'karma'; 2 | import { join } from 'path'; 3 | 4 | import Config from '../../config'; 5 | 6 | let repeatableStartKarma = (done: any, config: any = {}) => { 7 | return new (karma).Server(Object.assign({ 8 | configFile: join(process.cwd(), 'karma.conf.js'), 9 | singleRun: true 10 | }, config), (exitCode: any) => { 11 | // Karma run is finished but do not exit the process for failure. Rather just mark this task as done. 12 | done(); 13 | }).start(); 14 | }; 15 | 16 | export = (done: any) => { 17 | let karmaReporters = Config.getKarmaReporters(); 18 | karmaReporters.singleRun = true; 19 | return repeatableStartKarma(done, karmaReporters); 20 | }; 21 | -------------------------------------------------------------------------------- /tools/tasks/seed/karma.watch.ts: -------------------------------------------------------------------------------- 1 | import { startKarma } from '../../utils/seed/karma.start'; 2 | /** 3 | * Executes the build process, running all unit tests using `karma`. 4 | */ 5 | export = (done: any) => setTimeout(() => { 6 | return startKarma(done, { 7 | singleRun: false 8 | }); 9 | }, 10 | // On some OS, the default max opened file descriptor limit might cause karma to not start. 11 | // By setting this timeout, there should be enough time before other tasks release the descriptors. 12 | // Karma itself can have as many opened files as it needs, it uses graceful-fs. 13 | 1000); 14 | -------------------------------------------------------------------------------- /tools/tasks/seed/minify.bundles.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import * as merge from 'merge-stream'; 4 | import { join } from 'path'; 5 | 6 | import Config from '../../config'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | const getTask = (target: string, destDir: string) => { 11 | return gulp.src(join(destDir, target)) 12 | .pipe(plugins.uglify({ 13 | compress: true, 14 | mangle: true 15 | })) 16 | .pipe(gulp.dest(destDir)); 17 | }; 18 | 19 | export = () => { 20 | return merge( 21 | getTask(Config.JS_PROD_APP_BUNDLE, Config.JS_DEST), 22 | getTask(Config.JS_PROD_SHIMS_BUNDLE, Config.JS_DEST) 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /tools/tasks/seed/noop.ts: -------------------------------------------------------------------------------- 1 | export = (done: any) => { 2 | done(); 3 | }; 4 | -------------------------------------------------------------------------------- /tools/tasks/seed/print.banner.ts: -------------------------------------------------------------------------------- 1 | import Config from '../../config'; 2 | import { readFile } from 'fs'; 3 | import * as util from 'gulp-util'; 4 | import { join } from 'path'; 5 | 6 | export = (done: any) => { 7 | let bannerPath = join(Config.TOOLS_DIR, 'config', 'banner.txt'); 8 | if (require('supports-color').has256) { 9 | bannerPath = join(Config.TOOLS_DIR, 'config', 'banner-256.txt'); 10 | } 11 | readFile(bannerPath, (e, content) => { 12 | if (!e) { 13 | console.log(util.colors.green(content.toString())); 14 | } 15 | done(); 16 | }); 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /tools/tasks/seed/serve.coverage.ts: -------------------------------------------------------------------------------- 1 | import { serveCoverage } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, serving unit test coverage report using an `express` server. 5 | */ 6 | export = serveCoverage; 7 | -------------------------------------------------------------------------------- /tools/tasks/seed/serve.coverage.watch.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import * as browserSync from 'browser-sync'; 3 | 4 | import Config from '../../config'; 5 | 6 | export = () => { 7 | let coverageFolder = Config.COVERAGE_TS_DIR; 8 | let watchedFiles: string[] = [join(coverageFolder, '**')]; 9 | 10 | // Serve files from the coverage of this project 11 | browserSync.create().init({ 12 | server: { 13 | baseDir: './' + coverageFolder 14 | }, 15 | port: Config.COVERAGE_PORT, 16 | files: watchedFiles, 17 | logFileChanges: false 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /tools/tasks/seed/serve.docs.ts: -------------------------------------------------------------------------------- 1 | import { serveDocs } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, serving the application documentation using an `express` server. 5 | */ 6 | export = serveDocs; 7 | 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/server.prod.ts: -------------------------------------------------------------------------------- 1 | import { serveProd } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, serving the files of the production environment using an `express` server. 5 | */ 6 | export = serveProd; 7 | -------------------------------------------------------------------------------- /tools/tasks/seed/server.start.ts: -------------------------------------------------------------------------------- 1 | import { serveSPA } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, serving the files of the development environment using an `express` server. 5 | */ 6 | export = serveSPA; 7 | -------------------------------------------------------------------------------- /tools/tasks/seed/start.deving.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | import * as runSequence from 'run-sequence'; 5 | 6 | import Config from '../../config'; 7 | 8 | const plugins = gulpLoadPlugins(); 9 | 10 | import { notifyLiveReload } from '../../utils'; 11 | 12 | function watchAppFiles(path: string, fileChangeCallback: (e: any, done: () => void) => void) { 13 | 14 | let paths: string[] = [ 15 | join(Config.APP_SRC, path) 16 | ].concat(Config.TEMP_FILES.map((p) => { return '!' + p; })); 17 | 18 | let busyWithCall : boolean = false; 19 | let changesWaiting : any = null; 20 | let afterCall = () => { 21 | busyWithCall = false; 22 | if (changesWaiting) { 23 | fileChangeCallback(changesWaiting, afterCall); 24 | changesWaiting = null; 25 | } 26 | }; 27 | plugins.watch(paths, (e: any) => { 28 | if (busyWithCall) { 29 | changesWaiting = e; 30 | return; 31 | } 32 | busyWithCall = true; 33 | fileChangeCallback(e, afterCall); 34 | }); 35 | 36 | } 37 | 38 | gulp.task('watch.while_deving', function () { 39 | watchAppFiles('**/!(*.ts)', (e: any, done: any) => 40 | runSequence('build.assets.dev', 'build.html_css', 'build.index.dev', () => { notifyLiveReload(e); done(); })); 41 | watchAppFiles('**/(*.ts)', (e: any, done: any) => 42 | runSequence('build.js.dev', 'build.index.dev', () => { 43 | notifyLiveReload(e); 44 | runSequence('build.js.test', 'karma.run.with_coverage', done); 45 | })); 46 | }); 47 | 48 | export = (done: any) => 49 | runSequence('build.test', 50 | 'watch.while_deving', 51 | 'server.start', 52 | 'karma.run.with_coverage', 53 | 'serve.coverage.watch', 54 | done); 55 | -------------------------------------------------------------------------------- /tools/tasks/seed/transpile.bundles.rollup.aot.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | import { makeTsProject, } from '../../utils'; 7 | import { TemplateLocalsBuilder } from '../../utils/seed/template_locals'; 8 | 9 | const plugins = gulpLoadPlugins(); 10 | 11 | /** 12 | * Executes the build process, transpiling the TypeScript files for the production environment. 13 | */ 14 | 15 | export = () => { 16 | const tsProject = makeTsProject({ 17 | allowJs: true, 18 | noFallthroughCasesInSwitch: false 19 | }, Config.TMP_DIR); 20 | const src = [ 21 | join(Config.TMP_DIR, 'bundle.js') 22 | ]; 23 | const result = gulp.src(src) 24 | .pipe(plugins.plumber()) 25 | .pipe(tsProject()) 26 | .once('error', () => { 27 | this.once('finish', () => process.exit(1)); 28 | }); 29 | 30 | return result.js 31 | .pipe(plugins.template(new TemplateLocalsBuilder().build())) 32 | .pipe(plugins.rename(Config.JS_PROD_APP_BUNDLE)) 33 | .pipe(gulp.dest(Config.JS_DEST)) 34 | .on('error', (e: any) => { 35 | console.log(e); 36 | }); 37 | }; 38 | -------------------------------------------------------------------------------- /tools/tasks/seed/tslint.tns.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/mgechev/angular-seed/pull/1681 2 | import * as gulp from 'gulp'; 3 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 4 | 5 | import Config from '../../config'; 6 | 7 | const plugins = gulpLoadPlugins(); 8 | 9 | /** 10 | * Executes the build process, linting the TypeScript files using `codelyzer`. 11 | */ 12 | export = () => { 13 | let src = [ 14 | '**/*.ts', 15 | 'app/**/*.ts', 16 | ]; 17 | 18 | return gulp.src(src, { 19 | base: Config.TNS_APP_SRC, 20 | cwd: Config.TNS_APP_SRC, 21 | }) 22 | .pipe(plugins.tslint()) 23 | .pipe(plugins.tslint.report({ 24 | emitError: require('is-ci') 25 | })); 26 | }; 27 | -------------------------------------------------------------------------------- /tools/tasks/seed/tslint.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | 7 | const plugins = gulpLoadPlugins(); 8 | 9 | /** 10 | * Executes the build process, linting the TypeScript files using `codelyzer`. 11 | */ 12 | export = () => { 13 | let src = [ 14 | join(Config.APP_SRC, '**/*.ts'), 15 | '!' + join(Config.APP_SRC, '**/*.d.ts'), 16 | join(Config.E2E_SRC, '**/*.ts'), 17 | '!' + join(Config.E2E_SRC, '**/*.d.ts'), 18 | join(Config.TOOLS_DIR, '**/*.ts'), 19 | '!' + join(Config.TOOLS_DIR, '**/*.d.ts') 20 | ]; 21 | 22 | return gulp.src(src, {'base': '.'}) 23 | .pipe(plugins.tslint()) 24 | .pipe(plugins.tslint.report({ 25 | emitError: require('is-ci') || Config.FORCE_TSLINT_EMIT_ERROR 26 | })); 27 | }; 28 | -------------------------------------------------------------------------------- /tools/tasks/seed/watch.dev.ts: -------------------------------------------------------------------------------- 1 | import { watch } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, watching for file changes and rebuilding the development environment. 5 | */ 6 | export = watch('build.dev'); 7 | -------------------------------------------------------------------------------- /tools/tasks/seed/watch.e2e.ts: -------------------------------------------------------------------------------- 1 | import { watch } from '../../utils'; 2 | import Config from '../../config'; 3 | 4 | /** 5 | * Executes the build process, watching for file changes and rebuilding the e2e environment. 6 | */ 7 | export = watch('build.e2e', Config.E2E_SRC); 8 | -------------------------------------------------------------------------------- /tools/tasks/seed/watch.test.ts: -------------------------------------------------------------------------------- 1 | import { watch } from '../../utils'; 2 | 3 | /** 4 | * Executes the build process, watching for file changes and rebuilding the test environment. 5 | */ 6 | export = watch('build.test'); 7 | -------------------------------------------------------------------------------- /tools/tasks/seed/watch.tns.ts: -------------------------------------------------------------------------------- 1 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 2 | import * as runSequence from 'run-sequence'; 3 | 4 | import Config from '../../config'; 5 | import { changeFileManager } from '../../utils/seed/code_change_tools'; 6 | import { notifyLiveReload } from '../../utils'; 7 | const plugins = gulpLoadPlugins(); 8 | 9 | const taskname = 'build.tns'; 10 | 11 | export = function watch() { 12 | const paths: string[] = [ 13 | `${Config.ASSETS_SRC}/**/*`, 14 | `${Config.TNS_APP_SRC}/**/*`, 15 | `${Config.TNS_APP_SRC}/app/*`, 16 | `${Config.TNS_APP_SRC}/app/**/*`, 17 | `!${Config.TNS_APP_SRC}/app/*.component.css`, 18 | `!${Config.TNS_APP_SRC}/app/*.component.html`, 19 | ]; 20 | 21 | plugins.watch(paths, (e: any) => { 22 | changeFileManager.addFile(e.path); 23 | 24 | runSequence(taskname, () => { 25 | changeFileManager.clear(); 26 | 27 | notifyLiveReload(e); 28 | }); 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /tools/tasks/seed/webdriver.ts: -------------------------------------------------------------------------------- 1 | import { webdriver_update } from 'gulp-protractor'; 2 | 3 | /** 4 | * Executes the build process, installing the selenium webdriver used for the protractor e2e specs. 5 | */ 6 | export = webdriver_update; 7 | -------------------------------------------------------------------------------- /tools/tasks/task.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Base class for all tasks. 3 | */ 4 | export abstract class Task { 5 | /** 6 | * Override this task if you want to implement some custom 7 | * task activation mechanism. By default each task will be always executed. 8 | * 9 | * @param {string[]} files A list of files changed since the previous watch. 10 | */ 11 | shallRun(files: string[]): boolean { 12 | return true; 13 | } 14 | 15 | /** 16 | * Implements your task behavior. 17 | * 18 | * @param {any} done A function which should be activated once your task completes. 19 | * @return {ReadWriteStream | Promise | void} This method can either return a promise 20 | * which should be resolved once your task execution completes, a stream 21 | * which should throw an end event once your task execution completes 22 | * or nothing in case you will manually invoke the `done` method. 23 | */ 24 | abstract run(done?: any, files?: string[]): any | Promise | void; 25 | } 26 | -------------------------------------------------------------------------------- /tools/tasks/typescript_task.ts: -------------------------------------------------------------------------------- 1 | import { Task } from './task'; 2 | 3 | export abstract class TypeScriptTask extends Task { 4 | shallRun(files: String[]) { 5 | return files.reduce((a, f) => { 6 | return a || f.endsWith('.ts'); 7 | }, false); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tools/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This barrel file provides the export for the utilities provided by the project and the seed. 3 | */ 4 | export * from './utils/project.utils'; 5 | export * from './utils/seed.utils'; 6 | -------------------------------------------------------------------------------- /tools/utils/project.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This barrel file provides the exports for the project specific utilities. 3 | */ 4 | export * from './project/sample_util'; 5 | -------------------------------------------------------------------------------- /tools/utils/project/sample_util.ts: -------------------------------------------------------------------------------- 1 | export function myUtil() { 2 | // Code goes here 3 | } 4 | -------------------------------------------------------------------------------- /tools/utils/seed.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This barrel file provides the export for the utilities provided by the seed. 3 | */ 4 | export * from './seed/clean'; 5 | export * from './seed/code_change_tools'; 6 | export * from './seed/server'; 7 | export * from './seed/tasks_tools'; 8 | export * from './seed/template_locals'; 9 | export * from './seed/tsproject'; 10 | export * from './seed/watch'; 11 | -------------------------------------------------------------------------------- /tools/utils/seed/clean.ts: -------------------------------------------------------------------------------- 1 | import * as util from 'gulp-util'; 2 | import { relative, normalize } from 'path'; 3 | import * as rimraf from 'rimraf'; 4 | 5 | import Config from '../../config'; 6 | 7 | /** 8 | * Cleans the given path(s) using `rimraf`. 9 | * @param {string or string[]} paths - The path or list of paths to clean. 10 | */ 11 | export function clean(paths: string|string[]): (done: () => void) => void { 12 | return done => { 13 | let pathsToClean: string[]; 14 | if (paths instanceof Array) { 15 | pathsToClean = paths; 16 | } else { 17 | pathsToClean = [paths]; 18 | } 19 | 20 | let promises = pathsToClean.map(p => { 21 | return new Promise(resolve => { 22 | const relativePath: string = relative(Config.PROJECT_ROOT, p); 23 | if (relativePath.startsWith('..')) { 24 | util.log(util.colors.bgRed.white(`Cannot remove files outside the project root but tried "${normalize(p)}"`)); 25 | process.exit(1); 26 | } else { 27 | rimraf(p, e => { 28 | if (e) { 29 | util.log('Clean task failed with', e); 30 | } else { 31 | util.log('Deleted', util.colors.yellow(p || '-')); 32 | } 33 | resolve(); 34 | }); 35 | } 36 | }); 37 | }); 38 | Promise.all(promises).then(() => (done || (() => 1))()) 39 | .catch(e => util.log(util.colors.red(`Error while removing files "${[].concat(paths).join(', ')}", ${e}`))); 40 | }; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /tools/utils/seed/code_change_tools.ts: -------------------------------------------------------------------------------- 1 | import * as browserSync from 'browser-sync'; 2 | // import * as path from 'path'; 3 | 4 | import Config from '../../config'; 5 | 6 | class ChangeFileManager { 7 | private _files: string[] = []; 8 | private _pristine = true; 9 | 10 | get lastChangedFiles() { 11 | return this._files.slice(); 12 | } 13 | 14 | get pristine() { 15 | return this._pristine; 16 | } 17 | 18 | addFile(file: string) { 19 | this._pristine = false; 20 | this._files.push(file); 21 | } 22 | 23 | addFiles(files: string[]) { 24 | files.forEach(f => this.addFile(f)); 25 | } 26 | 27 | clear() { 28 | this._files = []; 29 | } 30 | } 31 | 32 | export let changeFileManager = new ChangeFileManager(); 33 | 34 | /** 35 | * Initialises BrowserSync with the configuration defined in seed.config.ts (or if overriden: project.config.ts). 36 | */ 37 | let runServer = () => { 38 | browserSync.init(Config.getPluginConfig('browser-sync')); 39 | }; 40 | 41 | /** 42 | * Runs BrowserSync as the listening process for the application. 43 | */ 44 | let listen = () => { 45 | runServer(); 46 | }; 47 | 48 | /** 49 | * Provides a flag to mark which files have changed and reloads BrowserSync accordingly. 50 | */ 51 | let changed = (files: any) => { 52 | if (!(files instanceof Array)) { 53 | files = [files]; 54 | } 55 | browserSync.reload(files); 56 | }; 57 | 58 | export { listen, changed }; 59 | -------------------------------------------------------------------------------- /tools/utils/seed/karma.start.ts: -------------------------------------------------------------------------------- 1 | import * as karma from 'karma'; 2 | import { join } from 'path'; 3 | 4 | export const startKarma = (done: any, config: any = {}) => { 5 | return new (karma).Server(Object.assign({ 6 | configFile: join(process.cwd(), 'karma.conf.js'), 7 | singleRun: true 8 | }, config)).start(done); 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /tools/utils/seed/server.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | import * as fallback from 'express-history-api-fallback'; 3 | import * as openResource from 'open'; 4 | import { resolve } from 'path'; 5 | 6 | import * as codeChangeTool from './code_change_tools'; 7 | import Config from '../../config'; 8 | 9 | /** 10 | * Serves the Single Page Application. More specifically, calls the `listen` method, which itself launches BrowserSync. 11 | */ 12 | export function serveSPA() { 13 | codeChangeTool.listen(); 14 | } 15 | 16 | /** 17 | * This utility method is used to notify that a file change has happened and subsequently calls the `changed` method, 18 | * which itself initiates a BrowserSync reload. 19 | * @param {any} e - The file that has changed. 20 | */ 21 | export function notifyLiveReload(e:any) { 22 | let fileName = e.path; 23 | codeChangeTool.changed(fileName); 24 | } 25 | 26 | /** 27 | * Starts a new `express` server, serving the static documentation files. 28 | */ 29 | export function serveDocs() { 30 | let server = express(); 31 | 32 | server.use( 33 | Config.APP_BASE, 34 | express.static(resolve(process.cwd(), Config.DOCS_DEST)) 35 | ); 36 | 37 | server.listen(Config.DOCS_PORT, () => 38 | openResource('http://localhost:' + Config.DOCS_PORT + Config.APP_BASE) 39 | ); 40 | } 41 | 42 | /** 43 | * Starts a new `express` server, serving the static unit test code coverage report. 44 | */ 45 | export function serveCoverage() { 46 | let server = express(); 47 | 48 | server.use( 49 | Config.APP_BASE, 50 | express.static(resolve(process.cwd(), Config.COVERAGE_TS_DIR)) 51 | ); 52 | 53 | server.listen(Config.COVERAGE_PORT, () => 54 | openResource('http://localhost:' + Config.COVERAGE_PORT + Config.APP_BASE) 55 | ); 56 | } 57 | 58 | /** 59 | * Starts a new `express` server, serving the built files from `dist/prod`. 60 | */ 61 | export function serveProd() { 62 | let root = resolve(process.cwd(), Config.PROD_DEST); 63 | let server = express(); 64 | 65 | for (let proxy of Config.getProxyMiddleware()) { 66 | server.use(proxy); 67 | } 68 | 69 | server.use(Config.APP_BASE, express.static(root)); 70 | 71 | server.use(fallback('index.html', { root })); 72 | 73 | server.listen(Config.PORT, () => 74 | openResource('http://localhost:' + Config.PORT + Config.APP_BASE) 75 | ); 76 | }; 77 | -------------------------------------------------------------------------------- /tools/utils/seed/template_locals.ts: -------------------------------------------------------------------------------- 1 | import * as util from 'gulp-util'; 2 | import { argv } from 'yargs'; 3 | import { join } from 'path'; 4 | 5 | import Config from '../../config'; 6 | 7 | /** 8 | * Builds an object consisting of the base configuration provided by confg/seed.config.ts, the additional 9 | * project specific overrides as defined in config/project.config.ts and including the base environment config as defined in env/base.ts 10 | * and the environment specific overrides (for instance if env=dev then as defined in env/dev.ts). 11 | */ 12 | export class TemplateLocalsBuilder { 13 | private stringifySystemConfigDev = false; 14 | private stringifyEnvConfig = true; 15 | 16 | withStringifiedSystemConfigDev() { 17 | this.stringifySystemConfigDev = true; 18 | return this; 19 | } 20 | wihtoutStringifiedEnvConfig() { 21 | this.stringifyEnvConfig = false; 22 | return this; 23 | } 24 | 25 | 26 | build() { 27 | const configEnvName = argv['env-config'] || argv['config-env'] || 'dev'; 28 | const configPath = Config.getPluginConfig('environment-config'); 29 | const envOnlyConfig = this.getConfig(configPath, configEnvName); 30 | const baseConfig = this.getConfig(configPath, 'base'); 31 | 32 | if (!envOnlyConfig) { 33 | throw new Error(configEnvName + ' is an invalid configuration name'); 34 | } 35 | 36 | const envConfig = Object.assign({}, baseConfig, envOnlyConfig); 37 | let locals = Object.assign({}, 38 | Config, 39 | { ENV_CONFIG: this.stringifyEnvConfig ? JSON.stringify(envConfig) : envConfig } 40 | ); 41 | if (this.stringifySystemConfigDev) { 42 | Object.assign(locals, {SYSTEM_CONFIG_DEV: JSON.stringify(Config.SYSTEM_CONFIG_DEV)}); 43 | } 44 | return locals; 45 | } 46 | 47 | private getConfig(path: string, env: string) { 48 | const configPath = join(path, env); 49 | let config: any; 50 | try { 51 | config = JSON.parse(JSON.stringify(require(configPath))); 52 | } catch (e) { 53 | config = null; 54 | util.log(util.colors.red(e.message)); 55 | } 56 | 57 | return config; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /tools/utils/seed/tsproject.ts: -------------------------------------------------------------------------------- 1 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 2 | import { join } from 'path'; 3 | import ts = require('gulp-typescript/release/main'); 4 | 5 | import Config from '../../config'; 6 | 7 | const plugins = gulpLoadPlugins(); 8 | 9 | let tsProjects: any = {}; 10 | 11 | /** 12 | * Creates a TypeScript project with the given options using the gulp typescript plugin. 13 | * @param {Object} options - The additional options for the project configuration. 14 | */ 15 | export function makeTsProject(options: ts.Settings = {}, pathToTsConfig: string = Config.APP_SRC, projectName = Config.APP_PROJECTNAME) { 16 | let optionsHash = JSON.stringify(options); 17 | if (!tsProjects[optionsHash]) { 18 | let config = Object.assign({ 19 | typescript: require('typescript') 20 | }, options); 21 | tsProjects[optionsHash] = 22 | plugins.typescript.createProject(join(pathToTsConfig, projectName), config); 23 | } 24 | return tsProjects[optionsHash]; 25 | } 26 | -------------------------------------------------------------------------------- /tools/utils/seed/watch.ts: -------------------------------------------------------------------------------- 1 | import * as gulpLoadPlugins from 'gulp-load-plugins'; 2 | import { join } from 'path'; 3 | import * as runSequence from 'run-sequence'; 4 | 5 | import Config from '../../config'; 6 | import { changeFileManager } from './code_change_tools'; 7 | import { notifyLiveReload } from '../../utils'; 8 | 9 | const plugins = gulpLoadPlugins(); 10 | 11 | /** 12 | * Watches the task with the given taskname. 13 | * @param {string} taskname - The name of the task. 14 | */ 15 | export function watch(taskname: string, root: string = Config.APP_SRC) { 16 | return function () { 17 | let paths: string[] = [ 18 | join(root, '**') 19 | ].concat(Config.TEMP_FILES.map((p) => { return '!' + p; })); 20 | 21 | // watches for user defined paths to trigger compilation 22 | if (Config.EXTRA_WATCH_PATHS) { 23 | paths = paths.concat(Config.EXTRA_WATCH_PATHS.map((p) => { 24 | return join(p, '**'); 25 | })); 26 | } 27 | 28 | plugins.watch(paths, (e: any) => { 29 | changeFileManager.addFile(e.path); 30 | 31 | 32 | // Resolves issue in IntelliJ and other IDEs/text editors which 33 | // save multiple files at once. 34 | // https://github.com/mgechev/angular-seed/issues/1615 for more details. 35 | setTimeout(() => { 36 | 37 | runSequence(taskname, () => { 38 | changeFileManager.clear(); 39 | notifyLiveReload(e); 40 | }); 41 | 42 | }, 100); 43 | }); 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "lib": ["es2015"], 11 | "sourceMap": true, 12 | "pretty": true, 13 | "allowUnreachableCode": false, 14 | "allowUnusedLabels": false, 15 | "noImplicitAny": true, 16 | "noImplicitReturns": true, 17 | "noImplicitUseStrict": false, 18 | "noFallthroughCasesInSwitch": true, 19 | "typeRoots": [ 20 | "./node_modules/@types", 21 | "./node_modules" 22 | ], 23 | "types": [ 24 | "node" 25 | ] 26 | }, 27 | "exclude": [ 28 | "desktop", 29 | "nativescript", 30 | "node_modules", 31 | "dist", 32 | "src" 33 | ], 34 | "compileOnSave": false 35 | } 36 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tools/config/seed.tslint.json", 3 | "rules": { 4 | } 5 | } 6 | --------------------------------------------------------------------------------