Skip to content
This repository has been archived by the owner on Nov 22, 2024. It is now read-only.

Commit

Permalink
feat(hapi): upgrade to Hapi v17 (#1015)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
* The `ngHapiEngine` is no longer supported for Hapi v16. The `RESPONSE` token provided under `@nguniversal/hapi-engine/tokens` now uses the new `ResponseToolkit`, which is unavailable in Hapi v16. Updated instructions are available in the package's README
  • Loading branch information
CaerusKaru authored Jun 10, 2018
1 parent b417300 commit 311b9fe
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 251 deletions.
2 changes: 1 addition & 1 deletion integration/hapi-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"babel-loader": "^6.4.0",
"babel-preset-es2015": "^6.22.0",
"concurrently": "3.1.0",
"inert": "^4.2.1",
"inert": "^5.1.0",
"protractor": "file:../../node_modules/protractor",
"raw-loader": "^0.5.1",
"webpack": "^2.2.1"
Expand Down
49 changes: 21 additions & 28 deletions integration/hapi-engine/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,48 @@ import {ngHapiEngine} from '@nguniversal/hapi-engine';
require('zone.js/dist/zone-node.js');

import {enableProdMode} from '@angular/core';
import * as Hapi from 'hapi';
import {Server, Request} from 'hapi';
import * as Inert from 'inert';

import {HelloWorldServerModuleNgFactory} from './helloworld/app.server.ngfactory';
import {Base_Reply} from 'hapi';
const helloworld = require('raw-loader!./helloworld/index.html');

const server = new Hapi.Server();
server.connection({ port: 9876, host: 'localhost' });
server.register(Inert, () => {});
const server = new Server({ port: 9876, host: 'localhost' });

enableProdMode();

// Client bundles will be statically served from the built/ directory.
server.route({
method: 'GET',
path: '/built/{file*}',
handler: {
directory: {
path: 'built'
}
}
});

// Keep the browser logs free of errors.
server.route({
method: 'GET',
path: '/favicon.ico',
handler: function (request, reply) {
reply('');
}
handler: () => ''
});

//-----------ADD YOUR SERVER SIDE RENDERED APP HERE ----------------------
server.route({
method: 'GET',
path: '/helloworld',
handler: (req: Request, reply: Base_Reply) => {
handler: (req: Request) =>
ngHapiEngine({
bootstrap: HelloWorldServerModuleNgFactory,
req,
document: helloworld
} as any).then(html => reply(html));
}
})
});

