Skip to content

Commit 3a9a3cb

Browse files
authored
Merge pull request #784 from nemtech/dev
Dev -> Main
2 parents 1bb1d1c + e18100f commit 3a9a3cb

File tree

7 files changed

+1113
-1770
lines changed

7 files changed

+1113
-1770
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
44

55
The changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

7+
## [1.0.1] - 24-May-2021
8+
9+
**Milestone**: Symbol Mainnet
10+
Package | Version | Link
11+
---|---|---
12+
SDK Core| v1.0.1 | [symbol-sdk](https://www.npmjs.com/package/symbol-sdk)
13+
Catbuffer | v1.0.0 | [catbuffer-typescript](https://www.npmjs.com/package/catbuffer-typescript)
14+
Client Library | v1.0.0 | [symbol-openapi-typescript-fetch-client](https://www.npmjs.com/package/symbol-openapi-typescript-fetch-client)
15+
16+
- Fixed missing `utf-8` dependancy issue.
17+
- Fixed `UnhandledPromiseRejection` issue in http repository.
18+
719
## [1.0.0] - 13-Mar-2021
820

921
**Milestone**: Symbol Mainnet

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The Symbol SDK for TypeScript / JavaScript allows you to develop web, mobile, an
1111

1212
### _Catapult-Server_ Network Compatibility ([email protected])
1313

14-
Symbol network pre-launch [catapult-server](https://github.com/nemtech/catapult-server/releases/tag/v0.10.0.8), **it is recommended to use this package's 0.23.3 version and upwards for the upcoming pre-release versions and final release**.
14+
Symbol network launched [catapult-server](https://github.com/nemtech/catapult-server/releases/tag/v1.0.0.0), **it is recommended to use this package's 1.0.0 version and upwards for the Symbol public network**.
1515

1616
Find the complete release notes [here](CHANGELOG.md).
1717

package-lock.json

+1,013-1,696
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
"scripts": {
66
"pretest": "npm run build",
77
"prepack": "npm run build",
8-
"test": "mocha --ui bdd --recursive ./dist/test --timeout 90000",
8+
"test": "mocha --ui bdd --recursive ./dist/test --timeout 90000 --unhandled-rejections=strict ",
99
"e2econfigcopy": "gulp",
10-
"test:e2e": "npm run build && mocha --ui bdd --recursive ./dist/e2e --timeout 90000",
10+
"test:e2e": "npm run build && mocha --ui bdd --recursive ./dist/e2e --timeout 90000 --unhandled-rejections=strict",
1111
"e2e": "npm run bootstrap-stop && npm run bootstrap-start-detached && npm run test:e2e && npm run bootstrap-stop",
12-
"test:all": "mocha --ui bdd --recursive ./dist/ --timeout 90000",
12+
"test:all": "mocha --ui bdd --recursive ./dist/ --timeout 90000 --unhandled-rejections=strict",
1313
"build": "shx rm -rf dist/ && tsc && npm run e2econfigcopy",
1414
"test:cov": "nyc --reporter=lcov --reporter=text-summary npm t",
1515
"test:coveralls": "npm run test:cov | coveralls",
@@ -91,10 +91,9 @@
9191
"symbol-bootstrap": "^0.4.3",
9292
"ts-mockito": "^2.6.1",
9393
"ts-node": "^8.10.2",
94-
"typedoc": "^0.18.0",
94+
"typedoc": "^0.20.36",
9595
"typescript": "^3.9.7",
96-
"typescript-require": "^0.2.10",
97-
"utf8": "^2.1.2"
96+
"typescript-require": "^0.2.10"
9897
},
9998
"dependencies": {
10099
"@js-joda/core": "^3.2.0",
@@ -115,6 +114,7 @@
115114
"rxjs-compat": "^6.6.3",
116115
"symbol-openapi-typescript-fetch-client": "0.11.2",
117116
"tweetnacl": "^1.0.3",
117+
"utf8": "^2.1.2",
118118
"ws": "^7.3.1"
119119
},
120120
"nyc": {

src/infrastructure/Http.ts

+28-37
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
*/
1616

1717
import fetch from 'node-fetch';
18-
import { from as observableFrom, Observable, of as observableOf, of, throwError } from 'rxjs';
19-
import { catchError, flatMap, map } from 'rxjs/operators';
18+
import { defer, from as observableFrom, Observable, of as observableOf } from 'rxjs';
2019
import { Configuration, NodeRoutesApi, Pagination, querystring } from 'symbol-openapi-typescript-fetch-client';
21-
import { NetworkType } from '../model/network/NetworkType';
20+
import { NetworkType } from '../model/network';
2221
import { Page } from './Page';
2322
import { RepositoryCallError } from './RepositoryCallError';
2423

@@ -33,9 +32,9 @@ export abstract class Http {
3332
*/
3433
protected constructor(protected readonly url: string, protected readonly fetchApi?: any) {}
3534

36-
public static errorHandling(error: any): Observable<never> {
35+
public static async errorHandling(error: any): Promise<Error> {
3736
if (error instanceof Error) {
38-
return throwError(error);
37+
return error;
3938
}
4039
const statusCode: number = parseInt(error?.status || error?.statusCode || error?.response?.statusCode || 0);
4140
const statusMessage: string = (
@@ -55,29 +54,23 @@ export abstract class Http {
5554
return JSON.stringify(body);
5655
};
5756

58-
const getBody = (error: any): Observable<string> => {
57+
const getBody = async (error: any): Promise<string> => {
5958
const body = error?.response?.body;
6059
if (body) {
61-
return of(toString(body));
60+
return toString(body);
6261
}
6362
if (error.text) {
64-
return observableFrom(error.text()).pipe(
65-
map(toString),
66-
catchError(() => of('')),
67-
);
63+
return toString(await error.text());
6864
}
69-
return of('');
65+
return '';
7066
};
71-
return getBody(error).pipe(
72-
flatMap((body: string) => {
73-
const formattedError: RepositoryCallError = {
74-
statusCode,
75-
statusMessage,
76-
body,
77-
};
78-
return throwError(new Error(JSON.stringify(formattedError)));
79-
}),
80-
);
67+
68+
const formattedError: RepositoryCallError = {
69+
statusCode,
70+
statusMessage,
71+
body: await getBody(error),
72+
};
73+
return new Error(JSON.stringify(formattedError));
8174
}
8275

8376
createNetworkTypeObservable(networkType?: NetworkType | Observable<NetworkType>): Observable<NetworkType> {
@@ -86,7 +79,7 @@ export abstract class Http {
8679
} else if (networkType) {
8780
return observableOf(networkType as NetworkType);
8881
} else {
89-
return this.call(new NodeRoutesApi(this.config()).getNodeInfo(), (body) => body.networkIdentifier);
82+
return defer(() => this.call(new NodeRoutesApi(this.config()).getNodeInfo(), (body) => body.networkIdentifier));
9083
}
9184
}
9285

@@ -102,20 +95,18 @@ export abstract class Http {
10295
*/
10396
protected call<D, M>(remoteCall: Promise<D>, mapper: (value: D) => M): Observable<M> {
10497
return observableFrom(
105-
remoteCall.catch((e) => {
106-
if (e instanceof Error) {
107-
return Promise.resolve(e);
108-
}
109-
return Promise.reject(e);
110-
}),
111-
).pipe(
112-
map((body) => {
113-
if (body instanceof Error) {
114-
throw body;
115-
}
116-
return mapper(body);
117-
}),
118-
catchError(Http.errorHandling),
98+
new Promise<M>((resolve, reject) =>
99+
remoteCall.then(
100+
async (a) => {
101+
try {
102+
resolve(mapper(a));
103+
} catch (e) {
104+
reject(await Http.errorHandling(e));
105+
}
106+
},
107+
async (e) => reject(await Http.errorHandling(e)),
108+
),
109+
),
119110
);
120111
}
121112

src/infrastructure/RepositoryFactoryHttp.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ export class RepositoryFactoryHttp implements RepositoryFactory {
9898
this.generationHash = observableOf(configs.generationHash);
9999
this.nodePublicKey = observableOf(configs.nodePublicKey);
100100
} else {
101-
const nodeInfoObservable = this.createNodeRepository().getNodeInfo();
102-
this.generationHash = this.cache(() => nodeInfoObservable.pipe(map((b) => b.networkGenerationHashSeed)));
103-
this.nodePublicKey = this.cache(() => nodeInfoObservable.pipe(map((b) => b.nodePublicKey)));
101+
const nodeInfoObservable = this.cache(() => this.createNodeRepository().getNodeInfo());
102+
this.generationHash = defer(() => nodeInfoObservable.pipe(map((b) => b.networkGenerationHashSeed)));
103+
this.nodePublicKey = defer(() => nodeInfoObservable.pipe(map((b) => b.nodePublicKey)));
104104
}
105105
this.websocketUrl = configs?.websocketUrl ? configs?.websocketUrl : `${url.replace(/\/$/, '')}/ws`;
106106
this.websocketInjected = configs?.websocketInjected;

test/infrastructure/RepositoryFactory.spec.ts

+50-27
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,36 @@
1616
import { expect } from 'chai';
1717
import { of as observableOf, of } from 'rxjs';
1818
import { catchError, map } from 'rxjs/operators';
19-
import { NetworkConfigurationDTO } from 'symbol-openapi-typescript-fetch-client';
19+
import { NetworkConfigurationDTO, NodeRoutesApi } from 'symbol-openapi-typescript-fetch-client';
2020
import { instance, mock, when } from 'ts-mockito';
21-
import { AccountHttp } from '../../src/infrastructure/AccountHttp';
22-
import { BlockHttp } from '../../src/infrastructure/BlockHttp';
23-
import { ChainHttp } from '../../src/infrastructure/ChainHttp';
24-
import { FinalizationHttp } from '../../src/infrastructure/FinalizationHttp';
25-
import { HashLockHttp } from '../../src/infrastructure/HashLockHttp';
26-
import { Listener } from '../../src/infrastructure/Listener';
27-
import { MetadataHttp } from '../../src/infrastructure/MetadataHttp';
28-
import { MosaicHttp } from '../../src/infrastructure/MosaicHttp';
29-
import { MultisigHttp } from '../../src/infrastructure/MultisigHttp';
30-
import { NamespaceHttp } from '../../src/infrastructure/NamespaceHttp';
31-
import { NamespaceRepository } from '../../src/infrastructure/NamespaceRepository';
32-
import { NetworkHttp } from '../../src/infrastructure/NetworkHttp';
33-
import { NetworkRepository } from '../../src/infrastructure/NetworkRepository';
34-
import { NodeHttp } from '../../src/infrastructure/NodeHttp';
35-
import { NodeRepository } from '../../src/infrastructure/NodeRepository';
36-
import { ReceiptHttp } from '../../src/infrastructure/ReceiptHttp';
37-
import { RepositoryFactoryHttp } from '../../src/infrastructure/RepositoryFactoryHttp';
38-
import { RestrictionAccountHttp } from '../../src/infrastructure/RestrictionAccountHttp';
39-
import { RestrictionMosaicHttp } from '../../src/infrastructure/RestrictionMosaicHttp';
40-
import { SecretLockHttp } from '../../src/infrastructure/SecretLockHttp';
41-
import { TransactionGroup } from '../../src/infrastructure/TransactionGroup';
42-
import { TransactionHttp } from '../../src/infrastructure/TransactionHttp';
43-
import { TransactionStatusHttp } from '../../src/infrastructure/TransactionStatusHttp';
44-
import { NetworkCurrencies } from '../../src/model/mosaic/NetworkCurrencies';
45-
import { NetworkType } from '../../src/model/network/NetworkType';
46-
import { NodeInfo } from '../../src/model/node/NodeInfo';
21+
import {
22+
AccountHttp,
23+
BlockHttp,
24+
ChainHttp,
25+
FinalizationHttp,
26+
HashLockHttp,
27+
Listener,
28+
MetadataHttp,
29+
MosaicHttp,
30+
MultisigHttp,
31+
NamespaceHttp,
32+
NamespaceRepository,
33+
NetworkHttp,
34+
NetworkRepository,
35+
NodeHttp,
36+
NodeRepository,
37+
ReceiptHttp,
38+
RepositoryFactoryHttp,
39+
RestrictionAccountHttp,
40+
RestrictionMosaicHttp,
41+
SecretLockHttp,
42+
TransactionGroup,
43+
TransactionHttp,
44+
TransactionStatusHttp,
45+
} from '../../src/infrastructure';
46+
import { NetworkCurrencies } from '../../src/model/mosaic';
47+
import { NetworkType } from '../../src/model/network';
48+
import { NodeInfo } from '../../src/model/node';
4749

4850
describe('RepositoryFactory', () => {
4951
it('Should create repositories', () => {
@@ -70,6 +72,27 @@ describe('RepositoryFactory', () => {
7072
expect(repositoryFactory.createFinalizationRepository()).to.be.not.null;
7173
});
7274

75+
it('Raise error without unhandled-rejections', async () => {
76+
const nodeRoutesApi: NodeRoutesApi = mock();
77+
78+
const fetchResponseMock: Partial<Response> = {
79+
status: 666,
80+
statusText: 'Some status text error',
81+
text: () => Promise.resolve('This is the body'),
82+
};
83+
when(nodeRoutesApi.getNodeHealth()).thenReturn(Promise.reject(fetchResponseMock));
84+
const url = 'https://invalid';
85+
const repositoryFactory = new RepositoryFactoryHttp(url);
86+
try {
87+
const nodeRepository = repositoryFactory.createNodeRepository();
88+
(nodeRepository as any).nodeRoutesApi = instance(nodeRoutesApi);
89+
await nodeRepository.getNodeHealth().toPromise();
90+
expect(true).to.be.false;
91+
} catch (e) {
92+
expect(e.message).eq('{"statusCode":666,"statusMessage":"Some status text error","body":"This is the body"}');
93+
}
94+
});
95+
7396
it('Should get GenerationHash from cache', (done) => {
7497
let counter = 0;
7598
const repositoryMock: NodeRepository = mock();

0 commit comments

Comments
 (0)