├── .editorconfig
├── .gitignore
├── README.md
├── demo
├── README.md
├── app_ui.ts
├── component.ts
├── index.html
├── main.ts
└── package.json
├── package.json
├── src
├── main.ts
├── platform
│ ├── electron.ts
│ ├── electron_app.ts
│ ├── electron_app_common.ts
│ ├── electron_message_bus.ts
│ ├── electron_renderer.ts
│ └── electron_renderer_common.ts
└── renderer.ts
├── tsconfig.json
└── typings.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
16 |
17 | [*.json]
18 | insert_final_newline = false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | typings/
4 | npm-debug.log
5 | .DS_Store
6 | demo/*.js
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular Electron
2 |
3 | Electron Platform for Angular 2. Work in progress.
4 |
5 | ## Testing the demo
6 |
7 | Make sure to have NodeJS version 5.x.x installed.
8 |
9 | Start off by running `npm run setup`. That command will install the dependencies and the required TypeScript typings (using the [typings](https://www.npmjs.com/package/typings) package).
10 |
11 | Since the demo application is not apart of the plugin, angular2 and
12 | its peer dependencies also need to be installed manually via npm. Run
13 | the following command to install everything required for the demo: `npm run setup-demo`.
14 |
15 | That command will install the following:
16 | * angular2
17 | * es6-promise
18 | * es6-shim
19 | * reflect-metadata
20 | * rxjs
21 | * zone.js
22 |
23 | Then execute `npm start` to see the demo application in action!
24 |
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | ### Angular Electron Sample App
2 |
--------------------------------------------------------------------------------
/demo/app_ui.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import {bootstrapElectronRenderer} from '../dist/renderer';
3 |
4 | bootstrapElectronRenderer();
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from 'angular2/core';
2 |
3 | @Component({
4 | selector: 'app',
5 | template: `
Hello from {{name}}
`
6 | })
7 | export class App {
8 | name: string;
9 | constructor(){
10 | this.name = 'Angular2 Electron!';
11 |
12 | setTimeout(() => {
13 | this.name = 'Angular2 Electron!!!';
14 | },1000);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Loading...
8 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/main.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import 'zone.js/dist/zone';
3 | import {bootstrap} from '../dist/main';
4 |
5 | import {App} from './component';
6 |
7 | bootstrap(App, []);
8 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "angular-electron-demo",
3 | "version" : "1.0.0",
4 | "main" : "main.js"
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@angular2/electron",
3 | "version": "1.0.0",
4 | "description": "Electron Platform for Angular2",
5 | "main": "index.js",
6 | "scripts": {
7 | "clean": "rimraf dist",
8 | "typings-install": "typings install",
9 | "setup": "npm install --no-optional && npm run typings-install",
10 | "setup-demo": "npm install --no-optional angular2@2.0.0-beta.12 es6-promise@^3.1.2 es6-shim@0.35.0 reflect-metadata@0.1.2 rxjs@5.0.0-beta.2 zone.js@^0.6.6",
11 | "build": "npm run clean && tsc",
12 | "build_demo": "tsc typings/browser.d.ts demo/main.ts demo/app_ui.ts --module commonjs -t es5 --experimentalDecorators --emitDecoratorMetadata",
13 | "test": "echo Not supported yet",
14 | "demo": "npm run build && npm run build_demo && electron ./demo",
15 | "start": "npm run demo"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/angular/angular-electron.git"
20 | },
21 | "keywords": [
22 | "Angular2",
23 | "Electron"
24 | ],
25 | "author": "Rob Wormald ",
26 | "license": "MIT",
27 | "bugs": {
28 | "url": "https://github.com/angular/angular-electron/issues"
29 | },
30 | "homepage": "https://github.com/angular/angular-electron#readme",
31 | "devDependencies": {
32 | "electron-prebuilt": "^0.37.2",
33 | "typescript": "^1.8.9",
34 | "rimraf": "^2.5.2"
35 | },
36 | "peerDependencies": {
37 | "angular2": "2.0.0-beta.12"
38 | },
39 | "dependencies": {
40 | "parse5": "^1.5.1"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | //public angular electron API for main (node/background)
2 | export * from 'angular2/common';
3 | export * from 'angular2/core';
4 | export * from 'angular2/platform/worker_app';
5 | export {UrlResolver} from 'angular2/compiler';
6 | export * from 'angular2/instrumentation';
7 | export * from './platform/electron_app';
8 | export * from './platform/electron';
9 |
--------------------------------------------------------------------------------
/src/platform/electron.ts:
--------------------------------------------------------------------------------
1 | import {platform} from 'angular2/core';
2 | import { ELECTRON_APP_APPLICATION, bootstrap } from './electron_app';
3 | import { ELECTRON_APP_PLATFORM } from './electron_app_common';
4 | export { bootstrap }
5 |
--------------------------------------------------------------------------------
/src/platform/electron_app.ts:
--------------------------------------------------------------------------------
1 | import * as electron from 'electron';
2 | import {ElectronMessageBus, ElectronMessageBusSink, ElectronMessageBusSource, ELECTRON_READY} from './electron_message_bus';
3 | import {ELECTRON_APP_APPLICATION_COMMON, ELECTRON_APP_PLATFORM} from './electron_app_common';
4 | import {Type, CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
5 | import {Parse5DomAdapter} from 'angular2/src/platform/server/parse5_adapter';
6 | import {APP_INITIALIZER, platform, ComponentRef, NgZone, Provider} from 'angular2/core';
7 | import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
8 | import {COMPILER_PROVIDERS} from 'angular2/compiler';
9 |
10 | export const ELECTRON_APP_APPLICATION: Array = [
11 | ELECTRON_APP_APPLICATION_COMMON,
12 | COMPILER_PROVIDERS,
13 | new Provider(MessageBus, { useFactory: createMessageBus, deps: [NgZone] }),
14 | new Provider(APP_INITIALIZER, { useValue: () => {}, multi: true })
15 | ];
16 |
17 | let applicationRef:Electron.BrowserWindow;
18 |
19 | function createMessageBus(zone: NgZone): MessageBus {
20 | let sink = new ElectronMessageBusSink(applicationRef.webContents);
21 | let source = new ElectronMessageBusSource(electron.ipcMain);
22 | let bus = new ElectronMessageBus(sink, source);
23 | bus.attachToZone(zone);
24 | return bus;
25 | }
26 |
27 | function waitForAppReady(){
28 | return new Promise((resolve, reject) => {
29 | electron.app.on('ready', resolve);
30 | });
31 | }
32 |
33 | function waitForPingback(){
34 | initializeMainWindow()
35 | return new Promise((resolve) => {
36 | electron.ipcMain.once(ELECTRON_READY, (ev) => {
37 | ev.returnValue = 'ok';
38 | resolve();
39 | });
40 | });
41 | }
42 |
43 | function initializeMainWindow(){
44 | applicationRef = new electron.BrowserWindow();
45 | applicationRef.loadURL(`file://${process.cwd()}/demo/index.html`);
46 | }
47 |
48 | export function bootstrap(appComp, providers?:any) {
49 | Parse5DomAdapter.makeCurrent();
50 |
51 | return platform([ ELECTRON_APP_PLATFORM ])
52 | .asyncApplication((z) => {
53 | return z.run(() => {
54 | return waitForAppReady()
55 | .then(waitForPingback)
56 | .then(() => {
57 | return ELECTRON_APP_APPLICATION;
58 | })
59 | })
60 | })
61 | .then((appRef) => {
62 | return appRef.bootstrap(appComp);
63 | })
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/platform/electron_app_common.ts:
--------------------------------------------------------------------------------
1 | import {XHR} from 'angular2/src/compiler/xhr';
2 | import {WebWorkerXHRImpl} from 'angular2/src/web_workers/worker/xhr_impl';
3 | import {WebWorkerRootRenderer} from 'angular2/src/web_workers/worker/renderer';
4 | import {print, Type, CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
5 | import {RootRenderer} from 'angular2/src/core/render/api';
6 | import {
7 | PLATFORM_DIRECTIVES,
8 | PLATFORM_PIPES,
9 | ExceptionHandler,
10 | APPLICATION_COMMON_PROVIDERS,
11 | PLATFORM_COMMON_PROVIDERS,
12 | } from 'angular2/core';
13 | import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS} from "angular2/common";
14 | import {
15 | ClientMessageBrokerFactory,
16 | ClientMessageBrokerFactory_
17 | } from 'angular2/src/web_workers/shared/client_message_broker';
18 | import {
19 | ServiceMessageBrokerFactory,
20 | ServiceMessageBrokerFactory_
21 | } from 'angular2/src/web_workers/shared/service_message_broker';
22 | import {Serializer} from "angular2/src/web_workers/shared/serializer";
23 | import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api";
24 | import {Provider} from 'angular2/src/core/di';
25 | import {RenderStore} from 'angular2/src/web_workers/shared/render_store';
26 |
27 | class PrintLogger {
28 | log = print;
29 | logError = print;
30 | logGroup = print;
31 | logGroupEnd() {}
32 | }
33 |
34 | export const ELECTRON_APP_PLATFORM: Array =
35 | CONST_EXPR([PLATFORM_COMMON_PROVIDERS]);
36 |
37 | export const ELECTRON_APP_APPLICATION_COMMON: Array = CONST_EXPR([
38 | APPLICATION_COMMON_PROVIDERS,
39 | FORM_PROVIDERS,
40 | Serializer,
41 | new Provider(PLATFORM_PIPES, {useValue: COMMON_PIPES, multi: true}),
42 | new Provider(PLATFORM_DIRECTIVES, {useValue: COMMON_DIRECTIVES, multi: true}),
43 | new Provider(ClientMessageBrokerFactory, {useClass: ClientMessageBrokerFactory_}),
44 | new Provider(ServiceMessageBrokerFactory, {useClass: ServiceMessageBrokerFactory_}),
45 | WebWorkerRootRenderer,
46 | new Provider(RootRenderer, {useExisting: WebWorkerRootRenderer}),
47 | new Provider(ON_WEB_WORKER, {useValue: true}),
48 | RenderStore,
49 | new Provider(ExceptionHandler, {useFactory: _exceptionHandler, deps: []}),
50 | WebWorkerXHRImpl,
51 | new Provider(XHR, {useExisting: WebWorkerXHRImpl})
52 | ]);
53 |
54 | function _exceptionHandler(): ExceptionHandler {
55 | return new ExceptionHandler(new PrintLogger());
56 | }
57 |
--------------------------------------------------------------------------------
/src/platform/electron_message_bus.ts:
--------------------------------------------------------------------------------
1 | import * as electron from 'electron';
2 | import {
3 | MessageBus,
4 | MessageBusSource,
5 | MessageBusSink
6 | } from "angular2/src/web_workers/shared/message_bus";
7 | import {NgZone, EventEmitter, Injectable} from 'angular2/core';
8 |
9 | /**
10 | * Typescript Implementation of MessageBus for use in electron apps
11 | */
12 |
13 | export const ELECTRON_WORKER = '__ELECTRON_WORKER';
14 | export const ELECTRON_CLIENT = '__ELECTRON_CLIENT';
15 | export const ELECTRON_READY = '__ELECTRON_READY'
16 |
17 | const ELECTRON_CHANNEL = '__ELECTRON_CHANNEL';
18 |
19 | @Injectable()
20 | export class ElectronMessageBus implements MessageBus {
21 | constructor(public sink: ElectronMessageBusSink,
22 | public source: ElectronMessageBusSource,
23 | private env: string = ELECTRON_CLIENT) {}
24 |
25 | attachToZone(zone: NgZone): void {
26 | this.source.attachToZone(zone);
27 | this.sink.attachToZone(zone);
28 | }
29 |
30 | initChannel(channel: string, runInZone: boolean = false): void {
31 | this.source.initChannel(channel, runInZone);
32 | this.sink.initChannel(channel, runInZone);
33 | }
34 |
35 | from(channel: string): EventEmitter { return this.source.from(channel); }
36 |
37 | to(channel: string): EventEmitter { return this.sink.to(channel); }
38 | }
39 |
40 | export class ElectronMessageBusSink implements MessageBusSink {
41 | private _zone: NgZone;
42 | private _channels: Map =
43 | new Map();
44 | private _messageBuffer: Array