server.start((err) => {
if (err) {
throw err;
}
console.log('Server listening on port 9876!');
});
(async() => {
await server.register(Inert);

// Client bundles will be statically served from the built/ directory.
server.route({
method: 'GET',
path: '/built/{file*}',
handler: {
directory: {
path: 'built'
}
}
});

await server.start();
})();
2 changes: 1 addition & 1 deletion modules/express-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@angular/common": "NG_VERSION",
"@angular/core": "NG_VERSION",
"@angular/platform-server": "NG_VERSION",
"express": "^4.15.2"
"express": "EXPRESS_VERSION"
},
"ng-update": {
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
Expand Down
37 changes: 12 additions & 25 deletions modules/hapi-engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This is a Hapi Engine for running Angular Apps on the server for server side ren
To use it, set the engine and then route requests to it

```ts
import { Base_Reply, Request, Server } from 'hapi';
import { Request, Server } from 'hapi';
import { ngHapiEngine } from '@nguniversal/hapi-engine';

const server = new Server();
Expand All @@ -18,20 +18,10 @@ server.connection({
port: 8000
});

// Set the engine
const hapiEngine = ngHapiEngine({
bootstrap: ServerAppModule // Give it a module to bootstrap
});

server.route({
method: 'GET',
path: '/{path*}',
handler: (req: Request, reply: Base_Reply) => {
hapiEngine({
req
}).then(html => reply(html))
.then(err => reply(boom.wrap(err)));
}
handler: (req: Request) => ngHapiEngine({req, bootstrap: ServerAppModule})
});
```

Expand All @@ -44,15 +34,14 @@ is called. To do so, simply pass in a `url` and/or `document` string to the rend
server.route({
method: 'GET',
path: '/{path*}',
handler: (req: Request, reply: Base_Reply) => {
let url = 'http://someurl.com';
let doc = '<html><head><title>New doc</title></head></html>';
hapiEngine({
handler: (req: Request) => {
const url = 'http://someurl.com';
const document = '<html><head><title>New doc</title></head></html>';
return ngHapiEngine({
req,
url,
document: doc
}).then(html => reply(html))
.then(err => reply(boom.wrap(err)));
document,
});
}
});
```
Expand Down Expand Up @@ -80,23 +69,21 @@ The Bootstrap module as well as more providers can be passed on request
server.route({
method: 'GET',
path: '/{path*}',
handler: (req: Request, reply: Base_Reply) => {
hapiEngine({
handler: (req: Request) =>
ngHapiEngine({
bootstrap: OtherServerAppModule,
providers: [
OtherServerService
],
req
}).then(html => reply(html))
.then(err => reply(boom.wrap(err)));
}
})
});
```

### Using the Request and Response

The Request and Response objects are injected into the app via injection tokens.
You can access them by @Inject
You can access them by `@Inject`

```ts
import { Request } from 'hapi';
Expand Down
2 changes: 1 addition & 1 deletion modules/hapi-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@angular/common": "NG_VERSION",
"@angular/core": "NG_VERSION",
"@angular/platform-server": "NG_VERSION",
"hapi": "^16.1.1"
"hapi": "HAPI_VERSION"
},
"ng-update": {
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
Expand Down
68 changes: 66 additions & 2 deletions modules/hapi-engine/spec/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,69 @@
import {Component, destroyPlatform, getPlatform, NgModule} from '@angular/core';
import {ServerModule} from '@angular/platform-server';
import {ngHapiEngine} from '@nguniversal/hapi-engine';
import {ServerInjectResponse, Request, Server} from 'hapi';
import 'zone.js';
import {BrowserModule} from '@angular/platform-browser';

@Component({selector: 'app', template: `Works!`})
class MyServerApp {
}


@NgModule({
bootstrap: [MyServerApp],
declarations: [MyServerApp],
imports: [ServerModule, BrowserModule.withServerTransition({appId: 'hapi-test'})],
})
class ExampleModule {
}


describe('test runner', () => {
it('can run a test', () => {
expect(true).toBe(true);

const server = new Server({ debug: false });
server.route([
{
method: 'GET',
path: '/',
handler: (req: Request) => ngHapiEngine({
bootstrap: ExampleModule,
req,
document: '<html><body><app></app></body></html>'
})
},
{
method: 'GET',
path: '/test',
handler: () => 'ok'
},
]);

beforeEach(async () => {
if (getPlatform()) {
destroyPlatform();
}
});

it('should test the server', async () => {
const request = {
method: 'GET',
url: '/test'
};

const res = await server.inject(request);
expect(res.result).toBeDefined();
expect(res.result).toBe('ok' as any);
});

it('Returns a reply on successful request', async () => {
const request = {
method: 'GET',
url: '/'
};

const res: ServerInjectResponse = await server.inject(request);
expect(res.result).toBeDefined();
expect(res.result).toContain('Works!');
});
});
20 changes: 5 additions & 15 deletions modules/hapi-engine/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as fs from 'fs';
import { Request, Response } from 'hapi';
import { Request, ResponseToolkit } from 'hapi';

import { NgModuleFactory, Type, CompilerFactory, Compiler, StaticProvider } from '@angular/core';
import { ResourceLoader } from '@angular/compiler';
Expand All @@ -32,7 +32,7 @@ export interface NgSetupOptions {
*/
export interface RenderOptions extends NgSetupOptions {
req: Request;
res?: Response;
res?: ResponseToolkit;
url?: string;
document?: string;
}
Expand Down Expand Up @@ -90,16 +90,8 @@ export function ngHapiEngine(options: RenderOptions) {
]);

getFactory(moduleOrFactory, compiler)
.then(factory => {
return renderModuleFactory(factory, {
extraProviders
});
})
.then((html: string) => {
resolve(html);
}, (err) => {
reject(err);
});
.then(factory => renderModuleFactory(factory, {extraProviders}))
.then(resolve, reject);
});
}

Expand Down Expand Up @@ -128,9 +120,7 @@ function getFactory(
.then((factory) => {
factoryCacheMap.set(moduleOrFactory, factory);
resolve(factory);
}, (err => {
reject(err);
}));
}, reject);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions modules/hapi-engine/tokens/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Request, Response } from 'hapi';
import { Request, ResponseToolkit } from 'hapi';
import { InjectionToken } from '@angular/core';

export const REQUEST = new InjectionToken<Request>('REQUEST');
export const RESPONSE = new InjectionToken<Response>('RESPONSE');
export const RESPONSE = new InjectionToken<ResponseToolkit>('RESPONSE');
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@
"@bazel/ibazel": "^0.3.1",
"@types/express": "^4.0.39",
"@types/fs-extra": "^4.0.5",
"@types/hapi": "^16.1.2",
"@types/hapi": "^17.0.12",
"@types/jasmine": "^2.8.6",
"@types/node": "^9.4.6",
"camelcase": "^4.1.0",
"express": "^4.15.2",
"fs-extra": "^3.0.1",
"glob": "^7.1.2",
"hapi": "^16.1.1",
"hapi": "^17.5.1",
"jasmine-core": "^2.8.0",
"karma": "^2.0.0",
"karma-chrome-launcher": "^2.2.0",
Expand Down
10 changes: 7 additions & 3 deletions tools/defaults.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ DEFAULT_NODE_MODULES = "//:node_modules"

NG_VERSION = "^6.0.0-rc.0"
RXJS_VERSION = "^6.0.0-beta.0"
HAPI_VERSION = "^17.0.0"
EXPRESS_VERSION = "^4.15.2"

NGUNIVERSAL_SCOPED_PACKAGES = ["@nguniversal/%s" % p for p in [
"aspnetcore-engine",
Expand All @@ -20,6 +22,8 @@ NGUNIVERSAL_SCOPED_PACKAGES = ["@nguniversal/%s" % p for p in [
PKG_GROUP_REPLACEMENTS = {
"NG_VERSION": NG_VERSION,
"RXJS_VERSION": RXJS_VERSION,
"HAPI_VERSION": HAPI_VERSION,
"EXPRESS_VERSION": EXPRESS_VERSION,
"\"NG_UPDATE_PACKAGE_GROUP\"": """[
%s
]""" % ",\n ".join(["\"%s\"" % s for s in NGUNIVERSAL_SCOPED_PACKAGES])
Expand All @@ -39,14 +43,14 @@ GLOBALS = {
"@nguniversal/express-engine/tokens": "nguniversal.expressEngine.tokens",
"@nguniversal/hapi-engine/tokens": "nguniversal.hapiEngine.tokens",
'tslib': 'tslib',
"rxjs": "Rx",
"rxjs/operators": "Rx.operators",
"rxjs": "rxjs",
"rxjs/operators": "rxjs.operators",
"fs": "fs",
"express": "express",
"hapi": "hapi"
}

# TODO: when a better api for defaults is avilable use that isntead of these macros
# TODO(Toxicable): when a better api for defaults is avilable use that instead of these macros
def ts_test_library(node_modules=None, **kwargs):
ts_library(testonly=1, **kwargs)

Expand Down
Loading

0 comments on commit 311b9fe

Please sign in to comment.