Skip to content

Commit af8fac3

Browse files
committed
Basic bindings
0 parents  commit af8fac3

10 files changed

Lines changed: 262 additions & 0 deletions

File tree

.babelrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"presets": [
3+
"airbnb"
4+
]
5+
}

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[*]
2+
indent_size = 2
3+
indent_style = space

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
example
3+
lib

.eslintrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": [
3+
"airbnb-base"
4+
],
5+
"rules": {
6+
"import/no-unresolved": 0,
7+
"import/prefer-default-export": 0
8+
}
9+
}

.gitignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Directory for instrumented libs generated by jscoverage/JSCover
7+
lib-cov
8+
9+
# Coverage directory used by tools like istanbul
10+
coverage
11+
12+
# node-waf configuration
13+
.lock-wscript
14+
15+
# Compiled binary addons (http://nodejs.org/api/addons.html)
16+
build/Release
17+
18+
# Dependency directory
19+
node_modules
20+
21+
# Optional npm cache directory
22+
.npm
23+
24+
# Optional REPL history
25+
.node_repl_history
26+
27+
TODO
28+
coverage
29+
lib
30+
31+
# Only apps should have lockfiles
32+
npm-shrinkwrap.json
33+
yarn.lock
34+
package-lock.json
35+
© 2019 GitHub, Inc.
36+
Terms
37+
Privacy
38+
Security
39+
Status
40+
Help
41+
Contact GitHub
42+
Pricing
43+
API
44+
Training
45+
Blog
46+
About
47+
48+
example

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
example

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2019 Felipe Guizar Diaz
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# hypernova-angular
2+
3+
[Angular](https://angular.io/) bindings for [Hypernova](https://github.com/airbnb/hypernova).
4+
5+
On the server, wraps the component in a function to render it to a HTML string given its props.
6+
7+
On the client, calling this function with your component scans the DOM for any server-side rendered instances of it. It then resumes those components using the server-specified props.
8+
9+
## Install
10+
11+
```sh
12+
npm install hypernova-angular
13+
```
14+
15+
## Usage
16+
17+
Here's how to use it in your browser module:
18+
19+
```ts
20+
import { renderAngular } from 'hypernova-angular'
21+
22+
import { ExampleModule } from './components/example/example.module'
23+
import { ExampleComponent } from './components/example/example.component'
24+
25+
renderAngular('Example', ExampleComponent, ExampleModule)
26+
```

package.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "hypernova-angular",
3+
"version": "0.1.1",
4+
"description": "Angular Bindings for Hypernova",
5+
"main": "lib/index.js",
6+
"author": "Felipe Guizar Diaz <felipegaiacharly@gmail.com>",
7+
"license": "MIT",
8+
"keywords": [
9+
"angular",
10+
"hypernova",
11+
"ssr",
12+
"isomorphic"
13+
],
14+
"repository": {
15+
"type": "git",
16+
"url": "git@github.com:marconi1992/hypernova-angular.git"
17+
},
18+
"scripts": {
19+
"prepublish": "npm run build",
20+
"lint": "eslint src",
21+
"build": "babel src -d lib"
22+
},
23+
"devDependencies": {
24+
"babel-cli": "^6.26.0",
25+
"babel-preset-airbnb": "^2.5.3",
26+
"eslint": "^5.14.1",
27+
"eslint-config-airbnb-base": "^13.1.0",
28+
"eslint-plugin-import": "^2.16.0"
29+
},
30+
"peerDependencies": {
31+
"@angular/core": ">=5.0.0",
32+
"@angular/platform-browser": ">=5.0.0",
33+
"@angular/platform-server": ">=5.0.0",
34+
"@angular/platform-browser-dynamic": ">=5.0.0",
35+
"hypernova": "^2.5.0",
36+
"rxjs": ">=5.0.0"
37+
}
38+
}

src/index.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import hypernova, { serialize, load } from 'hypernova';
2+
import { first } from 'rxjs/operators';
3+
import { BrowserModule } from '@angular/platform-browser';
4+
import {
5+
ServerModule,
6+
platformDynamicServer,
7+
INITIAL_CONFIG,
8+
PlatformState,
9+
} from '@angular/platform-server';
10+
11+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
12+
13+
import { NgModule, ApplicationRef } from '@angular/core';
14+
15+
const APP_ID = 'hypernova';
16+
17+
export const HYPERNOVA_DATA = 'Hypernova.Data';
18+
19+
const getServerAppModule = (Component, Module) => {
20+
function AppModule() {
21+
this.ngDoBootstrap = (app) => {
22+
app.bootstrap(Component, `#${APP_ID}`);
23+
};
24+
}
25+
return NgModule({
26+
imports: [
27+
Module,
28+
BrowserModule,
29+
ServerModule,
30+
],
31+
entryComponents: [Component],
32+
})(AppModule);
33+
};
34+
35+
const getBrowserAppModule = (Component, Module, node) => {
36+
function AppModule() {
37+
this.ngDoBootstrap = (app) => {
38+
app.bootstrap(Component, node);
39+
};
40+
}
41+
return NgModule({
42+
imports: [
43+
Module,
44+
BrowserModule.withServerTransition({ appId: APP_ID }),
45+
],
46+
entryComponents: [Component],
47+
})(AppModule);
48+
};
49+
50+
const renderServer = (ServerAppModule, propsData) => {
51+
const platform = platformDynamicServer([
52+
{
53+
provide: INITIAL_CONFIG,
54+
useValue: {
55+
document: `<div id="${APP_ID}"></div>`,
56+
},
57+
},
58+
{
59+
provide: HYPERNOVA_DATA,
60+
useValue: propsData,
61+
},
62+
]);
63+
64+
return platform.bootstrapModule(ServerAppModule)
65+
.then((moduleRef) => {
66+
const applicationRef = moduleRef.injector.get(ApplicationRef);
67+
return applicationRef.isStable.pipe(first(isStable => isStable))
68+
.toPromise()
69+
.then(() => {
70+
const platformState = platform.injector.get(PlatformState);
71+
72+
platform.destroy();
73+
return platformState.getDocument().getElementById(APP_ID).serialize();
74+
});
75+
});
76+
};
77+
78+
export const renderAngular = (name, Component, Module) => hypernova({
79+
server() {
80+
return async (propsData) => {
81+
const ServerAppModule = getServerAppModule(Component, Module);
82+
83+
const html = await renderServer(ServerAppModule, propsData);
84+
85+
return serialize(name, html, propsData);
86+
};
87+
},
88+
89+
client() {
90+
const payloads = load(name);
91+
if (payloads) {
92+
payloads.forEach((payload) => {
93+
const { node, data: propsData } = payload;
94+
95+
const BrowserAppModule = getBrowserAppModule(Component, Module, node);
96+
97+
platformBrowserDynamic([
98+
{
99+
provide: HYPERNOVA_DATA,
100+
useValue: propsData,
101+
},
102+
]).bootstrapModule(BrowserAppModule);
103+
});
104+
}
105+
return Component;
106+
},
107+
});

0 commit comments

Comments
 (0)