From 2f1af56a4ef46e844efbf6597b6bd36c5f1d2863 Mon Sep 17 00:00:00 2001 From: christophercr Date: Wed, 4 Apr 2018 14:44:25 +0200 Subject: [PATCH] chore(rxjs): use pipeable operators instead of prototype-patched based operators [#258] --- packages/rollup.config.common-data.js | 20 +- packages/stark-build/config/build-utils.js | 5 +- packages/stark-build/config/tslint.json | 2 +- packages/stark-build/config/webpack.common.js | 34 +- packages/stark-build/config/webpack.prod.js | 12 + packages/stark-core/package.json | 2 +- packages/stark-core/src/http/http.module.ts | 18 +- .../src/http/services/http.service.spec.ts | 495 +++++++++--------- .../src/http/services/http.service.ts | 105 ++-- .../logging/services/logging.service.spec.ts | 12 +- .../test/unit-testing/unit-testing-utils.ts | 3 - starter/src/app/app.routes.ts | 6 +- starter/src/app/home/home.component.ts | 51 +- 13 files changed, 388 insertions(+), 377 deletions(-) diff --git a/packages/rollup.config.common-data.js b/packages/rollup.config.common-data.js index 432dbcbb91..00b7194ec2 100644 --- a/packages/rollup.config.common-data.js +++ b/packages/rollup.config.common-data.js @@ -7,33 +7,21 @@ const commonjs = require("rollup-plugin-commonjs"); const sourcemaps = require("rollup-plugin-sourcemaps"); const globals = { - "class-validator": "class-validator", - cerialize: "cerialize", "@angular/core": "ng.core", "@angular/common/http": "angular.common.http", - rxjs: "rxjs", - "@ngrx/store": "@ngrx/store", + "class-validator": "class-validator", + cerialize: "cerialize", moment: "moment", uuid: "uuid", + rxjs: "rxjs", + // this should be the preferred way to import RxJS operators: https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md // we should only use that in our code base "rxjs/operators": "rxjs.operators", - // so that we can get rid of those: https://github.com/NationalBankBelgium/stark/issues/232 - "rxjs/add/operator/catch": "Rx.Observable.prototype", - "rxjs/add/operator/map": "Rx.Observable.prototype", - "rxjs/add/operator/mergeMap": "Rx.Observable.prototype", - "rxjs/add/operator/retryWhen": "Rx.Observable.prototype", - "rxjs/add/operator/toPromise": "Rx.Observable.prototype", - - // TODO could we also get rid of those? "rxjs/Observable": "Rx", - "rxjs/add/observable/of": "Rx.Observable.prototype", - "rxjs/add/observable/throw": "Rx.Observable.prototype", - "rxjs/add/observable/timer": "Rx.Observable.prototype", - "rxjs/Subject": "Rx", //"rxjs/Subscription": "Rx", diff --git a/packages/stark-build/config/build-utils.js b/packages/stark-build/config/build-utils.js index ee893705aa..cdb7d24f49 100644 --- a/packages/stark-build/config/build-utils.js +++ b/packages/stark-build/config/build-utils.js @@ -56,15 +56,16 @@ function getEnvFile(suffix) { /** * Read the tsconfig to determine if we should prefer ES2015 modules. * Load rxjs path aliases. - * https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#build-and-treeshaking + * https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#build-and-treeshaking * @param supportES2015 Set to true when the output of typescript is >= ES6 */ function rxjsAlias(supportES2015) { try { const rxjsPathMappingImport = supportES2015 ? "rxjs/_esm2015/path-mapping" : "rxjs/_esm5/path-mapping"; const rxPaths = require(rxjsPathMappingImport); - return rxPaths(helpers.root("node_modules")); + return rxPaths(); } catch (e) { + console.warn(e); return {}; } } diff --git a/packages/stark-build/config/tslint.json b/packages/stark-build/config/tslint.json index d34a5c1e4a..06ddd043c3 100644 --- a/packages/stark-build/config/tslint.json +++ b/packages/stark-build/config/tslint.json @@ -183,7 +183,7 @@ "no-import-side-effect": [ true, { - "ignore-module": "(rxjs|reflect-metadata|core-js|ngrx-store|angular|polyfills|vendor|typings|\\.css|\\.pcss)" + "ignore-module": "(reflect-metadata|core-js|ngrx-store|angular|polyfills|vendor|typings|\\.css|\\.pcss)" } ], "no-non-null-assertion": true, diff --git a/packages/stark-build/config/webpack.common.js b/packages/stark-build/config/webpack.common.js index f0b492109a..ac9a6d5ead 100644 --- a/packages/stark-build/config/webpack.common.js +++ b/packages/stark-build/config/webpack.common.js @@ -39,7 +39,7 @@ module.exports = function(options) { }; const tsConfigApp = buildUtils.readTsConfig(helpers.root(METADATA.tsConfigPath)); - + const defaultNgcOptions = { generateCodeForLibraries: true, skipMetadataEmit: false, @@ -70,12 +70,28 @@ module.exports = function(options) { }; return { + /** + * Stats lets you precisely control what bundle information gets displayed + * reference: https://webpack.js.org/configuration/stats/ + */ stats: { + assets: true, + children: true, + chunks: true, + chunkModules: false, + chunkOrigins: false, colors: true, - reasons: true, - errorDetails: true // display error details. Same as the --show-error-details flag - // maxModules: Infinity, // examine all modules (ModuleConcatenationPlugin debugging) - // optimizationBailout: true // display bailout reasons (ModuleConcatenationPlugin debugging) + errors: true, + errorDetails: true, // display error details. Same as the --show-error-details flag, + hash: true, + modules: true, + moduleTrace: true, + performance: true, + reasons: false, + source: true, + timings: true, + version: true, + warnings: true }, /** @@ -114,23 +130,23 @@ module.exports = function(options) { modules: [helpers.root("src"), helpers.root("node_modules")], /** - * Add support for lettable operators. + * Add support for pipeable operators. * * For existing codebase a refactor is required. * All rxjs operator imports (e.g. `import 'rxjs/add/operator/map'` or `import { map } from `rxjs/operator/map'` * must change to `import { map } from 'rxjs/operators'` (note that all operators are now under that import. * Additionally some operators have changed to to JS keyword constraints (do => tap, catch => catchError) * - * Remember to use the `pipe()` method to chain operators, this functinoally makes lettable operators similar to + * Remember to use the `pipe()` method to chain operators, this functionally makes pipeable operators similar to * the old operators usage paradigm. * * For more details see: - * https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#build-and-treeshaking + * https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#build-and-treeshaking * * If you are not planning on refactoring your codebase (or not planning on using imports from `rxjs/operators` * comment out this line. * - * BE AWARE that not using lettable operators will probably result in significant payload added to your bundle. + * BE AWARE that not using pipeable operators will probably result in significant payload added to your bundle. */ alias: buildUtils.rxjsAlias(supportES2015) }, diff --git a/packages/stark-build/config/webpack.prod.js b/packages/stark-build/config/webpack.prod.js index 3bc5c89daf..455f302e53 100644 --- a/packages/stark-build/config/webpack.prod.js +++ b/packages/stark-build/config/webpack.prod.js @@ -59,6 +59,18 @@ module.exports = function() { METADATA.envFileSuffix = METADATA.E2E ? "e2e.prod" : "prod"; return webpackMerge(commonConfig({ ENV: ENV, metadata: METADATA }), { + /** + * Stats lets you precisely control what bundle information gets displayed + * reference: https://webpack.js.org/configuration/stats/ + */ + stats: { + chunkModules: true, + chunkOrigins: true, + reasons: true, + maxModules: Infinity, // examine all modules (ModuleConcatenationPlugin debugging) + optimizationBailout: true // display bailout reasons (ModuleConcatenationPlugin debugging) + }, + /** * Options affecting the output of the compilation. * diff --git a/packages/stark-core/package.json b/packages/stark-core/package.json index f11af93903..a9d8f1ecaa 100644 --- a/packages/stark-core/package.json +++ b/packages/stark-core/package.json @@ -59,7 +59,7 @@ }, "scripts": { "ngc": "ngc", - "lint": "tslint --config tslint.json --project ./tsconfig.json --format codeFrame", + "lint": "tslint --config tslint.json --project ./tsconfig.spec.json --format codeFrame", "test-fast": "node ./node_modules/@nationalbankbelgium/stark-testing/node_modules/karma/bin/karma start ./karma.conf.typescript.js", "test-fast:ci": "node ./node_modules/@nationalbankbelgium/stark-testing/node_modules/karma/bin/karma start karma.conf.typescript.ci.js", "tsc": "tsc -p tsconfig.json", diff --git a/packages/stark-core/src/http/http.module.ts b/packages/stark-core/src/http/http.module.ts index 55b0c8daf2..db17de7c4a 100644 --- a/packages/stark-core/src/http/http.module.ts +++ b/packages/stark-core/src/http/http.module.ts @@ -3,7 +3,7 @@ import { HttpClient, HttpClientModule } from "@angular/common/http"; import { StarkHttpServiceImpl, starkHttpServiceName } from "./services/index"; // FIXME: remove this factory once LoggingService and SessionService are implemented -const starkHttpServiceFactory: any = (httpClient: HttpClient) => { +const starkHttpServiceFactory = (httpClient: HttpClient) => { const logger: any = { debug: console.debug, warn: console.warn, @@ -12,17 +12,23 @@ const starkHttpServiceFactory: any = (httpClient: HttpClient) => { }; const sessionService: any = { - fakePreAuthenticationHeaders: new Map([["nbb-dummy-header", "some value"], ["nbb-another-header", "whatever"]]) + fakePreAuthenticationHeaders: new Map([ + ["nbb-dummy-header", "some value"], ["nbb-another-header", "whatever"] + ]) }; - return new StarkHttpServiceImpl(logger, sessionService, httpClient); + return new StarkHttpServiceImpl(logger, sessionService, httpClient) }; @NgModule({ - imports: [HttpClientModule], + imports: [ + HttpClientModule + ], providers: [ // FIXME: replace this Factory provider by a simple Class provider once LoggingService and SessionService are implemented - { provide: starkHttpServiceName, useFactory: starkHttpServiceFactory, deps: [HttpClient] } + {provide: starkHttpServiceName, useFactory: starkHttpServiceFactory, deps: [HttpClient]}, ] }) -export class StarkHttpModule {} +export class StarkHttpModule { + +} diff --git a/packages/stark-core/src/http/services/http.service.spec.ts b/packages/stark-core/src/http/services/http.service.spec.ts index 7efb196306..9970264105 100644 --- a/packages/stark-core/src/http/services/http.service.spec.ts +++ b/packages/stark-core/src/http/services/http.service.spec.ts @@ -4,9 +4,12 @@ import createSpyObj = jasmine.createSpyObj; import Spy = jasmine.Spy; import { autoserialize, autoserializeAs, inheritSerialization, Serialize } from "cerialize"; import { Observable } from "rxjs/Observable"; -import "rxjs/add/observable/of"; -import "rxjs/add/observable/throw"; -import "rxjs/add/operator/catch"; +import { of } from "rxjs/observable/of"; +import { _throw as observableThrow } from "rxjs/observable/throw"; +// FIXME: importing from single entry "rxjs/operators" together with webpack's scope hoisting prevents dead code removal +// see https://github.com/ReactiveX/rxjs/issues/2981 +// import { catchError } from "rxjs/operators"; +import { catchError } from "rxjs/operators/catchError"; import { ErrorObservable } from "rxjs/observable/ErrorObservable"; import { HttpClient, HttpHeaders, HttpResponse } from "@angular/common/http"; @@ -97,7 +100,9 @@ describe("Service: StarkHttpService", () => { titleKey: "errors.user.invalid", detail: mockHttpErrorDetail1, detailKey: "errors.user.invalid.username.already.in.use", - fields: ["username"], + fields: [ + "username" + ], instance: mockHttpErrorInstance }, { @@ -106,7 +111,9 @@ describe("Service: StarkHttpService", () => { titleKey: "errors.user.invalid", detail: mockHttpErrorDetail2, detailKey: "errors.user.invalid.username.missing", - fields: [mockHttpErrorDetailField1, mockHttpErrorDetailField2], + fields: [ + mockHttpErrorDetailField1, mockHttpErrorDetailField2 + ], instance: mockHttpErrorInstance }, { @@ -115,7 +122,9 @@ describe("Service: StarkHttpService", () => { titleKey: "errors.user.invalid", detail: mockHttpErrorDetail3, detailKey: "errors.user.invalid.e-mail", - fields: [" e-mail"], + fields: [ + " e-mail" + ], instance: mockHttpErrorInstance } ] @@ -134,7 +143,7 @@ describe("Service: StarkHttpService", () => { mockResourceWithoutEtag = new MockResource(mockUuid); mockResourceWithoutEtag.property1 = mockProperty1; mockResourceWithoutEtag.property2 = mockProperty2; - mockResourceWithEtag = { ...mockResourceWithoutEtag, etag: mockEtag }; + mockResourceWithEtag = {...mockResourceWithoutEtag, etag: mockEtag}; mockResourceWithMetadata = { ...mockResourceWithoutEtag, etag: mockEtag, @@ -176,11 +185,9 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -198,12 +205,15 @@ describe("Service: StarkHttpService", () => { expect(result.data.metadata).toBeUndefined(); expect(httpMock.get).toHaveBeenCalledTimes(1); - expect(httpMock.get).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.get).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); }, () => { fail("The 'error' function should not be called in case of success"); @@ -217,11 +227,9 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithMetadata, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -265,11 +273,9 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.get).and.returnValue(observableThrow(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -304,12 +310,15 @@ describe("Service: StarkHttpService", () => { expect(errorWrapper.starkHttpHeaders.get(expiresKey)).toBe(expiresValue); expect(httpMock.get).toHaveBeenCalledTimes(1); - expect(httpMock.get).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.get).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); } ); }); @@ -322,18 +331,16 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.get).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.get).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -374,11 +381,9 @@ describe("Service: StarkHttpService", () => { body: undefined, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.delete).and.returnValue(Observable.of(httpResponse)); + ( httpMock.delete).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -391,12 +396,15 @@ describe("Service: StarkHttpService", () => { expect(result.starkHttpHeaders.get(expiresKey)).toBe(expiresValue); expect(httpMock.delete).toHaveBeenCalledTimes(1); - expect(httpMock.delete).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.delete).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); }, () => { fail("The 'error' function should not be called in case of success"); @@ -410,11 +418,9 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.delete).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.delete).and.returnValue(observableThrow(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -449,12 +455,15 @@ describe("Service: StarkHttpService", () => { expect(errorWrapper.starkHttpHeaders.get(expiresKey)).toBe(expiresValue); expect(httpMock.delete).toHaveBeenCalledTimes(1); - expect(httpMock.delete).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.delete).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); } ); }); @@ -467,18 +476,16 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.delete).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.delete).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -519,13 +526,11 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe((result: StarkSingleItemResponseWrapper) => { expect(result).toBeDefined(); @@ -549,13 +554,11 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -596,13 +599,11 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithMetadata, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -646,13 +647,11 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.put).and.returnValue(Observable.of(httpResponse)); + ( httpMock.put).and.returnValue(of(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE_IDEMPOTENT; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -693,13 +692,11 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithMetadata, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.put).and.returnValue(Observable.of(httpResponse)); + ( httpMock.put).and.returnValue(of(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE_IDEMPOTENT; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -743,13 +740,11 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.post).and.returnValue(observableThrow(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -806,19 +801,17 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.post).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.post).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.requestType = StarkHttpRequestType.UPDATE; request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -842,13 +835,11 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.put).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.put).and.returnValue(observableThrow(httpResponse)); request.requestType = StarkHttpRequestType.UPDATE_IDEMPOTENT; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -905,19 +896,17 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.put).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.put).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.requestType = StarkHttpRequestType.UPDATE_IDEMPOTENT; request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -958,11 +947,9 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe((result: StarkSingleItemResponseWrapper) => { expect(result).toBeDefined(); @@ -986,11 +973,9 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithEtag, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -1030,11 +1015,9 @@ describe("Service: StarkHttpService", () => { body: mockResourceWithMetadata, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( (result: StarkSingleItemResponseWrapper) => { @@ -1078,11 +1061,9 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.post).and.returnValue(observableThrow(httpResponse)); - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -1138,18 +1119,16 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.post).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.post).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeSingleItemRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeSingleItemRequest(request); resultObs.subscribe( () => { @@ -1191,7 +1170,16 @@ describe("Service: StarkHttpService", () => { prop1: 1234, prop2: "whatever", prop3: "2016-03-18T18:25:43.511Z", - prop4: ["some value", "false", "null", "", true, false, 0, { name: "Christopher", surname: "Cortes" }] + prop4: [ + "some value", + "false", + "null", + "", + true, + false, + 0, + {name: "Christopher", surname: "Cortes"} + ] }; describe("with a GetCollection request", () => { @@ -1217,7 +1205,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [ { @@ -1240,11 +1230,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1293,12 +1281,15 @@ describe("Service: StarkHttpService", () => { expect(loggerMock.warn).not.toHaveBeenCalled(); expect(httpMock.get).toHaveBeenCalledTimes(1); - expect(httpMock.get).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.get).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); }, () => { fail("The 'error' function should not be called in case of success"); @@ -1310,7 +1301,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -1327,11 +1320,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1363,7 +1354,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -1380,11 +1373,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1436,17 +1427,15 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { expect(result).toBeDefined(); expect(result.starkHttpStatusCode).toBe(StarkHttpStatusCodes.HTTP_200_OK); - expect(result.data).toBeDefined(); // the data is whatever it comes in the "items" property + expect(result.data).toBeDefined(); // the data is whatever it comes in the "items" property expect(result.metadata instanceof StarkCollectionMetadataImpl).toBe(true); expect(result.metadata.sortedBy.length).toBe(0); expect(result.metadata.pagination).toBeDefined(); @@ -1467,8 +1456,7 @@ describe("Service: StarkHttpService", () => { const etags: { [uuid: string]: string } = {}; etags[mockUuid] = mockEtag; - const items: any[] = [ - // non-object item in "items" array + const items: any[] = [ // non-object item in "items" array "some value" ]; @@ -1492,11 +1480,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1526,13 +1512,15 @@ describe("Service: StarkHttpService", () => { const etags: { [uuid: string]: string } = {}; etags[mockUuid] = mockEtag; - const mockResourceWithoutUuid: MockResource = { ...mockResourceWithEtag }; + const mockResourceWithoutUuid: MockResource = {...mockResourceWithEtag}; delete mockResourceWithoutUuid.uuid; const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutUuid], + items: [ + mockResourceWithoutUuid + ], metadata: { sortedBy: [], pagination: { @@ -1549,11 +1537,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1589,7 +1575,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -1607,11 +1595,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1643,16 +1629,16 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: undefined }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.of(httpResponse)); + ( httpMock.get).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1679,11 +1665,9 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.get).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.get).and.returnValue(observableThrow(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( () => { @@ -1718,12 +1702,15 @@ describe("Service: StarkHttpService", () => { expect(errorWrapper.starkHttpHeaders.get(expiresKey)).toBe(expiresValue); expect(httpMock.get).toHaveBeenCalledTimes(1); - expect(httpMock.get).toHaveBeenCalledWith("www.awesomeapi.com/mock", { - params: convertMapIntoObject(request.queryParameters), - headers: convertMapIntoObject(headersMap), - observe: "response", - responseType: "json" - }); + expect(httpMock.get).toHaveBeenCalledWith( + "www.awesomeapi.com/mock", + { + params: convertMapIntoObject(request.queryParameters), + headers: convertMapIntoObject(headersMap), + observe: "response", + responseType: "json" + } + ); } ); }); @@ -1736,18 +1723,16 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.get).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.get).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( () => { @@ -1768,7 +1753,7 @@ describe("Service: StarkHttpService", () => { describe("with a Search request", () => { let request: StarkHttpRequest; - const mockCriteria: { [key: string]: any } = { field1: "anything", field2: "whatever" }; + const mockCriteria: { [key: string]: any } = {field1: "anything", field2: "whatever"}; beforeEach(() => { request = { @@ -1790,7 +1775,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [ { @@ -1813,11 +1800,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1887,7 +1872,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -1904,11 +1891,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -1940,7 +1925,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -1957,11 +1944,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -2013,17 +1998,15 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { expect(result).toBeDefined(); expect(result.starkHttpStatusCode).toBe(StarkHttpStatusCodes.HTTP_200_OK); - expect(result.data).toBeDefined(); // the data is whatever it comes in the "items" property + expect(result.data).toBeDefined(); // the data is whatever it comes in the "items" property expect(result.metadata instanceof StarkCollectionMetadataImpl).toBe(true); expect(result.metadata.sortedBy.length).toBe(0); expect(result.metadata.pagination).toBeDefined(); @@ -2044,8 +2027,7 @@ describe("Service: StarkHttpService", () => { const etags: { [uuid: string]: string } = {}; etags[mockUuid] = mockEtag; - const items: any[] = [ - // non-object item in "items" array + const items: any[] = [ // non-object item in "items" array "some value" ]; @@ -2069,11 +2051,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -2103,13 +2083,15 @@ describe("Service: StarkHttpService", () => { const etags: { [uuid: string]: string } = {}; etags[mockUuid] = mockEtag; - const mockResourceWithoutUuid: MockResource = { ...mockResourceWithEtag }; + const mockResourceWithoutUuid: MockResource = {...mockResourceWithEtag}; delete mockResourceWithoutUuid.uuid; const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutUuid], + items: [ + mockResourceWithoutUuid + ], metadata: { sortedBy: [], pagination: { @@ -2126,11 +2108,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -2166,7 +2146,9 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: { sortedBy: [], pagination: { @@ -2184,11 +2166,9 @@ describe("Service: StarkHttpService", () => { }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -2220,16 +2200,16 @@ describe("Service: StarkHttpService", () => { const httpResponse: Partial>> = { status: StarkHttpStatusCodes.HTTP_200_OK, body: { - items: [mockResourceWithoutEtag], + items: [ + mockResourceWithoutEtag + ], metadata: undefined }, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.of(httpResponse)); + ( httpMock.post).and.returnValue(of(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( (result: StarkCollectionResponseWrapper) => { @@ -2256,11 +2236,9 @@ describe("Service: StarkHttpService", () => { body: mockHttpError, headers: httpHeadersGetter(httpHeaders) }; - (httpMock.post).and.returnValue(Observable.throw(httpResponse)); + ( httpMock.post).and.returnValue(observableThrow(httpResponse)); - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( () => { @@ -2317,18 +2295,16 @@ describe("Service: StarkHttpService", () => { headers: httpHeadersGetter(httpHeaders) }; let errorCounter: number = 0; - (httpMock.post).and.returnValue( - Observable.throw(httpResponse).catch((err: any) => { + ( httpMock.post).and.returnValue(observableThrow(httpResponse).pipe( + catchError((err: any) => { errorCounter++; - return Observable.throw(err); + return observableThrow(err); }) - ); + )); request.retryCount = 2; - const resultObs: Observable> = starkHttpService.executeCollectionRequest( - request - ); + const resultObs: Observable> = starkHttpService.executeCollectionRequest(request); resultObs.subscribe( () => { @@ -2429,19 +2405,25 @@ describe("Service: StarkHttpService", () => { @inheritSerialization(StarkSingleItemMetadataImpl) class MockResourceMetadata extends StarkSingleItemMetadataImpl { - @autoserialize public someValue?: string; + @autoserialize + public someValue?: string; } class MockResource implements StarkResource { - @autoserialize public uuid: string; + @autoserialize + public uuid: string; - @autoserialize public etag: string; + @autoserialize + public etag: string; - @autoserializeAs(MockResourceMetadata) public metadata: MockResourceMetadata; + @autoserializeAs(MockResourceMetadata) + public metadata: MockResourceMetadata; - @autoserialize public property1: string; + @autoserialize + public property1: string; - @autoserialize public property2: string; + @autoserialize + public property2: string; public constructor(uuid: string) { this.uuid = uuid; @@ -2465,6 +2447,7 @@ function convertMapIntoObject(map: Map): object { } class HttpServiceHelper

extends StarkHttpServiceImpl

{ + public retryDelay: number; public constructor(logger: StarkLoggingService, sessionService: StarkSessionService, $http: HttpClient) { diff --git a/packages/stark-core/src/http/services/http.service.ts b/packages/stark-core/src/http/services/http.service.ts index 55aebb6774..5c2541c204 100644 --- a/packages/stark-core/src/http/services/http.service.ts +++ b/packages/stark-core/src/http/services/http.service.ts @@ -3,12 +3,15 @@ const _cloneDeep: Function = require("lodash/cloneDeep"); import { Deserialize, Serialize } from "cerialize"; import { Observable } from "rxjs/Observable"; -import "rxjs/add/observable/timer"; -import "rxjs/add/observable/throw"; -import "rxjs/add/operator/catch"; -import "rxjs/add/operator/map"; -import "rxjs/add/operator/retryWhen"; -import "rxjs/add/operator/mergeMap"; +import { timer } from "rxjs/observable/timer"; +import { _throw as observableThrow } from "rxjs/observable/throw"; +// FIXME: importing from single entry "rxjs/operators" together with webpack's scope hoisting prevents dead code removal +// see https://github.com/ReactiveX/rxjs/issues/2981 +// import { catchError, map, mergeMap, retryWhen } from "rxjs/operators"; +import { catchError } from "rxjs/operators/catchError"; +import { map } from "rxjs/operators/map"; +import { retryWhen } from "rxjs/operators/retryWhen"; +import { mergeMap } from "rxjs/operators/mergeMap"; import { Injectable } from "@angular/core"; import { HttpClient, HttpHeaders, HttpResponse } from "@angular/common/http"; @@ -50,11 +53,9 @@ export class StarkHttpServiceImpl

implements StarkHttpS private httpClient: HttpClient; // FIXME: uncomment these lines once LoggingService and SessionService are implemented - public constructor( - /*@Inject(starkLoggingServiceName)*/ logger: StarkLoggingService, - /*@Inject(starkSessionServiceName)*/ sessionService: StarkSessionService, - httpClient: HttpClient - ) { + public constructor(/*@Inject(starkLoggingServiceName)*/ logger: StarkLoggingService, + /*@Inject(starkSessionServiceName)*/ sessionService: StarkSessionService, + httpClient: HttpClient) { this.logger = logger; this.sessionService = sessionService; this.httpClient = httpClient; @@ -100,11 +101,11 @@ export class StarkHttpServiceImpl

implements StarkHttpS if (httpResponse$) { return this.getSingleItemResponseWrapperObservable(httpResponse$, request); } else { - return Observable.throw( + return observableThrow( "Unknown request type encountered " + - request.requestType + - ". For collection requests, " + - "call the executeCollectionRequest method" + request.requestType + + ". For collection requests, " + + "call the executeCollectionRequest method" ); } } @@ -138,11 +139,11 @@ export class StarkHttpServiceImpl

implements StarkHttpS return this.getCollectionResponseWrapperObservable(httpResponse$, request); } else { // we return directly here because otherwise compilation fails (can't assign the ErrorObservable type to Subject) - return Observable.throw( + return observableThrow( "Unknown request type encountered " + - request.requestType + - ". For single requests (no " + - "collection), call the executeSingleItemRequest method" + request.requestType + + ". For single requests (no " + + "collection), call the executeSingleItemRequest method" ); } } @@ -280,10 +281,10 @@ export class StarkHttpServiceImpl

implements StarkHttpS ); } - private convertMapIntoObject(map: Map): { [param: string]: any } { + private convertMapIntoObject(mapObj: Map): { [param: string]: any } { const resultObj: { [param: string]: any } = {}; - map.forEach((value: any, key: string) => { + mapObj.forEach((value: any, key: string) => { resultObj[key] = value; }); @@ -310,8 +311,8 @@ export class StarkHttpServiceImpl

implements StarkHttpS httpResponse$ = this.addRetryLogic(httpResponse$, retryCount); } - return httpResponse$ - .map((result: HttpResponse

) => { + return httpResponse$.pipe( + map((result: HttpResponse

) => { const httpResponseHeaders: Map = this.getResponseHeaders(result.headers); const resource: P = this.deserialize(result.body, request, result); @@ -320,13 +321,14 @@ export class StarkHttpServiceImpl

implements StarkHttpS } return new StarkSingleItemResponseWrapperImpl

(result.status, httpResponseHeaders, resource); - }) - .catch((result: HttpResponse

) => { + }), + catchError((result: HttpResponse

) => { const httpError: StarkHttpError = Deserialize(result.body, StarkHttpErrorImpl); const httpResponseHeaders: Map = this.getResponseHeaders(result.headers); - return Observable.throw(new StarkHttpErrorWrapperImpl(result.status, httpResponseHeaders, httpError)); - }); + return observableThrow(new StarkHttpErrorWrapperImpl(result.status, httpResponseHeaders, httpError)); + }) + ); } private getCollectionResponseWrapperObservable( @@ -339,8 +341,8 @@ export class StarkHttpServiceImpl

implements StarkHttpS httpResponse$ = this.addRetryLogic(httpResponse$, retryCount); } - return httpResponse$ - .map((result: HttpResponse>) => { + return httpResponse$.pipe( + map((result: HttpResponse>) => { const httpResponseHeaders: Map = this.getResponseHeaders(result.headers); if ((>result.body).items instanceof Array) { if ((>result.body).metadata) { @@ -351,7 +353,7 @@ export class StarkHttpServiceImpl

implements StarkHttpS if (((>result.body).metadata.etags)[item.uuid]) { item.etag = ((>result.body).metadata.etags)[ item.uuid - ]; + ]; } else { this.logger.warn(starkHttpServiceName + ": no etag found for resource with uuid ", item.uuid); } @@ -361,9 +363,9 @@ export class StarkHttpServiceImpl

implements StarkHttpS } else { this.logger.warn( starkHttpServiceName + - ": cannot set the etag property in the item '" + - item + - "' because it is not an object" + ": cannot set the etag property in the item '" + + item + + "' because it is not an object" ); } } @@ -383,27 +385,32 @@ export class StarkHttpServiceImpl

implements StarkHttpS items instanceof Array ? items.map((item: object) => this.deserialize(item, request, result)) : items, Deserialize((>result.body).metadata, StarkCollectionMetadataImpl) ); - }) - .catch((result: HttpResponse

) => { + }), + catchError((result: HttpResponse

) => { const httpError: StarkHttpError = Deserialize(result.body, StarkHttpErrorImpl); const httpResponseHeaders: Map = this.getResponseHeaders(result.headers); - return Observable.throw(new StarkHttpErrorWrapperImpl(result.status, httpResponseHeaders, httpError)); - }); + return observableThrow(new StarkHttpErrorWrapperImpl(result.status, httpResponseHeaders, httpError)); + }) + ); } private addRetryLogic(httpResponse$: Observable>, retryCount: number): Observable> { - return httpResponse$.retryWhen((errors: Observable) => { - let retries: number = 0; - return errors.mergeMap((error: HttpResponse

) => { - if (retries < retryCount) { - retries++; - return Observable.timer(this.retryDelay); - } else { - return Observable.throw(error); - } - }); - }); + return httpResponse$.pipe( + retryWhen((errors: Observable) => { + let retries: number = 0; + return errors.pipe( + mergeMap((error: HttpResponse

) => { + if (retries < retryCount) { + retries++; + return timer(this.retryDelay); + } else { + return observableThrow(error); + } + }) + ); + }) + ) } private serialize(entity: P, request: StarkHttpRequest

): string | object { @@ -411,7 +418,7 @@ export class StarkHttpServiceImpl

implements StarkHttpS } private deserialize( - rawEntity: string | object, + rawEntity: string | object, request: StarkHttpRequest

, response: HttpResponse

> ): P { diff --git a/packages/stark-core/src/logging/services/logging.service.spec.ts b/packages/stark-core/src/logging/services/logging.service.spec.ts index e15809ad7c..5c3be42601 100644 --- a/packages/stark-core/src/logging/services/logging.service.spec.ts +++ b/packages/stark-core/src/logging/services/logging.service.spec.ts @@ -3,8 +3,8 @@ import Spy = jasmine.Spy; import { Action, Store } from "@ngrx/store"; import { Observable } from "rxjs/Observable"; -import "rxjs/add/observable/of"; -import "rxjs/add/observable/throw"; +import { of } from "rxjs/observable/of"; +import { _throw as observableThrow } from "rxjs/observable/throw"; import { Serialize } from "cerialize"; import { StarkLoggingActionTypes, FlushLogMessages } from "../../logging/actions/index"; @@ -66,7 +66,7 @@ describe("Service: StarkLoggingService", () => { applicationId: "dummy app id", messages: [] }; - (mockStore.select).and.returnValue(Observable.of(mockStarkLogging)); + (mockStore.select).and.returnValue(of(mockStarkLogging)); loggingService = new LoggingServiceHelper(mockStore, appConfig /*, mockXSRFService*/); // reset the calls counter because there is a log in the constructor (mockStore.dispatch).calls.reset(); @@ -248,7 +248,7 @@ describe("Service: StarkLoggingService", () => { it("should persist messages to the back-end when the persist size exceeds", () => { expect(mockStarkLogging.messages.length).toBe(loggingFlushPersistSize); - const sendRequestSpy: Spy = spyOn(loggingService, "sendRequest").and.callFake(() => Observable.of("ok")); + const sendRequestSpy: Spy = spyOn(loggingService, "sendRequest").and.callFake(() => of("ok")); const data: string = JSON.stringify(Serialize(mockStarkLogging, StarkLoggingImpl)); (loggingService).persistLogMessagesHelper(); expect(sendRequestSpy).toHaveBeenCalledTimes(1); @@ -263,7 +263,7 @@ describe("Service: StarkLoggingService", () => { it("should fail to persist messages when the back-end fails", () => { expect(mockStarkLogging.messages.length).toBe(loggingFlushPersistSize); - const sendRequestSpy: Spy = spyOn(loggingService, "sendRequest").and.callFake(() => Observable.throw("ko")); + const sendRequestSpy: Spy = spyOn(loggingService, "sendRequest").and.callFake(() => observableThrow("ko")); const errorSpy: Spy = spyOn(loggingService, "error"); const data: string = JSON.stringify(Serialize(mockStarkLogging, StarkLoggingImpl)); (loggingService).persistLogMessagesHelper(); @@ -292,7 +292,7 @@ class LoggingServiceHelper extends StarkLoggingServiceImpl { // override parent's implementation to prevent actual HTTP request to be sent! public sendRequest(): Observable { /* dummy function to be mocked */ - return Observable.of(undefined); + return of(undefined); } // override parent's implementation to prevent logging to the console diff --git a/packages/stark-core/src/test/unit-testing/unit-testing-utils.ts b/packages/stark-core/src/test/unit-testing/unit-testing-utils.ts index 8bdb92821a..db8c89c39a 100644 --- a/packages/stark-core/src/test/unit-testing/unit-testing-utils.ts +++ b/packages/stark-core/src/test/unit-testing/unit-testing-utils.ts @@ -1,8 +1,5 @@ "use strict"; -import "rxjs/add/observable/of"; -import "rxjs/add/operator/toPromise"; - import { StarkLoggingService, starkLoggingServiceName } from "../..//logging/index"; import { StarkSessionService, starkSessionServiceName } from "../../session/index"; import { StarkHttpHeaders, StarkHttpService, starkHttpServiceName } from "../../http/index"; diff --git a/starter/src/app/app.routes.ts b/starter/src/app/app.routes.ts index b5c52ac90f..c11a6c2c06 100644 --- a/starter/src/app/app.routes.ts +++ b/starter/src/app/app.routes.ts @@ -3,7 +3,7 @@ import { AboutComponent } from "./about"; import { NoContentComponent } from "./no-content"; import { Ng2StateDeclaration, Transition } from "@uirouter/angular"; import { of } from "rxjs/observable/of"; -import "rxjs/add/operator/delay"; +import { delay } from "rxjs/operators/delay"; import { Observable } from "rxjs/Observable"; export function getResolvedData(): Observable { @@ -12,14 +12,14 @@ export function getResolvedData(): Observable { // if resolve policy = 'WAIT' or 'NOWAIT' the component WILL BE LOADED WITHOUT // WAITING FOR THE OBSERVABLE TO EMIT // if resolve policy = 'RXWAIT', the component WILL BE LOADED UNTIL THE OBSERVABLE EMITS - return of({ resolve: "I am data from the resolve" }).delay(5000); + return of({ resolve: "I am data from the resolve" }).pipe(delay(5000)); // could return a promise // when resolve policy is 'WAIT', the component WILL BE LOADED UNTIL THE PROMISE // IS RESOLVED and the value will be already unwrapped // when resolve policy is 'NOWAIT', the component WILL BE LOADED WITHOUT // WAITING FOR IT but the component should unwrap the promise - // return of({ resolve: 'I am data from the resolve'}).delay(5000).toPromise(); + // return of({ resolve: 'I am data from the resolve'}).pipe(delay(5000)).toPromise(); } export function getParamData($transition$: Transition): any { diff --git a/starter/src/app/home/home.component.ts b/starter/src/app/home/home.component.ts index 18be8cab94..db0f9ae087 100644 --- a/starter/src/app/home/home.component.ts +++ b/starter/src/app/home/home.component.ts @@ -11,7 +11,7 @@ import { starkHttpServiceName, StarkSingleItemResponseWrapper } from "@nationalbankbelgium/stark-core"; -import { Observable } from "rxjs/Observable"; +import { Observable } from "rxjs/Observable" import { AppState } from "../app.service"; import { Title } from "./title"; @@ -41,16 +41,15 @@ export class HomeComponent implements OnInit { /** * Set our default values */ - public localState: any = { value: " " }; + public localState: any = {value: " "}; /** * TypeScript public modifiers */ - public constructor( - public appState: AppState, - public title: Title, - @Inject(starkHttpServiceName) public httpService: StarkHttpService - ) {} + public constructor(public appState: AppState, + public title: Title, + @Inject(starkHttpServiceName) public httpService: StarkHttpService) { + } public ngOnInit(): void { console.log("hello `Home` component"); @@ -78,25 +77,27 @@ export class HomeComponent implements OnInit { let httpRequest$: Observable | StarkCollectionResponseWrapper>; if (type === "singleItem") { - httpRequest$ = this.httpService.executeSingleItemRequest({ - backend: backend, - resourcePath: "requests/11", - headers: new Map(), - queryParameters: new Map(), - requestType: StarkHttpRequestType.GET, - serializer: serializer, - retryCount: 4 - }); + httpRequest$ = this.httpService + .executeSingleItemRequest({ + backend: backend, + resourcePath: "requests/11", + headers: new Map(), + queryParameters: new Map(), + requestType: StarkHttpRequestType.GET, + serializer: serializer, + retryCount: 4 + }) } else { - httpRequest$ = this.httpService.executeCollectionRequest({ - backend: backend, - resourcePath: "requests", - headers: new Map(), - queryParameters: new Map(), - requestType: StarkHttpRequestType.GET_COLLECTION, - serializer: serializer, - retryCount: 4 - }); + httpRequest$ = this.httpService + .executeCollectionRequest({ + backend: backend, + resourcePath: "requests", + headers: new Map(), + queryParameters: new Map(), + requestType: StarkHttpRequestType.GET_COLLECTION, + serializer: serializer, + retryCount: 4 + }) } httpRequest$.subscribe(