Repository: BenjaminDobler/ngtron Branch: master Commit: ba00550fb2b7 Files: 97 Total size: 152.5 KB Directory structure: gitextract_19xx1qw3/ ├── .editorconfig ├── .gitignore ├── .npmignore ├── .prettierrc ├── .vscode/ │ └── settings.json ├── LICENSE ├── README.md ├── package.json ├── sandbox/ │ ├── singleproject-sandbox/ │ │ ├── .browserslistrc │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── README.md │ │ ├── angular.json │ │ ├── e2e/ │ │ │ ├── protractor.conf.js │ │ │ ├── src/ │ │ │ │ ├── app.e2e-spec.ts │ │ │ │ └── app.po.ts │ │ │ └── tsconfig.json │ │ ├── karma.conf.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── app-routing.module.ts │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.scss │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ └── app.module.ts │ │ │ ├── assets/ │ │ │ │ └── .gitkeep │ │ │ ├── environments/ │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── styles.scss │ │ │ └── test.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.spec.json │ │ └── tslint.json │ ├── workspace/ │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── README.md │ │ ├── angular.json │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── tslint.json │ └── workspace-existing/ │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── angular.json │ ├── package.json │ ├── projects/ │ │ └── app/ │ │ ├── .browserslistrc │ │ ├── e2e/ │ │ │ ├── protractor.conf.js │ │ │ ├── src/ │ │ │ │ ├── app.e2e-spec.ts │ │ │ │ └── app.po.ts │ │ │ └── tsconfig.json │ │ ├── karma.conf.js │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── app-routing.module.ts │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.scss │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ └── app.module.ts │ │ │ ├── assets/ │ │ │ │ └── .gitkeep │ │ │ ├── environments/ │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── styles.scss │ │ │ └── test.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.spec.json │ │ └── tslint.json │ ├── tsconfig.json │ └── tslint.json ├── src/ │ ├── builders/ │ │ ├── build/ │ │ │ ├── index.ts │ │ │ └── schema.json │ │ ├── builders.json │ │ ├── package/ │ │ │ ├── index.ts │ │ │ └── schema.json │ │ ├── serve/ │ │ │ ├── index.ts │ │ │ └── schema.json │ │ └── util/ │ │ ├── dev.server/ │ │ │ └── dev.server.ts │ │ ├── electron.ts │ │ ├── externals.ts │ │ └── util.ts │ └── schematics/ │ ├── add-to-project/ │ │ ├── index.ts │ │ └── schema.json │ ├── application/ │ │ ├── index.ts │ │ └── schema.json │ ├── collection.json │ ├── files/ │ │ ├── electron/ │ │ │ └── package.json │ │ └── main/ │ │ ├── src/ │ │ │ └── main.ts │ │ └── tsconfig.json │ └── ng-add/ │ ├── index.ts │ └── schema.json ├── tsconfig.json └── tslint.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # Editor configuration, see https://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.md] max_line_length = off trim_trailing_whitespace = false ================================================ FILE: .gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # Outputs src/**/*.js src/**/*.js.map src/**/*.d.ts # compiled output /dist /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events.json speed-measure-plugin.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db ================================================ FILE: .npmignore ================================================ src !dist/**/*.ts sandbox ================================================ FILE: .prettierrc ================================================ { "printWidth": 160, "tabWidth": 4, "singleQuote": true, "trailingComma": "es5", "endOfLine": "lf" } ================================================ FILE: .vscode/settings.json ================================================ { } ================================================ FILE: LICENSE ================================================ Copyright 2019 Benjamin Dobler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # NgTron ![Alt text](ngtron.png?raw=true "NGTron Logo") Angular + Electron = :heart: Angular CLI extension based on Schematics and Builders for building angular based electron applications. This project uses the new architect API which was introduced in Angular 8. **So you can only use this addon starting with angular 8!** Ngtron will setup your angular workspace with the finest electron tools available. [Electron Builder](https://github.com/electron-userland/electron-builder) is added to package your projects for mac, windows and linux. [![npm version](https://badge.fury.io/js/%40richapps%2Fngtron.svg)](https://www.npmjs.com/@richapps/ngtron) ## Introduction An typical electron project consists of node application which is called the **main process**. This main process can create BrowserWindows which contain web pages. Those web pages are called **renderer processes** in the context of electron. Consequently an ngtron project is a combination of different types of applications. This nicely fits with the multi project support of Angular workspaces. An ngtron project can have exactly one main (node) project and n renderer projects (normal angular projects). There is one more type which is an electron project type where this all configured. This flexible architecture allows to build electron apps which include multiple angular projects. You can for example open several windows each containing a different Angular application. ## Installation NGTron supports the ng-add schematic to setup an angular workspace. Running the schematic will install the @richapps/ngtron packages and setup further dependencies like electron-builder. ```bash ng add @richapps/ngtron ``` ## Setup The recommended way of using ngtron is to use multiple projects for each type (main, renderer, electron) in an angular workspace. Beside that ngtron also supports root level projects which do not use multiple projects by adding the main process and electron files inside the renderer project. Here you will find an overview of the different setups. ## Creating an application as multiple projects in a workspace (recommended) `ng new workspace --create-application=false` `ng add @richapps/ngtron` `ng generate @richapps/ngtron:app` You will be prompted for a project name. Let's assue you choose my_app as the project name. This will generate three projects in your worspace. - **_myapp-electron_** This projects holds the electron specific configuration and assets like icons for your electron application. - **_myapp-main_** This projects is a node project which will used for the main process of your application - **_myapp-renderer_** This is the angular project where you can define your renderer code (Note: you can add more renderer projects if you for example want to open different angular apps in different windows of your electron app). You can now run your app with: `ng serve myapp-electron` And package your app with: `ng run myapp-electron:package` ## Using an existing angular project as the renderer for an electron app `ng add @richapps/ngtron` `ng generate @richapps/ngtron:app --project= ## Create a root level ngtron project `ng new ` `ng add @richapps/ngtron` `ng generate @richapps/ngtron:app --project= --singleProject=true` ## Adding ngtron to an existing root level project `ng add @richapps/ngtron` `ng generate @richapps/ngtron:app --project=my-existing-project --singleProject=true` ### Run app while developing (with hot reloading) ```bash ng run project:build-electron ``` Builds the app and opens it in an electron window. Uses hot reloading whenever your code changes. ### Package your app ```bash ng run project:package-electron ``` You can customize your build settings in the angular.json. There you will find all the settings which you can use in electron-builder. ### Serve app in the browser `ng run project:serve-electron` This will serve your app in the browser even if you use node or electron apis. Example will follow. ================================================ FILE: package.json ================================================ { "name": "@richapps/ngtron", "version": "1.0.0-rc.8", "description": "Easily serve and build angular based electron applications", "author": { "name": "Benjamin Dobler", "email": "benz@richapps.de", "url": "http://www.richapps.de" }, "repository": { "type": "git", "url": "https://github.com/BenjaminDobler/ngtron" }, "license": "MIT", "scripts": { "build": "tsc -p tsconfig.json && npm run copy:json && npm run copy:js && npm run copy:files", "copy:json": "cpx 'src/**/*.json' ./dist", "copy:js": "cpx 'src/**/*.js' ./dist", "copy:files": "cpx \"./src/schematics/files/**/*\" \"./dist/schematics/files\"", "link:schematic": "npm link && cd sandbox/singleproject-sandbox && npm link @richapps/ngtron && cd ../workspace-existing && npm link @richapps/ngtron && cd ../workspace && npm link @richapps/ngtron", "clean": "git checkout HEAD -- sandbox && git clean -f -d sandbox", "test-schematic-single": "cd sandbox/singleproject-sandbox && ng generate @richapps/ngtron:app --project=singleproject-sandbox --singleProject=true", "test-schematic-workspace-existing": "cd sandbox/workspace-existing && ng generate @richapps/ngtron:app --project=app", "test-schematic-workspace": "cd sandbox/workspace && ng generate @richapps/ngtron:app" }, "schematics": "./dist/schematics/collection.json", "builders": "./dist/builders/builders.json", "dependencies": { "@angular-devkit/core": ">=8.0.0", "@angular-devkit/schematics": ">=8.0.0", "@schematics/angular": ">=8.3.12", "find-free-port": "^2.0.0", "fs-extra": "8.1.0", "webpack-inject-plugin": "^1.5.3", "ws": "^7.1.2" }, "peerDependencies": { "@angular-devkit/build-angular": ">=0.803.12" }, "devDependencies": { "@angular-devkit/build-angular": ">=0.803.12", "@angular/compiler-cli": "^9.1.9", "@types/jasmine": "^3.3.13", "@types/node": "~11.9.0", "@types/webpack": "^4.39.3", "@types/webpack-dev-server": "^3.1.6", "codelyzer": "^5.2.2", "cpx": "^1.5.0", "electron-builder": "^22.6.1", "inquirer": "^7.1.0", "jasmine": "^3.0.0", "quicktype": "^15.0.194", "tslint": "~5.15.0", "typescript": "~3.4.3" } } ================================================ FILE: sandbox/singleproject-sandbox/.browserslistrc ================================================ # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. # For additional information regarding the format and rule options, please see: # https://github.com/browserslist/browserslist#queries # For the full list of supported browsers by the Angular framework, please see: # https://angular.io/guide/browser-support # You can see what browsers were selected by your queries by running: # npx browserslist last 1 Chrome version last 1 Firefox version last 2 Edge major versions last 2 Safari major versions last 2 iOS major versions Firefox ESR not IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line. not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. ================================================ FILE: sandbox/singleproject-sandbox/.editorconfig ================================================ # Editor configuration, see https://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.ts] quote_type = single [*.md] max_line_length = off trim_trailing_whitespace = false ================================================ FILE: sandbox/singleproject-sandbox/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events*.json speed-measure-plugin*.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db ================================================ FILE: sandbox/singleproject-sandbox/README.md ================================================ # SingleprojectSandbox This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.7. ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. ## Build Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). ================================================ FILE: sandbox/singleproject-sandbox/angular.json ================================================ { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "singleproject-sandbox": { "projectType": "application", "schematics": { "@schematics/angular:component": { "style": "scss" } }, "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/singleproject-sandbox", "index": "src/index.html", "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", "aot": true, "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.scss" ], "scripts": [] }, "configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "singleproject-sandbox:build" }, "configurations": { "production": { "browserTarget": "singleproject-sandbox:build:production" } } }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { "browserTarget": "singleproject-sandbox:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "main": "src/test.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.spec.json", "karmaConfig": "karma.conf.js", "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.scss" ], "scripts": [] } }, "lint": { "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ "tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json" ], "exclude": [ "**/node_modules/**" ] } }, "e2e": { "builder": "@angular-devkit/build-angular:protractor", "options": { "protractorConfig": "e2e/protractor.conf.js", "devServerTarget": "singleproject-sandbox:serve" }, "configurations": { "production": { "devServerTarget": "singleproject-sandbox:serve:production" } } } } }}, "defaultProject": "singleproject-sandbox" } ================================================ FILE: sandbox/singleproject-sandbox/e2e/protractor.conf.js ================================================ // @ts-check // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); /** * @type { import("protractor").Config } */ exports.config = { allScriptsTimeout: 11000, specs: [ './src/**/*.e2e-spec.ts' ], capabilities: { browserName: 'chrome' }, directConnect: true, baseUrl: 'http://localhost:4200/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, print: function() {} }, onPrepare() { require('ts-node').register({ project: require('path').join(__dirname, './tsconfig.json') }); jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: StacktraceOption.PRETTY } })); } }; ================================================ FILE: sandbox/singleproject-sandbox/e2e/src/app.e2e-spec.ts ================================================ import { AppPage } from './app.po'; import { browser, logging } from 'protractor'; describe('workspace-project App', () => { let page: AppPage; beforeEach(() => { page = new AppPage(); }); it('should display welcome message', () => { page.navigateTo(); expect(page.getTitleText()).toEqual('singleproject-sandbox app is running!'); }); afterEach(async () => { // Assert that there are no errors emitted from the browser const logs = await browser.manage().logs().get(logging.Type.BROWSER); expect(logs).not.toContain(jasmine.objectContaining({ level: logging.Level.SEVERE, } as logging.Entry)); }); }); ================================================ FILE: sandbox/singleproject-sandbox/e2e/src/app.po.ts ================================================ import { browser, by, element } from 'protractor'; export class AppPage { navigateTo(): Promise { return browser.get(browser.baseUrl) as Promise; } getTitleText(): Promise { return element(by.css('app-root .content span')).getText() as Promise; } } ================================================ FILE: sandbox/singleproject-sandbox/e2e/tsconfig.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/e2e", "module": "commonjs", "target": "es2018", "types": [ "jasmine", "jasminewd2", "node" ] } } ================================================ FILE: sandbox/singleproject-sandbox/karma.conf.js ================================================ // Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular-devkit/build-angular/plugins/karma') ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { dir: require('path').join(__dirname, './coverage/singleproject-sandbox'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false, restartOnFileChange: true }); }; ================================================ FILE: sandbox/singleproject-sandbox/package.json ================================================ { "name": "singleproject-sandbox", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "~10.1.6", "@angular/common": "~10.1.6", "@angular/compiler": "~10.1.6", "@angular/core": "~10.1.6", "@angular/forms": "~10.1.6", "@angular/platform-browser": "~10.1.6", "@angular/platform-browser-dynamic": "~10.1.6", "@angular/router": "~10.1.6", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" }, "devDependencies": { "@angular-devkit/build-angular": "~0.1001.7", "@angular/cli": "~10.1.7", "@angular/compiler-cli": "~10.1.6", "@types/node": "^12.11.1", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "codelyzer": "^6.0.0", "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", "typescript": "~4.0.2" } } ================================================ FILE: sandbox/singleproject-sandbox/src/app/app-routing.module.ts ================================================ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } ================================================ FILE: sandbox/singleproject-sandbox/src/app/app.component.html ================================================
{{ title }} app is running!

