Skip to content
This repository has been archived by the owner on May 10, 2021. It is now read-only.

Commit

Permalink
Merge pull request #4 from hapinessjs/next
Browse files Browse the repository at this point in the history
release(version): v5.1.0
  • Loading branch information
akanass committed Nov 18, 2017
2 parents a882af1 + 6681fb4 commit af82483
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 164 deletions.
8 changes: 7 additions & 1 deletion README.md
Expand Up @@ -45,7 +45,7 @@ This is a [Hapiness](https://github.com/hapinessjs/hapiness) Engine for running

This story will show you how to set up Universal bundling for an existing `@angular/cli`.

We support actually `@angular` `@5.0.0` and next so you must upgrade all packages inside your project.
We support actually `@angular` `@5.0.2` and next so you must upgrade all packages inside your project.

We use `yarn` as package manager.

Expand Down Expand Up @@ -550,6 +550,12 @@ To set up your development environment:
[Back to top](#table-of-contents)

## Change History
* v5.1.0 (2017-11-18)
* `Angular v5.0.2+`
* Returns `Observable` in route instead of to use `ReplyNoContinue` interface
* Update tests
* Change packaging process
* Documentation
* v5.0.0 (2017-11-13)
* `Angular v5.0.0+`
* Publish all features of the module
Expand Down
38 changes: 19 additions & 19 deletions package.json
@@ -1,8 +1,8 @@
{
"name": "@hapiness/ng-universal",
"version": "5.0.0",
"version": "5.1.0",
"description": "This is a Hapiness Engine for running Angular Apps on the server for server side rendering.",
"main": "index.js",
"main": "commonjs/index.js",
"types": "index.d.ts",
"private": false,
"scripts": {
Expand Down Expand Up @@ -71,20 +71,20 @@
},
"homepage": "https://github.com/hapinessjs/ng-universal-module#readme",
"dependencies": {
"@types/node": "^8.0.51"
"@types/node": "^8.0.53"
},
"devDependencies": {
"@angular/animations": "^5.0.1",
"@angular/common": "^5.0.1",
"@angular/compiler": "^5.0.1",
"@angular/core": "^5.0.1",
"@angular/http": "^5.0.1",
"@angular/platform-browser": "^5.0.1",
"@angular/platform-browser-dynamic": "^5.0.1",
"@angular/platform-server": "^5.0.1",
"@hapiness/core": "^1.1.1",
"@angular/animations": "^5.0.2",
"@angular/common": "^5.0.2",
"@angular/compiler": "^5.0.2",
"@angular/core": "^5.0.2",
"@angular/http": "^5.0.2",
"@angular/platform-browser": "^5.0.2",
"@angular/platform-browser-dynamic": "^5.0.2",
"@angular/platform-server": "^5.0.2",
"@hapiness/core": "^1.2.0",
"@nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.5",
"@types/fs-extra": "^4.0.4",
"@types/fs-extra": "^4.0.5",
"coveralls": "^3.0.0",
"fs-extra": "^4.0.2",
"istanbul": "^1.1.0-alpha.1",
Expand All @@ -99,12 +99,12 @@
"zone.js": "^0.8.18"
},
"peerDependencies": {
"@angular/compiler": "^5.0.1",
"@angular/core": "^5.0.1",
"@angular/http": "^5.0.1",
"@angular/platform-server": "^5.0.1",
"@hapiness/core": "^1.1.1",
"@hapiness/ng-universal-transfer-http": "^5.0.0",
"@angular/compiler": "^5.0.2",
"@angular/core": "^5.0.2",
"@angular/http": "^5.0.2",
"@angular/platform-server": "^5.0.2",
"@hapiness/core": "^1.2.0",
"@hapiness/ng-universal-transfer-http": "^5.1.0",
"@nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.5",
"rxjs": "^5.5.2",
"ts-loader": "^3.1.1"
Expand Down
14 changes: 8 additions & 6 deletions src/module/routes/universal/get/html.route.ts
@@ -1,5 +1,7 @@
import { OnGet, Request, Route, ReplyNoContinue } from '@hapiness/core';
import { NgEngineService, UniversalResult } from '../../../services';
import { OnGet, Request, Route } from '@hapiness/core';
import { HapinessHTTPHandlerResponse } from '@hapiness/core/extensions/http-server';
import { NgEngineService } from '../../../services';
import { Observable } from 'rxjs/Observable';

@Route({
path: '/{path*}',
Expand All @@ -18,10 +20,10 @@ export class GetHtmlUniversalRoute implements OnGet {
* OnGet implementation
*
* @param {Request} request
* @param {ReplyNoContinue} reply
*
* @returns {Observable<any | HapinessHTTPHandlerResponse>}
*/
onGet(request: Request, reply: ReplyNoContinue): void {
this._ngEngineService.universal(request)
.subscribe((_: UniversalResult) => !!_.mime ? reply(_.body).header('content-type', _.mime) : reply(_.body.toString()));
onGet(request: Request): Observable<any | HapinessHTTPHandlerResponse> {
return this._ngEngineService.universal(request);
}
}
34 changes: 13 additions & 21 deletions src/module/services/engine/ng.service.ts
Expand Up @@ -13,14 +13,9 @@ import { _throw } from 'rxjs/observable/throw';

import * as fs from 'fs';
import { join } from 'path';
import { Buffer } from 'buffer';

import { NG_UNIVERSAL_MODULE_CONFIG, REQUEST, RESPONSE, NgSetupOptions, StaticContent } from '../../interfaces';

export interface UniversalResult {
body: Buffer;
mime?: string;
}
import { HapinessHTTPHandlerResponse } from '@hapiness/core/extensions/http-server';

@Injectable()
export class NgEngineService {
Expand Down Expand Up @@ -92,9 +87,9 @@ export class NgEngineService {
*
* @param {Request} request initial request
*
* @return {Observable<UniversalResult>}
* @return {Observable<any | HapinessHTTPHandlerResponse>}
*/
universal(request: Request): Observable<UniversalResult> {
universal(request: Request): Observable<any | HapinessHTTPHandlerResponse> {
return mergeStatic(
this._checkRequest(request),
this._checkConfig()
Expand All @@ -117,37 +112,39 @@ export class NgEngineService {
}

/**
* Returns UniversalResult from static content
* Returns HapinessHTTPHandlerResponse from static content
*
* @param _
*
* @returns {Observable<UniversalResult>}
* @returns {Observable<HapinessHTTPHandlerResponse>}
*
* @private
*/
private _getStaticContent(_: any): Observable<UniversalResult> {
private _getStaticContent(_: any): Observable<HapinessHTTPHandlerResponse> {
return of(_)
.pipe(
filter(__ => !!__.mime),
flatMap(__ =>
of({
body: this._getDocument(this._buildFilePath(__.config.staticContent, __.mime, __.request.raw.req.url)),
mime: __.mime
response: this._getDocument(this._buildFilePath(__.config.staticContent, __.mime, __.request.raw.req.url)),
headers: {
'content-type': __.mime
}
})
)
);
}

/**
* Returns UniversalResult from NgFactoryModule
* Returns content from NgFactoryModule
*
* @param _
*
* @returns {Observable<UniversalResult>}
* @returns {Observable<any>}
*
* @private
*/
private _getFactoryContent(_: any): Observable<UniversalResult> {
private _getFactoryContent(_: any): Observable<any> {
return of(_)
.pipe(
filter(__ => !__.mime),
Expand All @@ -167,11 +164,6 @@ export class NgEngineService {
.pipe(
flatMap(factory =>
fromPromise(this._renderModuleFactory(factory, { extraProviders: __.extraProviders }))
),
flatMap(content =>
of({
body: Buffer.from(content)
})
)
)
)
Expand Down
19 changes: 9 additions & 10 deletions test/unit/get-html-universal.route.test.ts
@@ -1,5 +1,4 @@
import { test, suite } from 'mocha-typescript';
import { ReplyNoContinue } from '@hapiness/core';
import { GetHtmlUniversalRoute } from '../../src/module/routes';
import { NgEngineService } from '../../src/module/services';

Expand Down Expand Up @@ -62,31 +61,31 @@ export class GetHtmlUniversalRouteTest {
*/
@test('- `GetHtmlUniversalRoute.onGet()` function must return an Observable with html data and no header')
testGetHtmlUniversalRouteOnGetObservableHtmlWithoutHeader(done) {
this._ngEngineServiceMock.expects('universal').once().returns(of({ body: Buffer.from('<h1>Hello Angular</h1>') }));
this._ngEngineServiceMock.expects('universal').once().returns(of('<h1>Hello Angular</h1>'));

this._getHtmlUniversalRoute.onGet(null, <ReplyNoContinue>(res => {
this._getHtmlUniversalRoute.onGet(null).subscribe(res => {
unit.string(res).is('<h1>Hello Angular</h1>').when(_ => {
this._ngEngineServiceMock.verify();
this._ngEngineServiceMock.restore();
done();
})
}));
});
}

/**
* Test if `GetHtmlUniversalRoute.onGet()` function returns an Observable with html data and without header
* Test if `GetHtmlUniversalRoute.onGet()` function returns an Observable with html buffer and without header
*/
@test('- `GetHtmlUniversalRoute.onGet()` function must return an Observable with html data and header')
@test('- `GetHtmlUniversalRoute.onGet()` function must return an Observable with html buffer and header')
testGetHtmlUniversalRouteOnGetObservableHtmlWithHeader(done) {
this._ngEngineServiceMock.expects('universal').once()
.returns(of({ body: Buffer.from('<h1>Hello Angular</h1>'), mime: 'text/html' }));
.returns(of({ response: Buffer.from('<h1>Hello Angular</h1>'), headers: { 'content-type': 'text/html' } }));

this._getHtmlUniversalRoute.onGet(null, <ReplyNoContinue>(res => {
unit.string(res.toString()).is('<h1>Hello Angular</h1>').when(_ => {
this._getHtmlUniversalRoute.onGet(null).subscribe(res => {
unit.string(res.response.toString()).is('<h1>Hello Angular</h1>').when(_ => {
this._ngEngineServiceMock.verify();
this._ngEngineServiceMock.restore();
done();
})
}));
});
}
}
6 changes: 3 additions & 3 deletions test/unit/ng-engine.service.test.ts
Expand Up @@ -164,7 +164,7 @@ export class NgEngineServiceTest {
.returns(new Promise((resolve) => resolve('<h1>Hello Angular</h1>')));

ngE.universal(this._request)
.subscribe(_ => unit.string(_.body.toString()).is('<h1>Hello Angular</h1>')
.subscribe(_ => unit.string(_).is('<h1>Hello Angular</h1>')
.when(__ => {
compilerStub.restore();
renderModuleFactoryStub.restore();
Expand All @@ -191,7 +191,7 @@ export class NgEngineServiceTest {
.returns(new Promise((resolve) => resolve('<h1>Hello Angular</h1>')));

ngE.universal(this._request)
.subscribe(_ => unit.string(_.body.toString()).is('<h1>Hello Angular</h1>')
.subscribe(_ => unit.string(_).is('<h1>Hello Angular</h1>')
.when(__ => {
renderModuleFactoryStub.restore();
done();
Expand All @@ -213,7 +213,7 @@ export class NgEngineServiceTest {


ngE.universal(<any> { raw: { req: { url: '/' } } })
.subscribe(_ => unit.string(_.body.toString()).is('')
.subscribe(_ => unit.string(_.response.toString()).is('')
.when(__ => {
done();
})
Expand Down
7 changes: 1 addition & 6 deletions tools/files.json
@@ -1,10 +1,5 @@
[
{ "name":"README.md" },
{ "name":"LICENSE.md" },
{ "name":"package.json" },
{ "name":"src" },
{ "name":"index.js", "remove":true },
{ "name":"index.js.map", "remove":true },
{ "name":"index.d.ts", "remove":true },
{ "name":"module", "remove":true }
{ "name":"package.json" }
]
63 changes: 10 additions & 53 deletions tools/packaging.ts
Expand Up @@ -9,8 +9,6 @@ import * as fs from 'fs-extra';
*/
interface FileObject {
name: string;
remove?: boolean;
externals?: boolean;
}

/**
Expand Down Expand Up @@ -41,28 +39,23 @@ class Packaging {
* Function to copy one file
*
* @param file {string}
* @param externals {boolean}
*
* @return {Observable<R>}
* @return {Observable<any>}
*/
private _copy(file: string, externals?: boolean): Observable<any> {
private _copy(file: string): Observable<any> {
// copy package.json
if (file.indexOf('package.json') !== -1) {
return this._copyAndCleanupPackageJson(file);
}

// copy other files
return <Observable<any>> Observable.create((observer) => {
let fileDest = file;
if (externals && file.indexOf('src/') !== -1) {
fileDest = file.split('src/').pop();
}
fs.stat(`${this._srcPath}${file}`, (error, stats) => {
if (error) {
console.error('doesn\'t exist on copy =>', error.message);
}
if (stats && (stats.isFile() || stats.isDirectory())) {
fs.copy(`${this._srcPath}${file}`, `${this._destPath}${fileDest}`, (err) => {
fs.copy(`${this._srcPath}${file}`, `${this._destPath}${file}`, (err) => {
if (err) {
console.error('copy failed =>', err.message);
}
Expand All @@ -78,52 +71,12 @@ class Packaging {
});
}

/**
* Function to remove original file
*
* @param file {string}
* @param remove {boolean}
*
* @return {Observable<any>}
*
* @private
*/
private _remove(file: string, remove?: boolean): Observable<any> {
// remove original files
return <Observable<any>> Observable.create((observer) => {
if (remove) {
fs.stat(`${this._srcPath}${file}`, (error, stats) => {
if (error) {
console.error('doesn\'t exist on remove =>', error.message);
}

if (stats && (stats.isFile() || stats.isDirectory())) {
fs.remove(`${this._srcPath}${file}`, (err) => {
if (err) {
console.error('remove failed =>', err.message);
}

observer.next();
observer.complete();
});
} else {
observer.next();
observer.complete();
}
});
} else {
observer.next();
observer.complete();
}
});
}

/**
* Function to cleanup package.json and _copy it to dist directory
*
* @param file {string}
*
* @return {Observable<R>}
* @return {Observable<any>}
*
* @private
*/
Expand Down Expand Up @@ -171,8 +124,12 @@ class Packaging {
* Function that _copy all files in dist directory
*/
process() {
Observable.forkJoin(this._files.map((fileObject: FileObject) => this._copy(fileObject.name, fileObject.externals)
.flatMap(_ => this._remove(fileObject.name, fileObject.remove)))).subscribe(null, error => console.error(error));
Observable.forkJoin(
this._files.map(
(fileObject: FileObject) => this._copy(fileObject.name)
)
)
.subscribe(null, error => console.error(error));
}
}

Expand Down

0 comments on commit af82483

Please sign in to comment.