Resources

Here are some links to help you get started:

Next Steps

What do you want to do next with your app?

New Component
Angular Material
Add PWA Support
Add Dependency
Run and Watch Tests
Build for Production
ng generate component xyz
ng add @angular/material
ng add @angular/pwa
ng add _____
ng test
ng build --prod
================================================ FILE: sandbox/singleproject-sandbox/src/app/app.component.scss ================================================ ================================================ FILE: sandbox/singleproject-sandbox/src/app/app.component.spec.ts ================================================ import { TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ AppComponent ], }).compileComponents(); }); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); it(`should have as title 'singleproject-sandbox'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual('singleproject-sandbox'); }); it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement; expect(compiled.querySelector('.content span').textContent).toContain('singleproject-sandbox app is running!'); }); }); ================================================ FILE: sandbox/singleproject-sandbox/src/app/app.component.ts ================================================ import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'singleproject-sandbox'; } ================================================ FILE: sandbox/singleproject-sandbox/src/app/app.module.ts ================================================ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ================================================ FILE: sandbox/singleproject-sandbox/src/assets/.gitkeep ================================================ ================================================ FILE: sandbox/singleproject-sandbox/src/environments/environment.prod.ts ================================================ export const environment = { production: true }; ================================================ FILE: sandbox/singleproject-sandbox/src/environments/environment.ts ================================================ // This file can be replaced during build by using the `fileReplacements` array. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // The list of file replacements can be found in `angular.json`. export const environment = { production: false }; /* * For easier debugging in development mode, you can import the following file * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. * * This import should be commented out in production mode because it will have a negative impact * on performance if an error is thrown. */ // import 'zone.js/dist/zone-error'; // Included with Angular CLI. ================================================ FILE: sandbox/singleproject-sandbox/src/index.html ================================================ SingleprojectSandbox ================================================ FILE: sandbox/singleproject-sandbox/src/main.ts ================================================ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err)); ================================================ FILE: sandbox/singleproject-sandbox/src/polyfills.ts ================================================ /** * This file includes polyfills needed by Angular and is loaded before the app. * You can add your own extra polyfills to this file. * * This file is divided into 2 sections: * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. * 2. Application imports. Files imported after ZoneJS that should be loaded before your main * file. * * The current setup is for so-called "evergreen" browsers; the last versions of browsers that * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. * * Learn more in https://angular.io/guide/browser-support */ /*************************************************************************************************** * BROWSER POLYFILLS */ /** IE10 and IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** * Web Animations `@angular/platform-browser/animations` * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). */ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. /** * By default, zone.js will patch all possible macroTask and DomEvents * user can disable parts of macroTask/DomEvents patch by setting following flags * because those flags need to be set before `zone.js` being loaded, and webpack * will put import in the top of bundle, so user need to create a separate file * in this directory (for example: zone-flags.ts), and put the following flags * into that file, and then add the following code before importing zone.js. * import './zone-flags'; * * The flags allowed in zone-flags.ts are listed here. * * The following flags will work for all browsers. * * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames * * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js * with the following flag, it will bypass `zone.js` patch for IE/Edge * * (window as any).__Zone_enable_cross_context_check = true; * */ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ ================================================ FILE: sandbox/singleproject-sandbox/src/styles.scss ================================================ /* You can add global styles to this file, and also import other style files */ ================================================ FILE: sandbox/singleproject-sandbox/src/test.ts ================================================ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/zone-testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; declare const require: { context(path: string, deep?: boolean, filter?: RegExp): { keys(): string[]; (id: string): T; }; }; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. context.keys().map(context); ================================================ FILE: sandbox/singleproject-sandbox/tsconfig.app.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/app", "types": [] }, "files": [ "src/main.ts", "src/polyfills.ts" ], "include": [ "src/**/*.d.ts" ] } ================================================ FILE: sandbox/singleproject-sandbox/tsconfig.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, "target": "es2015", "module": "es2020", "lib": [ "es2018", "dom" ] } } ================================================ FILE: sandbox/singleproject-sandbox/tsconfig.spec.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", "types": [ "jasmine" ] }, "files": [ "src/test.ts", "src/polyfills.ts" ], "include": [ "src/**/*.spec.ts", "src/**/*.d.ts" ] } ================================================ FILE: sandbox/singleproject-sandbox/tslint.json ================================================ { "extends": "tslint:recommended", "rulesDirectory": [ "codelyzer" ], "rules": { "align": { "options": [ "parameters", "statements" ] }, "array-type": false, "arrow-return-shorthand": true, "curly": true, "deprecation": { "severity": "warning" }, "eofline": true, "import-blacklist": [ true, "rxjs/Rx" ], "import-spacing": true, "indent": { "options": [ "spaces" ] }, "max-classes-per-file": false, "max-line-length": [ true, 140 ], "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-empty": false, "no-inferrable-types": [ true, "ignore-params" ], "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, "no-var-requires": false, "object-literal-key-quotes": [ true, "as-needed" ], "quotemark": [ true, "single" ], "semicolon": { "options": [ "always" ] }, "space-before-function-paren": { "options": { "anonymous": "never", "asyncArrow": "always", "constructor": "never", "method": "never", "named": "never" } }, "typedef": [ true, "call-signature" ], "typedef-whitespace": { "options": [ { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" }, { "call-signature": "onespace", "index-signature": "onespace", "parameter": "onespace", "property-declaration": "onespace", "variable-declaration": "onespace" } ] }, "variable-name": { "options": [ "ban-keywords", "check-format", "allow-pascal-case" ] }, "whitespace": { "options": [ "check-branch", "check-decl", "check-operator", "check-separator", "check-type", "check-typecast" ] }, "component-class-suffix": true, "contextual-lifecycle": true, "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, "no-inputs-metadata-property": true, "no-output-native": true, "no-output-on-prefix": true, "no-output-rename": true, "no-outputs-metadata-property": true, "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true, "directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ] } } ================================================ FILE: sandbox/workspace/.editorconfig ================================================ # Editor configuration, see https://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.ts] quote_type = single [*.md] max_line_length = off trim_trailing_whitespace = false ================================================ FILE: sandbox/workspace/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events*.json speed-measure-plugin*.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db ================================================ FILE: sandbox/workspace/README.md ================================================ # Workspace This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.7. ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. ## Build Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). ================================================ FILE: sandbox/workspace/angular.json ================================================ { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": {} } ================================================ FILE: sandbox/workspace/package.json ================================================ { "name": "workspace", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint" }, "private": true, "dependencies": { "@angular/animations": "~10.1.6", "@angular/common": "~10.1.6", "@angular/compiler": "~10.1.6", "@angular/core": "~10.1.6", "@angular/forms": "~10.1.6", "@angular/platform-browser": "~10.1.6", "@angular/platform-browser-dynamic": "~10.1.6", "@angular/router": "~10.1.6", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" }, "devDependencies": { "@angular/cli": "~10.1.7", "@angular/compiler-cli": "~10.1.6", "@types/node": "^12.11.1", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "codelyzer": "^6.0.0", "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", "typescript": "~4.0.2" } } ================================================ FILE: sandbox/workspace/tsconfig.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, "target": "es2015", "module": "es2020", "lib": [ "es2018", "dom" ] } } ================================================ FILE: sandbox/workspace/tslint.json ================================================ { "extends": "tslint:recommended", "rulesDirectory": [ "codelyzer" ], "rules": { "align": { "options": [ "parameters", "statements" ] }, "array-type": false, "arrow-return-shorthand": true, "curly": true, "deprecation": { "severity": "warning" }, "eofline": true, "import-blacklist": [ true, "rxjs/Rx" ], "import-spacing": true, "indent": { "options": [ "spaces" ] }, "max-classes-per-file": false, "max-line-length": [ true, 140 ], "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-empty": false, "no-inferrable-types": [ true, "ignore-params" ], "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, "no-var-requires": false, "object-literal-key-quotes": [ true, "as-needed" ], "quotemark": [ true, "single" ], "semicolon": { "options": [ "always" ] }, "space-before-function-paren": { "options": { "anonymous": "never", "asyncArrow": "always", "constructor": "never", "method": "never", "named": "never" } }, "typedef": [ true, "call-signature" ], "typedef-whitespace": { "options": [ { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" }, { "call-signature": "onespace", "index-signature": "onespace", "parameter": "onespace", "property-declaration": "onespace", "variable-declaration": "onespace" } ] }, "variable-name": { "options": [ "ban-keywords", "check-format", "allow-pascal-case" ] }, "whitespace": { "options": [ "check-branch", "check-decl", "check-operator", "check-separator", "check-type", "check-typecast" ] }, "component-class-suffix": true, "contextual-lifecycle": true, "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, "no-inputs-metadata-property": true, "no-output-native": true, "no-output-on-prefix": true, "no-output-rename": true, "no-outputs-metadata-property": true, "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true } } ================================================ FILE: sandbox/workspace-existing/.editorconfig ================================================ # Editor configuration, see https://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.ts] quote_type = single [*.md] max_line_length = off trim_trailing_whitespace = false ================================================ FILE: sandbox/workspace-existing/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events*.json speed-measure-plugin*.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db ================================================ FILE: sandbox/workspace-existing/README.md ================================================ # WorkspaceExisting This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.7. ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. ## Build Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). ================================================ FILE: sandbox/workspace-existing/angular.json ================================================ { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "app": { "projectType": "application", "schematics": { "@schematics/angular:component": { "style": "scss" } }, "root": "projects/app", "sourceRoot": "projects/app/src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/app", "index": "projects/app/src/index.html", "main": "projects/app/src/main.ts", "polyfills": "projects/app/src/polyfills.ts", "tsConfig": "projects/app/tsconfig.app.json", "aot": true, "assets": [ "projects/app/src/favicon.ico", "projects/app/src/assets" ], "styles": [ "projects/app/src/styles.scss" ], "scripts": [] }, "configurations": { "production": { "fileReplacements": [ { "replace": "projects/app/src/environments/environment.ts", "with": "projects/app/src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "app:build" }, "configurations": { "production": { "browserTarget": "app:build:production" } } }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { "browserTarget": "app:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "main": "projects/app/src/test.ts", "polyfills": "projects/app/src/polyfills.ts", "tsConfig": "projects/app/tsconfig.spec.json", "karmaConfig": "projects/app/karma.conf.js", "assets": [ "projects/app/src/favicon.ico", "projects/app/src/assets" ], "styles": [ "projects/app/src/styles.scss" ], "scripts": [] } }, "lint": { "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ "projects/app/tsconfig.app.json", "projects/app/tsconfig.spec.json", "projects/app/e2e/tsconfig.json" ], "exclude": [ "**/node_modules/**" ] } }, "e2e": { "builder": "@angular-devkit/build-angular:protractor", "options": { "protractorConfig": "projects/app/e2e/protractor.conf.js", "devServerTarget": "app:serve" }, "configurations": { "production": { "devServerTarget": "app:serve:production" } } } } }}, "defaultProject": "app" } ================================================ FILE: sandbox/workspace-existing/package.json ================================================ { "name": "workspace-existing", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "~10.1.6", "@angular/common": "~10.1.6", "@angular/compiler": "~10.1.6", "@angular/core": "~10.1.6", "@angular/forms": "~10.1.6", "@angular/platform-browser": "~10.1.6", "@angular/platform-browser-dynamic": "~10.1.6", "@angular/router": "~10.1.6", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" }, "devDependencies": { "@angular-devkit/build-angular": "~0.1001.7", "@angular/cli": "~10.1.7", "@angular/compiler-cli": "~10.1.6", "@types/node": "^12.11.1", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "codelyzer": "^6.0.0", "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", "typescript": "~4.0.2" } } ================================================ FILE: sandbox/workspace-existing/projects/app/.browserslistrc ================================================ # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. # For additional information regarding the format and rule options, please see: # https://github.com/browserslist/browserslist#queries # For the full list of supported browsers by the Angular framework, please see: # https://angular.io/guide/browser-support # You can see what browsers were selected by your queries by running: # npx browserslist last 1 Chrome version last 1 Firefox version last 2 Edge major versions last 2 Safari major versions last 2 iOS major versions Firefox ESR not IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line. not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. ================================================ FILE: sandbox/workspace-existing/projects/app/e2e/protractor.conf.js ================================================ // @ts-check // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); /** * @type { import("protractor").Config } */ exports.config = { allScriptsTimeout: 11000, specs: [ './src/**/*.e2e-spec.ts' ], capabilities: { browserName: 'chrome' }, directConnect: true, baseUrl: 'http://localhost:4200/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, print: function() {} }, onPrepare() { require('ts-node').register({ project: require('path').join(__dirname, './tsconfig.json') }); jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: StacktraceOption.PRETTY } })); } }; ================================================ FILE: sandbox/workspace-existing/projects/app/e2e/src/app.e2e-spec.ts ================================================ import { AppPage } from './app.po'; import { browser, logging } from 'protractor'; describe('workspace-project App', () => { let page: AppPage; beforeEach(() => { page = new AppPage(); }); it('should display welcome message', () => { page.navigateTo(); expect(page.getTitleText()).toEqual('app app is running!'); }); afterEach(async () => { // Assert that there are no errors emitted from the browser const logs = await browser.manage().logs().get(logging.Type.BROWSER); expect(logs).not.toContain(jasmine.objectContaining({ level: logging.Level.SEVERE, } as logging.Entry)); }); }); ================================================ FILE: sandbox/workspace-existing/projects/app/e2e/src/app.po.ts ================================================ import { browser, by, element } from 'protractor'; export class AppPage { navigateTo(): Promise { return browser.get(browser.baseUrl) as Promise; } getTitleText(): Promise { return element(by.css('app-root .content span')).getText() as Promise; } } ================================================ FILE: sandbox/workspace-existing/projects/app/e2e/tsconfig.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "../../../tsconfig.json", "compilerOptions": { "outDir": "../../../out-tsc/e2e", "module": "commonjs", "target": "es2018", "types": [ "jasmine", "jasminewd2", "node" ] } } ================================================ FILE: sandbox/workspace-existing/projects/app/karma.conf.js ================================================ // Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular-devkit/build-angular/plugins/karma') ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { dir: require('path').join(__dirname, '../../coverage/app'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false, restartOnFileChange: true }); }; ================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app-routing.module.ts ================================================ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } ================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app.component.html ================================================
{{ title }} app is running!

Resources

Here are some links to help you get started:

Next Steps

What do you want to do next with your app?

New Component
Angular Material
Add PWA Support
Add Dependency
Run and Watch Tests
Build for Production
ng generate component xyz
ng add @angular/material
ng add @angular/pwa
ng add _____
ng test
ng build --prod
================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app.component.scss ================================================ ================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app.component.spec.ts ================================================ import { TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ AppComponent ], }).compileComponents(); }); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); it(`should have as title 'app'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual('app'); }); it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement; expect(compiled.querySelector('.content span').textContent).toContain('app app is running!'); }); }); ================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app.component.ts ================================================ import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'app'; } ================================================ FILE: sandbox/workspace-existing/projects/app/src/app/app.module.ts ================================================ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ================================================ FILE: sandbox/workspace-existing/projects/app/src/assets/.gitkeep ================================================ ================================================ FILE: sandbox/workspace-existing/projects/app/src/environments/environment.prod.ts ================================================ export const environment = { production: true }; ================================================ FILE: sandbox/workspace-existing/projects/app/src/environments/environment.ts ================================================ // This file can be replaced during build by using the `fileReplacements` array. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // The list of file replacements can be found in `angular.json`. export const environment = { production: false }; /* * For easier debugging in development mode, you can import the following file * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. * * This import should be commented out in production mode because it will have a negative impact * on performance if an error is thrown. */ // import 'zone.js/dist/zone-error'; // Included with Angular CLI. ================================================ FILE: sandbox/workspace-existing/projects/app/src/index.html ================================================ App ================================================ FILE: sandbox/workspace-existing/projects/app/src/main.ts ================================================ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err)); ================================================ FILE: sandbox/workspace-existing/projects/app/src/polyfills.ts ================================================ /** * This file includes polyfills needed by Angular and is loaded before the app. * You can add your own extra polyfills to this file. * * This file is divided into 2 sections: * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. * 2. Application imports. Files imported after ZoneJS that should be loaded before your main * file. * * The current setup is for so-called "evergreen" browsers; the last versions of browsers that * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. * * Learn more in https://angular.io/guide/browser-support */ /*************************************************************************************************** * BROWSER POLYFILLS */ /** IE10 and IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** * Web Animations `@angular/platform-browser/animations` * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). */ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. /** * By default, zone.js will patch all possible macroTask and DomEvents * user can disable parts of macroTask/DomEvents patch by setting following flags * because those flags need to be set before `zone.js` being loaded, and webpack * will put import in the top of bundle, so user need to create a separate file * in this directory (for example: zone-flags.ts), and put the following flags * into that file, and then add the following code before importing zone.js. * import './zone-flags'; * * The flags allowed in zone-flags.ts are listed here. * * The following flags will work for all browsers. * * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames * * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js * with the following flag, it will bypass `zone.js` patch for IE/Edge * * (window as any).__Zone_enable_cross_context_check = true; * */ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ ================================================ FILE: sandbox/workspace-existing/projects/app/src/styles.scss ================================================ /* You can add global styles to this file, and also import other style files */ ================================================ FILE: sandbox/workspace-existing/projects/app/src/test.ts ================================================ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/zone-testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; declare const require: { context(path: string, deep?: boolean, filter?: RegExp): { keys(): string[]; (id: string): T; }; }; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. context.keys().map(context); ================================================ FILE: sandbox/workspace-existing/projects/app/tsconfig.app.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "../../out-tsc/app", "types": [] }, "files": [ "src/main.ts", "src/polyfills.ts" ], "include": [ "src/**/*.d.ts" ] } ================================================ FILE: sandbox/workspace-existing/projects/app/tsconfig.spec.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "../../out-tsc/spec", "types": [ "jasmine" ] }, "files": [ "src/test.ts", "src/polyfills.ts" ], "include": [ "src/**/*.spec.ts", "src/**/*.d.ts" ] } ================================================ FILE: sandbox/workspace-existing/projects/app/tslint.json ================================================ { "extends": "../../tslint.json", "rules": { "directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ] } } ================================================ FILE: sandbox/workspace-existing/tsconfig.json ================================================ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, "target": "es2015", "module": "es2020", "lib": [ "es2018", "dom" ] } } ================================================ FILE: sandbox/workspace-existing/tslint.json ================================================ { "extends": "tslint:recommended", "rulesDirectory": [ "codelyzer" ], "rules": { "align": { "options": [ "parameters", "statements" ] }, "array-type": false, "arrow-return-shorthand": true, "curly": true, "deprecation": { "severity": "warning" }, "eofline": true, "import-blacklist": [ true, "rxjs/Rx" ], "import-spacing": true, "indent": { "options": [ "spaces" ] }, "max-classes-per-file": false, "max-line-length": [ true, 140 ], "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-empty": false, "no-inferrable-types": [ true, "ignore-params" ], "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, "no-var-requires": false, "object-literal-key-quotes": [ true, "as-needed" ], "quotemark": [ true, "single" ], "semicolon": { "options": [ "always" ] }, "space-before-function-paren": { "options": { "anonymous": "never", "asyncArrow": "always", "constructor": "never", "method": "never", "named": "never" } }, "typedef": [ true, "call-signature" ], "typedef-whitespace": { "options": [ { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" }, { "call-signature": "onespace", "index-signature": "onespace", "parameter": "onespace", "property-declaration": "onespace", "variable-declaration": "onespace" } ] }, "variable-name": { "options": [ "ban-keywords", "check-format", "allow-pascal-case" ] }, "whitespace": { "options": [ "check-branch", "check-decl", "check-operator", "check-separator", "check-type", "check-typecast" ] }, "component-class-suffix": true, "contextual-lifecycle": true, "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, "no-inputs-metadata-property": true, "no-output-native": true, "no-output-on-prefix": true, "no-output-rename": true, "no-outputs-metadata-property": true, "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true } } ================================================ FILE: src/builders/build/index.ts ================================================ import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString, BuilderRun } from '@angular-devkit/architect'; import { DevServerBuilderOutput } from '@angular-devkit/build-angular'; import { from, Observable, combineLatest } from 'rxjs'; import { mapTo, switchMap, tap } from 'rxjs/operators'; import { openElectron } from '../util/electron'; import { basename, join } from 'path'; import { writeFileSync, existsSync, readFileSync } from 'fs'; import { JsonObject } from '@angular-devkit/core'; import { symlinkSync, removeSync, ensureDirSync } from 'fs-extra'; import { DevServer } from '../util/dev.server/dev.server'; const InjectPlugin = require('webpack-inject-plugin').default; import { getExternals } from '../util/externals'; import * as findFreePort from 'find-free-port'; export interface NGTronBuildOptions extends JsonObject { mainTarget: string; outputPath: string; rendererOutputPath: string; rendererTargets: string[]; watch: boolean; serve: boolean; package: string; devServerPort: number; } export const execute = (options: NGTronBuildOptions, context: BuilderContext): Observable => { let devServer: DevServer; const electronPkgPath = join(context.workspaceRoot, options.package); const mainTarget = targetFromTargetString(options.mainTarget); async function init() { removeSync(join(context.workspaceRoot, options.outputPath)); ensureDirSync(join(context.workspaceRoot, options.outputPath)); const electronPkgString = readFileSync(electronPkgPath, { encoding: 'utf-8' }); const electronPkg = JSON.parse(electronPkgString); const externals = getExternals(electronPkg.dependencies || {}); // Add the renderer targets const builderRuns$: Observable[] = options.rendererTargets.map((target) => { const rendererTarget = targetFromTargetString(target); const overrides = { outputPath: options.rendererOutputPath + '/' + rendererTarget.project, watch: options.watch, baseHref: './', aot: false, optimization: false, webpackConfig: { externals: externals, }, }; return from(context.scheduleTarget(rendererTarget, overrides)); }); const mainWebpackConfig: any = { mode: 'development', node: { __dirname: false, }, externals: { electron: 'commonjs electron', ws: 'commonjs ws', }, }; if (options.serve && options.watch) { const freePorts = await findFreePort(options.devServerPort); devServer = new DevServer(freePorts[0]); mainWebpackConfig.plugins = [ new InjectPlugin(function () { return devServer.getInject(); }), ]; } // Add the node js main target const mainOptions = await context.getTargetOptions(mainTarget); const mainOverrides: any = { watch: options.watch, outputPath: options.outputPath, webpackConfigObject: mainWebpackConfig, }; builderRuns$.push(from(context.scheduleTarget(mainTarget, mainOverrides))); // Symlink node modules for dev mode if (options.serve) { const electronBuildNodeModules = join(context.workspaceRoot, options.outputPath, 'node_modules'); if (!existsSync(electronBuildNodeModules)) { const workspaceNodeModules = join(context.workspaceRoot, 'node_modules'); symlinkSync(workspaceNodeModules, electronBuildNodeModules, 'junction'); } } const result: [Observable[], JsonObject] = [builderRuns$, mainOptions]; return result; } let allBuildOnce = false; return from(init()).pipe( switchMap(([builderRuns$, mainOptions]) => combineLatest(builderRuns$).pipe( switchMap((runs) => combineLatest( runs.map((run) => { if (options.serve) { return run.output.pipe( tap((builderOutput: BuilderOutput) => { if (builderOutput.info.name.startsWith('@richapps/ngnode') && options.serve) { if (allBuildOnce) { openElectron(join(context.workspaceRoot, options.outputPath), context).subscribe(); } } else { if (devServer) { devServer.sendUpdate({ type: 'renderer', info: builderOutput }); } } }) ); } else { return from(run.result); } }) ) ), tap(() => { if (!allBuildOnce) { // copy electron package.json const electronPKG = JSON.parse(readFileSync(electronPkgPath, { encoding: 'utf-8' })); const main = (Array.isArray(mainOptions.main) ? mainOptions.main[0] : mainOptions.main) as string; electronPKG.main = basename(main, '.ts') + '.js'; const electronPkgDistPath = join(context.workspaceRoot, options.outputPath, 'package.json'); writeFileSync(electronPkgDistPath, JSON.stringify(electronPKG, null, 4), { encoding: 'utf-8' }); openElectron(join(context.workspaceRoot, options.outputPath), context).subscribe(); allBuildOnce = true; } if (options.watch) { context.reportRunning(); } }), mapTo({ success: true }) ) ) ); }; export default createBuilder(execute); ================================================ FILE: src/builders/build/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "title": "Dev Server Target", "description": "Dev Server target options for Build Facade.", "type": "object", "properties": { "rendererTargets": { "description": "One or more renderer targets for your project (angular projects)", "type": "array", "items": { "type": "string", "pattern": ".+:.+(:.+)?" } }, "mainTarget": { "description": "The main process for your electron project (a node app)", "type": "string", "pattern": ".+:.+(:.+)?" }, "devServerPort": { "type": "number", "description": "the port where the dev server listens for changes.", "default": 6000 }, "outputPath": { "type": "string", "description": "Path where the electron app will be build." }, "watch": { "type": "boolean", "description": "" }, "serve": { "type": "boolean", "description": "", "boolean": false }, "rendererOutputPath": { "type": "string", "description": "Path where the renderer apps will be created." }, "package": { "type": "string", "description": "Path to the package json for the electron app." } }, "additionalProperties": false, "required": ["mainTarget", "rendererTargets"] } ================================================ FILE: src/builders/builders.json ================================================ { "builders": { "build": { "implementation": "./build", "schema": "./build/schema.json", "description": "build and watch electron" }, "package": { "implementation": "./package", "schema": "./package/schema.json", "description": "package electron" }, "serve": { "implementation": "./serve", "schema": "./serve/schema.json", "description": "serve electron app in the browser" } } } ================================================ FILE: src/builders/package/index.ts ================================================ import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString } from "@angular-devkit/architect"; import { DevServerBuilderOptions, DevServerBuilderOutput } from "@angular-devkit/build-angular"; import { from, Observable } from "rxjs"; import { filter, mapTo, switchMap, tap } from "rxjs/operators"; import { buildElectron } from "../util/electron"; import { electronBuildWebpackConfigTransformFactory } from "../util/util"; import { buildWebpackBrowser } from "@angular-devkit/build-angular/src/browser"; import { copyFileSync, writeFileSync } from "fs"; import { basename, join } from "path"; import { JsonObject } from "@angular-devkit/core"; export interface NGTronPackageOptions extends JsonObject { buildTarget: string; packagerConfig: any; } export const execute = (options: NGTronPackageOptions, context: BuilderContext): Observable => { const buildTarget = targetFromTargetString(options.buildTarget); return from(context.getTargetOptions(buildTarget)).pipe( switchMap(options => context.scheduleTarget(buildTarget, options)), switchMap(run => run.output), switchMap((x: any) => buildElectron(options.packagerConfig)), mapTo({ success: true }) ); /* async function setup() { const buildTarget = targetFromTargetString(options.buildTarget); const buildOptions = await context.getTargetOptions(buildTarget); buildOptions.watch = false; buildOptions.baseHref = "./"; return { buildOptions: buildOptions, }; } return from(setup()).pipe( switchMap(opt => { return buildWebpackBrowser(opt.buildOptions as any, context, { webpackConfiguration: electronBuildWebpackConfigTransformFactory(opt.buildOptions, opt.buildElectronOptions, context) }); }), filter((val, index) => index < 1), tap(result => { // Copy electron main const fromMain = join(context.workspaceRoot, options.electronMain as string); const toMain = join(result.outputPath, basename(options.electronMain as string)); copyFileSync(fromMain, toMain); // write electron package to dist writeFileSync(join(result.outputPath, "package.json"), JSON.stringify(options.electronPackage), { encoding: "utf-8" }); }), switchMap((x: any) => buildElectron(options.packagerConfig)), mapTo({ success: true }) ); */ }; export default createBuilder(execute); ================================================ FILE: src/builders/package/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "title": "Dev Server Target", "description": "Dev Server target options for Build Facade.", "type": "object", "properties": { "buildTarget": { "type": "string", "description": "Target to serve.", "pattern": ".+:.+(:.+)?" }, "packagerConfig": { "type": "object" } }, "additionalProperties": false, "required": ["buildTarget"] } ================================================ FILE: src/builders/serve/index.ts ================================================ import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString } from '@angular-devkit/architect'; import { DevServerBuilderOutput } from '@angular-devkit/build-angular'; import { from, Observable } from 'rxjs'; import { mapTo, switchMap, tap } from 'rxjs/operators'; import { JsonObject } from '@angular-devkit/core'; export interface NGTronServeOptions extends JsonObject { buildTarget: string; } export const execute = (options: NGTronServeOptions, context: BuilderContext): Observable => { const buildTarget = targetFromTargetString(options.buildTarget); return from(context.getTargetOptions(buildTarget)).pipe( switchMap((options) => { return context.scheduleTarget(buildTarget, { ...options, watch: true, serve: true, }); }), switchMap((run) => run.progress), mapTo({ success: true }) ); }; export default createBuilder(execute); ================================================ FILE: src/builders/serve/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "title": "Dev Server Target", "description": "Dev Server target options for Build Facade.", "type": "object", "properties": { "buildTarget": { "type": "string", "description": "Target to serve.", "pattern": ".+:.+(:.+)?" } }, "additionalProperties": false, "required": ["buildTarget"] } ================================================ FILE: src/builders/util/dev.server/dev.server.ts ================================================ import { readFileSync } from 'fs-extra'; import { join } from 'path'; const WebSocket = require('ws'); export class DevServer { clients: any[] = []; constructor(private port) { this.init(); } init() { const wss = new WebSocket.Server({ port: this.port }); wss.on('connection', (ws) => { this.clients.push(ws); }); } sendUpdate(data) { this.clients.forEach((ws) => { ws.send(JSON.stringify(data)); }); } getInject() { let inject = readFileSync(join(__dirname, 'inject.js'), { encoding: 'utf-8' }); inject = inject.replace(/\${this.port}/, this.port); return inject; } } ================================================ FILE: src/builders/util/electron.ts ================================================ import { DevServerBuilderOutput } from "@angular-devkit/build-angular"; import { BuilderContext, BuilderOutput } from "@angular-devkit/architect"; import { Observable } from "rxjs"; import { ChildProcess, spawn } from "child_process"; import { isMac } from "./util"; const builder = require("electron-builder"); let electronProcess: ChildProcess; export function openElectron(distFolder, context: BuilderContext): Observable { return new Observable(observer => { const electronBin = isMac() ? "./node_modules/.bin/electron" : "node_modules/electron/dist/electron"; if (electronProcess) { electronProcess.kill(); } const ls: ChildProcess = spawn(electronBin, [distFolder]); electronProcess = ls; ls.stdout.on("data", function (data) { context.logger.info(data.toString()); }); ls.stderr.on("data", function (data) { context.logger.error(data.toString()); }); ls.on("exit", function (code) { observer.next({ success: true }); observer.complete(); }); //} else { observer.next({ success: true }); observer.complete(); //} }); } export function buildElectron(config): Observable { return new Observable(observer => { builder.build(config).then( () => { observer.next({ success: true }); observer.complete(); }, e => { console.log("Error ", e); observer.error(); } ); }); } ================================================ FILE: src/builders/util/externals.ts ================================================ const NODE_BUILD_IN_MODULES = [ "assert", "async_hooks", "buffer", "child_process", "cluster", "console", "constants", "crypto", "dgram", "dns", "domain", "events", "fs", "http", "http2", "https", "inspector", "module", "net", "os", "path", "perf_hooks", "process", "punycode", "querystring", "readline", "repl", "stream", "string_decoder", "timers", "tls", "trace_events", "tty", "url", "util", "v8", "vm", "zlib" ]; export const getExternals = (pkgDependencies) => { const externalDependencies = ['electron', ...Object.keys(pkgDependencies), ...NODE_BUILD_IN_MODULES]; let externals: any = [ (function () { return function (context, request, callback) { if (externalDependencies.indexOf(request) >= 0) { if (externalDependencies.hasOwnProperty(request)) { // const modulePath = join(rootNodeModules, request); return callback(null, "require('" + request + "')"); } return callback(null, "require('" + request + "')"); } return callback(); }; })() ]; return externals; } ================================================ FILE: src/builders/util/util.ts ================================================ import {join} from "path"; import {BuilderContext} from "@angular-devkit/architect"; export const BUILD_IN_NODE_MODULES = ["fs", "path"]; // TODO: add all build in node modules export const BUILD_IN_ELECTRON_MODULES = ["electron", "app", "shell"]; // TODO: add all build in electron modules export function isMac() { return /^darwin/.test(process.platform); } export const noneElectronWebpackConfigTransformFactory: any = (options: any, buildElectronOptions: any, context: BuilderContext) => { context.logger.info("Electron Browser Serve Webpack"); return webpackConfig => { const externalDependencies = buildElectronOptions.electronPackage.dependencies; let EXTERNALS = Object.keys(externalDependencies); EXTERNALS = [...EXTERNALS, ...BUILD_IN_ELECTRON_MODULES, ...BUILD_IN_NODE_MODULES]; webpackConfig.externals = [ (function () { return function (context, request, callback) { if (EXTERNALS.indexOf(request) >= 0) { return callback(null, "'undefined'"); } return callback(); }; })() ]; webpackConfig.optimization.splitChunks = false; // What the F! return webpackConfig; }; }; export const electronServeWebpackConfigTransformFactory: any = (options: any, buildElectronOptions: any, context: BuilderContext) => { context.logger.info("Electron Serve Webpack"); return webpackConfig => { const externalDependencies = buildElectronOptions.electronPackage.dependencies; const rootNodeModules = join(context.workspaceRoot, "node_modules"); let EXTERNALS = Object.keys(externalDependencies); EXTERNALS = [...EXTERNALS, ...BUILD_IN_ELECTRON_MODULES, ...BUILD_IN_NODE_MODULES]; webpackConfig.externals = [ (function () { return function (context, request, callback) { console.log("Request ", request); if (EXTERNALS.indexOf(request) >= 0) { if (externalDependencies.hasOwnProperty(request)) { const modulePath = join(rootNodeModules, request); return callback(null, "require('" + modulePath + "')"); } return callback(null, "require('" + request + "')"); } return callback(); }; })() ]; webpackConfig.target = "electron-renderer"; return webpackConfig; }; }; // Package export const electronBuildWebpackConfigTransformFactory: any = (options: any, buildElectronOptions: any, context: BuilderContext) => { return webpackConfig => { const externalDependencies = buildElectronOptions.electronPackage.dependencies; let EXTERNALS = Object.keys(externalDependencies); EXTERNALS = [...EXTERNALS, ...BUILD_IN_ELECTRON_MODULES, ...BUILD_IN_NODE_MODULES]; webpackConfig.externals = [ (function () { return function (context, request, callback) { if (EXTERNALS.indexOf(request) >= 0) { return callback(null, "require('" + request + "')"); } return callback(); }; })() ]; webpackConfig.target = "electron-renderer"; webpackConfig.optimization.splitChunks = false; // What the F! console.log(webpackConfig); return webpackConfig; }; }; import * as ts from "typescript"; export function compile(fileNames: string[], options: ts.CompilerOptions): void { let program = ts.createProgram(fileNames, options); let emitResult = program.emit(); let allDiagnostics = ts .getPreEmitDiagnostics(program) .concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { if (diagnostic.file) { let {line, character} = diagnostic.file.getLineAndCharacterOfPosition( diagnostic.start! ); let message = ts.flattenDiagnosticMessageText( diagnostic.messageText, "\n" ); console.log( `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` ); } else { console.log( `${ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")}` ); } }); let exitCode = emitResult.emitSkipped ? 1 : 0; } ================================================ FILE: src/schematics/add-to-project/index.ts ================================================ import { Tree } from "@angular-devkit/schematics/src/tree/interface"; import { SchematicContext, chain, Rule, externalSchematic, mergeWith, apply, url, move, template } from "@angular-devkit/schematics"; import { updateWorkspace } from "@schematics/angular/utility/config"; import { getWorkspace as getWorkspace2 } from "@schematics/angular/utility/config"; import { ProjectType } from "@schematics/angular/utility/workspace-models"; import { experimental } from "@angular-devkit/core"; import { JsonParseMode, parseJson } from '@angular-devkit/core'; export interface NgGenerateOptions { project: string; } export default function (options: NgGenerateOptions): Rule { return (tree: Tree, _context: SchematicContext) => { return chain([ addRendererProject(options), addElectronProject(options), updateElectronWorkspace(options), addMainProject(options), updateMainWorkspace(options), updateRendererWorkspace(options), updateRendererTSConfig(options) ])(tree, _context); }; } function updateElectronWorkspace(options): Rule { return async (tree: Tree, _context: SchematicContext) => { const workspace: any = getWorkspace2(tree); const projectName = options.project + '-electron'; const rendererName = options.project + '-renderer'; const mainName = options.project + '-main'; workspace.projects[projectName] = { projectType: ProjectType.Application, root: "projects/electron", architect: { build: { builder: "@richapps/ngtron:build", options: { rendererTargets: [rendererName + ":build"], mainTarget: mainName + ":build", outputPath: "dist/" + projectName, rendererOutputPath: "dist/" + projectName + "/renderers", package: "projects/" + projectName + "/package.json" } }, serve: { builder: "@richapps/ngtron:serve", options: { buildTarget: projectName + ":build" } }, package: { builder: "@richapps/ngtron:package", options: { buildTarget: projectName + ":build", packagerConfig: { mac: ["zip", "dmg"], config: { appId: "some.id", npmRebuild: false, asar: false, directories: { app: "dist/" + projectName, output: "dist/" + projectName + "-package", buildResources: "project/" + projectName + "/electronResources" }, electronVersion: "4.0.0" } } } } } } return updateWorkspace(workspace); } } function updateMainWorkspace(options): Rule { return async (tree: Tree, _context: SchematicContext) => { const workspace: any = getWorkspace2(tree); const projectName = options.project + '-main'; workspace.projects[projectName] = { projectType: "application", root: "projects/" + projectName, sourceRoot: "projects/" + projectName + "/src", prefix: "app", architect: { build: { builder: "@richapps/ngnode:build", options: { outputPath: "dist/" + projectName, main: "projects/" + projectName + "/src/main.ts", tsConfig: "projects/" + projectName + "/tsconfig.json" } } } } return updateWorkspace(workspace); } } function updateRendererWorkspace(options): Rule { return async (tree: Tree, _context: SchematicContext) => { const workspace: any = getWorkspace2(tree); const projectName = options.project + '-renderer'; workspace.projects[projectName].architect.build.builder = '@richapps/build-angular:browser' return updateWorkspace(workspace); } } function updateRendererTSConfig(options): Rule { return async (tree: Tree, _context: SchematicContext) => { const config: any = getTSAppConfig(tree, options.project); config.compilerOptions.target = 'es5'; return updateTSAppConfig(config, options.project); } } export function updateTSAppConfig(config: any, project): Rule { return (host: Tree, context: SchematicContext) => { host.overwrite(getTSAppConfigPath(host, project), JSON.stringify(config, null, 2)); }; } export function getTSAppConfigPath(host: Tree, project): string { const possibleFiles = ['/projects/' + project + '-renderer/tsconfig.app.json']; const path = possibleFiles.filter(path => host.exists(path))[0]; return path; } export function getTSAppConfig(host: Tree, project: string): any { const path = getTSAppConfigPath(host, project); const configBuffer = host.read(path); if (configBuffer === null) { throw new Error(`Could not find (${path})`); } const content = configBuffer.toString(); return parseJson(content, JsonParseMode.Loose) as {} as any; } export const addElectronProject = (options) => { return addElectronFiles('projects/' + options.project + '-electron'); } export const addMainProject = (options) => { return addMainFiles('projects/' + options.project + '-main', options.project + '-renderer'); } export const addRendererProject = (options: NgGenerateOptions) => { return externalSchematic('@schematics/angular', 'application', { name: options.project + '-renderer' }); } function addElectronFiles(dest) { return (host: Tree, context: SchematicContext) => { // const project = getProject(host, options.project); return mergeWith( apply(url(`../files/electron`), [ template({ tmpl: '' }), move(dest) ])); } } function addMainFiles(dest, renderer) { return (host: Tree, context: SchematicContext) => { // const project = getProject(host, options.project); return mergeWith( apply(url(`../files/main`), [ template({ renderer, tmpl: '' }), move(dest) ])); } } ================================================ FILE: src/schematics/add-to-project/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "id": "ngtron-generate", "title": "NGTron application schematic", "type": "object", "properties": { "project": { "type": "string", "description": "The name of the project.", "x-prompt": "What name should your project have?" } }, "required": [], "additionalProperties": false } ================================================ FILE: src/schematics/application/index.ts ================================================ import { Tree } from '@angular-devkit/schematics/src/tree/interface'; import { SchematicContext, chain, Rule, externalSchematic, mergeWith, apply, url, move, template, noop } from '@angular-devkit/schematics'; import { updateWorkspace } from '@schematics/angular/utility/config'; import { getWorkspace as getWorkspace2 } from '@schematics/angular/utility/config'; import { ProjectType } from '@schematics/angular/utility/workspace-models'; import { JsonParseMode, parseJson } from '@angular-devkit/core'; import * as inquirer from 'inquirer'; import { Observable } from 'rxjs'; export interface NgGenerateOptions { project: string; singleProject: boolean; monoRepo: boolean; rendererRoot: string; rendererPrefix: string; mainPrefix: string; electronPrefix: string; projectRoot: string; name: string; electronName: string; mainName: string; rendererName: string; createRenderer: boolean; } async function setup(tree, options, context: SchematicContext) { if (!options.name && !options.project) { const result = await inquirer.prompt<{ analytics: boolean }>([ { name: 'project', message: `What name should your project have?`, }, ]); options.project = result.project; } if (options.name && !options.project) { options.project = options.name; } const workspace: any = getWorkspace2(tree); options.projectRoot = workspace.newProjectRoot || 'projects'; const rendererProjectExists = workspace.projects.hasOwnProperty(options.project); let isMonoRepo = true; if (rendererProjectExists) { isMonoRepo = workspace.projects[options.project].sourceRoot !== 'src'; options.rendererRoot = workspace.projects[options.project].root; } else { options.rendererRoot = options.singleProject ? options.projectRoot + '/' + options.project : options.projectRoot + '/' + options.project + options.rendererPrefix; } options.monoRepo = isMonoRepo; options.electronName = options.singleProject ? options.project : options.project + options.electronPrefix; options.rendererName = options.singleProject ? options.project : options.project + options.rendererPrefix; options.mainName = options.singleProject ? options.project : options.project + options.mainPrefix; if (rendererProjectExists) { options.rendererName = options.project; } options.createRenderer = !rendererProjectExists; } function setupRule(options: any): Rule { return (host: Tree, context: SchematicContext) => { const observer = new Observable((observer) => { setup(host, options, context).then(() => { observer.next(host); observer.complete(); }); }); return observer; }; } export default function (options: NgGenerateOptions): Rule { return (tree: Tree, context: SchematicContext) => { const rules = [ setupRule(options), addRendererProject(options), addElectronProject(options), updateElectronWorkspace(options), addMainProject(options), updateMainWorkspace(options), updateRendererWorkspace(options), updateRendererTSConfig(options), ]; return chain(rules)(tree, context); }; } function updateElectronWorkspace(options): Rule { return (tree: Tree, context: SchematicContext) => { context.logger.info('⚙️ updateElectronWorkspace'); const workspace: any = getWorkspace2(tree); let architectBuildName = options.singleProject ? 'build-electron' : 'build'; let architectServeName = options.singleProject ? 'serve-electron' : 'serve'; let architectPackageName = options.singleProject ? 'package-electron' : 'package'; let mainBuildTarget = options.singleProject ? options.project + ':build-node' : options.mainName + ':build'; let packagePath = options.singleProject ? options.rendererRoot + '/electron/package.json' : options.projectRoot + '/' + options.electronName + '/package.json'; let buildResourcesPath = options.singleProject ? options.rendererRoot + '/electron/electronResources' : options.projectRoot + '/' + options.electronName + '/electronResources'; if (!options.singleProject) { workspace.projects[options.electronName] = { projectType: ProjectType.Application, root: options.projectRoot + '/electron', architect: {}, }; } const architect = workspace.projects[options.electronName].architect; architect[architectBuildName] = { builder: '@richapps/ngtron:build', options: { rendererTargets: [options.rendererName + ':build'], mainTarget: mainBuildTarget, outputPath: 'dist/' + options.electronName, rendererOutputPath: 'dist/' + options.electronName + '/renderers', package: packagePath, }, }; architect[architectServeName] = { builder: '@richapps/ngtron:serve', options: { buildTarget: options.electronName + ':' + architectBuildName, }, }; architect[architectPackageName] = { builder: '@richapps/ngtron:package', options: { buildTarget: options.electronName + ':' + architectBuildName, packagerConfig: { mac: ['zip', 'dmg'], config: { appId: 'some.id', npmRebuild: false, asar: false, directories: { app: 'dist/' + options.electronName, output: 'dist/' + options.electronName + '-package', buildResources: buildResourcesPath, }, electronVersion: '4.0.0', }, }, }, }; return updateWorkspace(workspace); }; } function updateMainWorkspace(options): Rule { return (tree: Tree, context: SchematicContext) => { context.logger.info('⚙️ updateMainWorkspace'); const workspace: any = getWorkspace2(tree); const architectBuildName = options.singleProject ? 'build-node' : 'build'; const mainTsPath = options.singleProject ? options.rendererRoot + '/electron/src/main.ts' : options.projectRoot + '/' + options.mainName + '/src/main.ts'; const mainTsConfigPath = options.singleProject ? options.rendererRoot + '/electron/tsconfig.json' : options.projectRoot + '/' + options.mainName + '/tsconfig.json'; if (!options.singleProject) { workspace.projects[options.mainName] = { projectType: 'application', root: options.projectRoot + '/' + options.mainName, sourceRoot: options.projectRoot + '/' + options.mainName + '/src', architect: {}, }; } const architect = workspace.projects[options.mainName].architect; architect[architectBuildName] = { builder: '@richapps/ngnode:build', options: { outputPath: 'dist/' + options.mainName, main: mainTsPath, tsConfig: mainTsConfigPath, }, }; return updateWorkspace(workspace); }; } function updateRendererWorkspace(options): Rule { return (tree: Tree, context: SchematicContext) => { context.logger.info('⚙️ updateRendererWorkspace'); const workspace: any = getWorkspace2(tree); workspace.projects[options.rendererName].architect.build.builder = '@richapps/build-angular:browser'; return updateWorkspace(workspace); }; } function updateRendererTSConfig(options): Rule { return (tree: Tree, context: SchematicContext) => { context.logger.info('️️⚙️ updateRendererTSConfig'); const tsConfigRoot = options.monoRepo ? options.rendererRoot : ''; const config: any = getTSAppConfig(tree, tsConfigRoot); config.compilerOptions.target = 'es5'; if (!options.isMonoRepo) { config.exclude = config.exclude ? [...config.exclude, 'src/electron/**/*'] : (config.exclude = ['src/electron/**/*']); } return updateTSAppConfig(config, tsConfigRoot); }; } export function updateTSAppConfig(config: any, rendererRoot): Rule { return (host: Tree) => { host.overwrite(getTSAppConfigPath(host, rendererRoot), JSON.stringify(config, null, 2)); }; } export function getTSAppConfigPath(host: Tree, rendererRoot): string { const possibleFiles = [rendererRoot + '/tsconfig.app.json']; const path = possibleFiles.filter((path) => host.exists(path))[0]; return path; } export function getTSAppConfig(host: Tree, project: string): any { const path = getTSAppConfigPath(host, project); const configBuffer = host.read(path); if (configBuffer === null) { throw new Error(`Could not find (${path})`); } const content = configBuffer.toString(); return (parseJson(content, JsonParseMode.Loose) as {}) as any; } export const addElectronProject = (options) => { return (host: Tree, context: SchematicContext) => { context.logger.info('⚙️ addElectronProject'); const dir = options.singleProject ? options.rendererRoot + '/electron' : options.projectRoot + '/' + options.project + options.electronPrefix; return addElectronFiles(dir); }; }; export const addMainProject = (options) => { return (host: Tree, context: SchematicContext) => { context.logger.info('⚙️ addMainProject'); const dir = options.singleProject ? options.rendererRoot + '/electron' : options.projectRoot + '/' + options.project + options.mainPrefix; return addMainFiles(dir, options.rendererName); }; }; export const addRendererProject = (options: NgGenerateOptions) => { return (host: Tree, context: SchematicContext) => { if (options.createRenderer) { context.logger.info('⚙️ addRendererProject'); return externalSchematic('@schematics/angular', 'application', { name: options.rendererName, }); } }; }; function addElectronFiles(dest) { return () => { // const project = getProject(host, options.project); return mergeWith( apply(url(`../files/electron`), [ template({ tmpl: '', }), move(dest), ]) ); }; } function addMainFiles(dest, renderer) { return () => { // const project = getProject(host, options.project); return mergeWith( apply(url(`../files/main`), [ template({ renderer, tmpl: '', }), move(dest), ]) ); }; } ================================================ FILE: src/schematics/application/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "id": "ngtron-generate", "title": "NGTron application schematic", "type": "object", "properties": { "singleProject": { "type": "boolean", "default": false }, "rendererPrefix": { "type": "string", "default": "-renderer" }, "mainPrefix": { "type": "string", "default": "-main" }, "electronPrefix": { "type": "string", "default": "-electron" }, "name": { "description": "the base name of the project", "type": "string" }, "project": { "description": "the name of the angular renderer project which where electron should be added to", "type": "string" } }, "required": [], "additionalProperties": false } ================================================ FILE: src/schematics/collection.json ================================================ { "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "ng-add": { "description": "Adds NGTron to the application without affecting any templates", "factory": "./ng-add/index", "schema": "./ng-add/schema.json", "aliases": ["install"] }, "application": { "description": "Adds NGTron to the application without affecting any templates", "factory": "./application/index", "schema": "./application/schema.json", "aliases": ["app"] } } } ================================================ FILE: src/schematics/files/electron/package.json ================================================ { "version": "0.0.0", "name": "myapp", "main": "", "dependencies": {} } ================================================ FILE: src/schematics/files/main/src/main.ts ================================================ import { join } from 'path'; import { format } from 'url'; import { app, BrowserWindow } from 'electron'; function createWindow(path: string) { const url = format({ pathname: path, protocol: 'file:', slashes: true }); let win: BrowserWindow = new BrowserWindow({ width: 800, height: 700, webPreferences: { nodeIntegration: true } }); win.loadURL(url); win.on('closed', () => { win = null; }); return win; } app.on('ready', () => { createWindow(join(__dirname, 'renderers', '<%= renderer %>', 'index.html')); }); app.on('window-all-closed', () => { app.quit(); }); ================================================ FILE: src/schematics/files/main/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] }, "include": ["**/*.ts"] } ================================================ FILE: src/schematics/ng-add/index.ts ================================================ import { addPackageJsonDependency, NodeDependency, NodeDependencyType, } from '@schematics/angular/utility/dependencies' import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks' import { chain, Rule, SchematicContext, Tree, } from '@angular-devkit/schematics' export interface NgAddOptions { project: string } export default function (): Rule { return (tree: Tree, _context: SchematicContext) => { return chain([ addPackageJsonDependencies(), installPackageJsonDependencies(), ])(tree, _context) } } function addPackageJsonDependencies(): Rule { return (host: Tree, context: SchematicContext) => { // TODO: Get latest electron dependency or let user choose const dependencies: NodeDependency[] = [ { type: NodeDependencyType.Dev, version: 'latest', name: 'electron', }, { type: NodeDependencyType.Dev, version: 'latest', name: 'electron-builder', }, { type: NodeDependencyType.Dev, version: '~12.7.12', name: '@types/node', }, { type: NodeDependencyType.Dev, version: 'latest', name: '@richapps/ngnode', }, { type: NodeDependencyType.Dev, version: 'latest', name: '@richapps/build-angular', }, { type: NodeDependencyType.Dev, version: '^6.2.0', name: 'ts-loader', }, ] dependencies.forEach((dependency) => { addPackageJsonDependency(host, dependency) context.logger.log( 'info', `✅️ Added "${dependency.name}" into ${dependency.type}` ) }) return host } } function installPackageJsonDependencies(): Rule { return (host: Tree, context: SchematicContext) => { context.addTask(new NodePackageInstallTask()) context.logger.log('info', `🔍 Installing packages...`) return host } } ================================================ FILE: src/schematics/ng-add/schema.json ================================================ { "$schema": "http://json-schema.org/schema", "id": "ngtron-ng-add", "title": "NGTron ng-add schematic", "type": "object", "properties": { "project": { "type": "string", "description": "The name of the project.", "$default": { "$source": "projectName" } } }, "required": [], "additionalProperties": false } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "baseUrl": "tsconfig", "lib": ["es2018", "dom"], "declaration": true, "module": "commonjs", "moduleResolution": "node", "noEmitOnError": true, "noFallthroughCasesInSwitch": true, "noImplicitAny": false, "noImplicitThis": true, "noUnusedParameters": false, "noUnusedLocals": false, "skipDefaultLibCheck": true, "skipLibCheck": true, "sourceMap": true, "strictNullChecks": false, "target": "es6", "types": ["jasmine", "node"], "outDir": "dist" }, "include": ["src/**/*"], "exclude": ["src/schematics/files/**/*"] } ================================================ FILE: tslint.json ================================================ { "extends": "tslint:recommended", "rulesDirectory": [ "codelyzer" ], "rules": { "array-type": false, "arrow-parens": false, "deprecation": { "severity": "warn" }, "import-blacklist": [ true, "rxjs/Rx" ], "interface-name": false, "max-classes-per-file": false, "max-line-length": [ true, 140 ], "member-access": false, "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-consecutive-blank-lines": false, "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-empty": false, "no-inferrable-types": [ true, "ignore-params" ], "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, "no-use-before-declare": true, "no-var-requires": false, "object-literal-key-quotes": [ true, "as-needed" ], "object-literal-sort-keys": false, "ordered-imports": false, "quotemark": [ true, "single" ], "trailing-comma": false, "component-class-suffix": true, "contextual-lifecycle": true, "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, "no-inputs-metadata-property": true, "no-output-native": true, "no-output-on-prefix": true, "no-output-rename": true, "no-outputs-metadata-property": true, "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true } }