mobility-toolbox-js 2.0.0-beta.36 → 2.0.0-beta.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/api/RealtimeAPI.test.d.ts +2 -0
- package/api/RealtimeAPI.test.d.ts.map +1 -0
- package/api/RealtimeAPI.test.js +67 -0
- package/api/RoutingAPI.d.ts +6 -2
- package/api/RoutingAPI.d.ts.map +1 -1
- package/api/RoutingAPI.test.d.ts +2 -0
- package/api/RoutingAPI.test.d.ts.map +1 -0
- package/api/RoutingAPI.test.js +29 -0
- package/api/StopsAPI.test.d.ts +2 -0
- package/api/StopsAPI.test.d.ts.map +1 -0
- package/api/StopsAPI.test.js +26 -0
- package/common/api/HttpAPI.d.ts +4 -4
- package/common/api/HttpAPI.d.ts.map +1 -1
- package/common/api/HttpAPI.test.d.ts +2 -0
- package/common/api/HttpAPI.test.d.ts.map +1 -0
- package/common/api/HttpAPI.test.js +54 -0
- package/common/api/WebSocketAPI.d.ts +6 -2
- package/common/api/WebSocketAPI.d.ts.map +1 -1
- package/common/api/WebSocketAPI.js +57 -31
- package/common/api/WebSocketAPI.test.d.ts +2 -0
- package/common/api/WebSocketAPI.test.d.ts.map +1 -0
- package/common/api/WebSocketAPI.test.js +380 -0
- package/common/controls/Control.test.d.ts +2 -0
- package/common/controls/Control.test.d.ts.map +1 -0
- package/common/controls/Control.test.js +89 -0
- package/common/layers/Layer.test.d.ts +2 -0
- package/common/layers/Layer.test.d.ts.map +1 -0
- package/common/layers/Layer.test.js +137 -0
- package/common/mixins/UserInteractionsLayerMixin.test.d.ts +2 -0
- package/common/mixins/UserInteractionsLayerMixin.test.d.ts.map +1 -0
- package/common/mixins/UserInteractionsLayerMixin.test.js +214 -0
- package/common/styles/realtimeDefaultStyle.d.ts.map +1 -1
- package/common/styles/realtimeDefaultStyle.js +2 -4
- package/common/styles/realtimeSimpleStyle.js +1 -1
- package/common/utils/createTrackerFilters.test.d.ts +2 -0
- package/common/utils/createTrackerFilters.test.d.ts.map +1 -0
- package/common/utils/createTrackerFilters.test.js +79 -0
- package/common/utils/getMapboxMapCopyrights.test.d.ts +2 -0
- package/common/utils/getMapboxMapCopyrights.test.d.ts.map +1 -0
- package/common/utils/getMapboxMapCopyrights.test.js +40 -0
- package/common/utils/removeDuplicate.test.d.ts +2 -0
- package/common/utils/removeDuplicate.test.d.ts.map +1 -0
- package/common/utils/removeDuplicate.test.js +19 -0
- package/common/utils/timeUtils.test.d.ts +2 -0
- package/common/utils/timeUtils.test.d.ts.map +1 -0
- package/common/utils/timeUtils.test.js +10 -0
- package/common/utils/trackerConfig.test.d.ts +2 -0
- package/common/utils/trackerConfig.test.d.ts.map +1 -0
- package/common/utils/trackerConfig.test.js +23 -0
- package/mapbox/layers/Layer.test.d.ts +2 -0
- package/mapbox/layers/Layer.test.d.ts.map +1 -0
- package/mapbox/layers/Layer.test.js +204 -0
- package/mapbox/layers/RealtimeLayer.test.d.ts +2 -0
- package/mapbox/layers/RealtimeLayer.test.d.ts.map +1 -0
- package/mapbox/layers/RealtimeLayer.test.js +10 -0
- package/mbt.js +4723 -4172
- package/mbt.js.map +3 -3
- package/mbt.min.js +193 -118
- package/mbt.min.js.map +3 -3
- package/ol/controls/CopyrightControl.test.d.ts +2 -0
- package/ol/controls/CopyrightControl.test.d.ts.map +1 -0
- package/ol/controls/CopyrightControl.test.js +177 -0
- package/ol/controls/RoutingControl.test.d.ts +2 -0
- package/ol/controls/RoutingControl.test.d.ts.map +1 -0
- package/ol/controls/RoutingControl.test.js +150 -0
- package/ol/controls/StopFinderControl.test.d.ts +2 -0
- package/ol/controls/StopFinderControl.test.d.ts.map +1 -0
- package/ol/controls/StopFinderControl.test.js +49 -0
- package/ol/layers/Layer.test.d.ts +2 -0
- package/ol/layers/Layer.test.d.ts.map +1 -0
- package/ol/layers/Layer.test.js +196 -0
- package/ol/layers/MapboxLayer.d.ts.map +1 -1
- package/ol/layers/MapboxLayer.js +4 -0
- package/ol/layers/MapboxLayer.test.d.ts +2 -0
- package/ol/layers/MapboxLayer.test.d.ts.map +1 -0
- package/ol/layers/MapboxLayer.test.js +164 -0
- package/ol/layers/MapboxStyleLayer.test.d.ts +2 -0
- package/ol/layers/MapboxStyleLayer.test.d.ts.map +1 -0
- package/ol/layers/MapboxStyleLayer.test.js +232 -0
- package/ol/layers/RealtimeLayer.test.d.ts +2 -0
- package/ol/layers/RealtimeLayer.test.d.ts.map +1 -0
- package/ol/layers/RealtimeLayer.test.js +71 -0
- package/ol/layers/RoutingLayer.test.d.ts +2 -0
- package/ol/layers/RoutingLayer.test.d.ts.map +1 -0
- package/ol/layers/RoutingLayer.test.js +39 -0
- package/ol/layers/VectorLayer.test.d.ts +2 -0
- package/ol/layers/VectorLayer.test.d.ts.map +1 -0
- package/ol/layers/VectorLayer.test.js +87 -0
- package/ol/layers/WMSLayer.test.d.ts +2 -0
- package/ol/layers/WMSLayer.test.d.ts.map +1 -0
- package/ol/layers/WMSLayer.test.js +66 -0
- package/package.json +12 -15
package/README.md
CHANGED
|
@@ -5,19 +5,25 @@ The tools in this library have been inspired by many projects realized for publi
|
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/mobility-toolbox-js)
|
|
7
7
|
[](https://github.com/geops/mobility-toolbox-js/actions?query=workflow%3ABuild)
|
|
8
|
-
|
|
8
|
+

|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Documentation and examples
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
* Search for [stops and stations](https://maps2.trafimage.ch) all over the world.
|
|
14
|
-
* Get [precise geographic courses](https://geops.github.io/geops-routing-demo/) for all modes of transport.
|
|
15
|
-
* Generate beautiful maps for public transport, mobility and logistics
|
|
12
|
+
Visit https://mobility-toolbox-js.vercel.app/
|
|
16
13
|
|
|
17
|
-
##
|
|
14
|
+
## Demos
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
* Display [real-time vehicle positions and prognosis data](http://tracker.geops.ch/) on a map.
|
|
17
|
+
* Search for [stops and stations](https://maps.trafimage.ch) all over the world.
|
|
18
|
+
* Get [precise geographic courses](https://routing-demo.geops.io/) for all modes of transport.
|
|
19
|
+
* Generate beautiful [schematic](https://mobility.portal.geops.io/world.geops.networkplans) or [topographic](https://mobility.portal.geops.io) maps for public transport, mobility and logistics.
|
|
20
20
|
|
|
21
21
|
## Version 1.x.x
|
|
22
22
|
|
|
23
23
|
The master branch is now open for the version 2 development. The version 1 is still available in [1.x.x](https://github.com/geops/mobility-toolbox-js/tree/1.x.x) branch.
|
|
24
|
+
|
|
25
|
+
## Deploy
|
|
26
|
+
|
|
27
|
+
This library website is deployed automatically using [Vercel](https://vercel.com/geops).
|
|
28
|
+
For Vercel we have to add the nextjs and raw-loader modules in the dev dependencies of the main package.json.
|
|
29
|
+
But those 2 librairies are not need to build the library.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RealtimeAPI.test.d.ts","sourceRoot":"","sources":["../../src/api/RealtimeAPI.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { RealtimeAPI, RealtimeModes } from '.';
|
|
2
|
+
describe('RealtimeAPI', () => {
|
|
3
|
+
let api;
|
|
4
|
+
let get;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
get = jest.fn((params, cb) => {
|
|
7
|
+
cb({ content: 'content' });
|
|
8
|
+
});
|
|
9
|
+
api = new RealtimeAPI();
|
|
10
|
+
api.wsApi = {
|
|
11
|
+
get,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
describe('#getFullTrajectory() calls fullTrajectory channel', () => {
|
|
15
|
+
test('without parameters', (done) => {
|
|
16
|
+
api.getFullTrajectory().then(() => {
|
|
17
|
+
expect(get.mock.calls.length).toBe(1);
|
|
18
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
19
|
+
channel: 'full_trajectory',
|
|
20
|
+
});
|
|
21
|
+
done();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
[null, RealtimeModes.TOPOGRAPHIC].forEach((mode) => {
|
|
25
|
+
describe(`using mode ${mode}`, () => {
|
|
26
|
+
test('using id', (done) => {
|
|
27
|
+
api.getFullTrajectory('foo', mode).then(() => {
|
|
28
|
+
expect(get.mock.calls.length).toBe(1);
|
|
29
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
30
|
+
channel: 'full_trajectory_foo',
|
|
31
|
+
});
|
|
32
|
+
done();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
test('using id and generalizationLevel param', (done) => {
|
|
36
|
+
api.getFullTrajectory('foo', mode, 5).then(() => {
|
|
37
|
+
expect(get.mock.calls.length).toBe(1);
|
|
38
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
39
|
+
channel: 'full_trajectory_foo_gen5',
|
|
40
|
+
});
|
|
41
|
+
done();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('using schematic mode ', () => {
|
|
47
|
+
test('using id', (done) => {
|
|
48
|
+
api.getFullTrajectory('foo', RealtimeModes.SCHEMATIC).then(() => {
|
|
49
|
+
expect(get.mock.calls.length).toBe(1);
|
|
50
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
51
|
+
channel: 'full_trajectory_schematic_foo',
|
|
52
|
+
});
|
|
53
|
+
done();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
test("doesn't use generalizationLevel param", (done) => {
|
|
57
|
+
api.getFullTrajectory('foo', RealtimeModes.SCHEMATIC, 10).then(() => {
|
|
58
|
+
expect(get.mock.calls.length).toBe(1);
|
|
59
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
60
|
+
channel: 'full_trajectory_schematic_foo',
|
|
61
|
+
});
|
|
62
|
+
done();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
package/api/RoutingAPI.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import HttpAPI
|
|
1
|
+
import HttpAPI from '../common/api/HttpAPI';
|
|
2
2
|
import { RoutingParameters, RoutingResponse } from '../../types';
|
|
3
|
+
export declare type RoutingAPIOptions = {
|
|
4
|
+
url?: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
};
|
|
3
7
|
/**
|
|
4
8
|
* Access to the [geOps Routing service](https://developer.geops.io/apis/routing).
|
|
5
9
|
*
|
|
@@ -19,7 +23,7 @@ declare class RoutingAPI extends HttpAPI {
|
|
|
19
23
|
* @param {string} [options.url='https://api.geops.io/routing/v1/'] Service url.
|
|
20
24
|
* @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/).
|
|
21
25
|
*/
|
|
22
|
-
constructor(options:
|
|
26
|
+
constructor(options: RoutingAPIOptions);
|
|
23
27
|
/**
|
|
24
28
|
* Route.
|
|
25
29
|
*
|
package/api/RoutingAPI.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutingAPI.d.ts","sourceRoot":"","sources":["../../src/api/RoutingAPI.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"RoutingAPI.d.ts","sourceRoot":"","sources":["../../src/api/RoutingAPI.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,oBAAY,iBAAiB,GAAG;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,cAAM,UAAW,SAAQ,OAAO;IAC9B;;;;;;OAMG;gBACS,OAAO,EAAE,iBAAiB;IAItC;;;;;;OAMG;IACH,KAAK,CACH,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC;CAG5B;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoutingAPI.test.d.ts","sourceRoot":"","sources":["../../src/api/RoutingAPI.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fetch from 'jest-fetch-mock';
|
|
2
|
+
import RoutingAPI from './RoutingAPI';
|
|
3
|
+
let api;
|
|
4
|
+
describe('RoutingAPI', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
global.fetch = fetch;
|
|
7
|
+
fetch.resetMocks();
|
|
8
|
+
api = new RoutingAPI({ apiKey: 'apiKey' });
|
|
9
|
+
});
|
|
10
|
+
describe('#route', () => {
|
|
11
|
+
test('should success', (done) => {
|
|
12
|
+
fetch.mockResponseOnce(JSON.stringify(global.fetchRouteResponse));
|
|
13
|
+
return api
|
|
14
|
+
.route({
|
|
15
|
+
mot: 'bus',
|
|
16
|
+
via: '47.3739194713294,8.538274823394632|47.37595378493421,8.537490375951839',
|
|
17
|
+
})
|
|
18
|
+
.then((featureCollection) => {
|
|
19
|
+
// Correct url
|
|
20
|
+
expect(fetch.mock.calls[0][0]).toEqual('https://api.geops.io/routing/v1/?key=apiKey&mot=bus&via=47.3739194713294%2C8.538274823394632%7C47.37595378493421%2C8.537490375951839');
|
|
21
|
+
// Correct search result (for bus mot)
|
|
22
|
+
expect(featureCollection.features[0].geometry.type).toEqual('LineString');
|
|
23
|
+
expect(featureCollection.features[0].properties.lines).toBeDefined();
|
|
24
|
+
expect(featureCollection.features[0].properties.station_to).toBeDefined();
|
|
25
|
+
done();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StopsAPI.test.d.ts","sourceRoot":"","sources":["../../src/api/StopsAPI.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fetch from 'jest-fetch-mock';
|
|
2
|
+
import StopsAPI from './StopsAPI';
|
|
3
|
+
let api;
|
|
4
|
+
describe('StopsAPI', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
global.fetch = fetch;
|
|
7
|
+
fetch.resetMocks();
|
|
8
|
+
api = new StopsAPI({ apiKey: 'apiKey' });
|
|
9
|
+
});
|
|
10
|
+
describe('#search', () => {
|
|
11
|
+
test('should success', (done) => {
|
|
12
|
+
fetch.mockResponseOnce(JSON.stringify(global.stopsSearchResponse));
|
|
13
|
+
return api
|
|
14
|
+
.search({
|
|
15
|
+
q: 'Bern',
|
|
16
|
+
})
|
|
17
|
+
.then((featureCollection) => {
|
|
18
|
+
// Correct url
|
|
19
|
+
expect(fetch.mock.calls[0][0]).toEqual('https://api.geops.io/stops/v1/?key=apiKey&q=Bern');
|
|
20
|
+
// Correct search result
|
|
21
|
+
expect(featureCollection.features[0].properties.name).toEqual('Bern');
|
|
22
|
+
done();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
});
|
package/common/api/HttpAPI.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import BaseObject from 'ol/Object';
|
|
2
|
-
export declare type
|
|
3
|
-
url
|
|
2
|
+
export declare type HttpAPIOptions = {
|
|
3
|
+
url: string;
|
|
4
4
|
apiKey?: string;
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
@@ -18,9 +18,9 @@ export declare type HttpApiOptions = {
|
|
|
18
18
|
* @classproperty {string} apiKey Api key to access the service.
|
|
19
19
|
*/
|
|
20
20
|
declare class HttpAPI extends BaseObject {
|
|
21
|
-
url
|
|
21
|
+
url: string;
|
|
22
22
|
apiKey?: string;
|
|
23
|
-
constructor(options:
|
|
23
|
+
constructor(options: HttpAPIOptions);
|
|
24
24
|
/**
|
|
25
25
|
* Append the apiKey before sending the request.
|
|
26
26
|
* @ignore
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpAPI.d.ts","sourceRoot":"","sources":["../../../src/common/api/HttpAPI.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,WAAW,CAAC;AAGnC,oBAAY,cAAc,GAAG;IAC3B,GAAG,
|
|
1
|
+
{"version":3,"file":"HttpAPI.d.ts","sourceRoot":"","sources":["../../../src/common/api/HttpAPI.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,WAAW,CAAC;AAGnC,oBAAY,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AACF;;;;;;;;;;;;;GAaG;AACH,cAAM,OAAQ,SAAQ,UAAU;IAC9B,GAAG,EAAE,MAAM,CAAC;IAEZ,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEJ,OAAO,EAAE,cAAc;IASnC;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CAmCvE;AAED,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpAPI.test.d.ts","sourceRoot":"","sources":["../../../src/common/api/HttpAPI.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fetch from 'jest-fetch-mock';
|
|
2
|
+
import API from './HttpAPI';
|
|
3
|
+
let api;
|
|
4
|
+
describe('HttpAPI', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
global.fetch = fetch;
|
|
7
|
+
fetch.resetMocks();
|
|
8
|
+
api = new API({ url: 'https://foo.ch', apiKey: 'apiKey' });
|
|
9
|
+
});
|
|
10
|
+
describe('#fetch', () => {
|
|
11
|
+
test('should success', () => {
|
|
12
|
+
fetch.mockResponseOnce(JSON.stringify({ foo: 'bar' }));
|
|
13
|
+
return api
|
|
14
|
+
.fetch('/path', {
|
|
15
|
+
q: 'Bern',
|
|
16
|
+
fooUndefined: undefined,
|
|
17
|
+
fooNull: null,
|
|
18
|
+
fooEmpty: '',
|
|
19
|
+
})
|
|
20
|
+
.then((response) => {
|
|
21
|
+
// Correct url
|
|
22
|
+
expect(fetch.mock.calls[0][0]).toEqual('https://foo.ch/path?key=apiKey&q=Bern&fooEmpty=');
|
|
23
|
+
// Correct search result
|
|
24
|
+
expect(response).toEqual({ foo: 'bar' });
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('should display error message', () => {
|
|
28
|
+
test('reject error', (done) => {
|
|
29
|
+
fetch.mockRejectOnce(new Error('Fake error message'));
|
|
30
|
+
return api.fetch().catch((err) => {
|
|
31
|
+
expect(err.name).toEqual('Error');
|
|
32
|
+
expect(err.message).toEqual('Fake error message');
|
|
33
|
+
done();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
test('if the response is invalid json', (done) => {
|
|
37
|
+
fetch.mockResponseOnce('invalid json');
|
|
38
|
+
api.fetch().catch((err) => {
|
|
39
|
+
expect(err.name).toEqual('FetchError');
|
|
40
|
+
expect(err.message).toEqual('invalid json response body at reason: Unexpected token i in JSON at position 0');
|
|
41
|
+
done();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
test('if the response contains an error message', (done) => {
|
|
45
|
+
fetch.mockResponseOnce('{"error":"foo2"}');
|
|
46
|
+
api.fetch().catch((err) => {
|
|
47
|
+
expect(err.name).toEqual('Error');
|
|
48
|
+
expect(err.message).toEqual('foo2');
|
|
49
|
+
done();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -42,6 +42,8 @@ declare class WebSocketAPI {
|
|
|
42
42
|
* @private
|
|
43
43
|
*/
|
|
44
44
|
private send;
|
|
45
|
+
addEvents(onMessage: any, onError: any): void;
|
|
46
|
+
removeEvents(onMessage: any, onError: any): void;
|
|
45
47
|
/**
|
|
46
48
|
* Listen to websocket messages.
|
|
47
49
|
*
|
|
@@ -62,13 +64,15 @@ declare class WebSocketAPI {
|
|
|
62
64
|
private unlisten;
|
|
63
65
|
/**
|
|
64
66
|
* Sends a get request to the websocket.
|
|
67
|
+
* The callback is called only once, when the response is received or when the call returns an error.
|
|
65
68
|
*
|
|
66
69
|
* @param {Object} params Parameters for the websocket get request
|
|
67
|
-
* @param {function}
|
|
68
|
-
* @param {function}
|
|
70
|
+
* @param {function} onMessage callback on message event
|
|
71
|
+
* @param {function} onError Callback on error and close event
|
|
69
72
|
* @private
|
|
70
73
|
*/
|
|
71
74
|
private get;
|
|
75
|
+
requests: any[] | undefined;
|
|
72
76
|
/**
|
|
73
77
|
* Subscribe to a given channel.
|
|
74
78
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketAPI.d.ts","sourceRoot":"","sources":["../../../src/common/api/WebSocketAPI.js"],"names":[],"mappings":";AAAA;;;;GAIG;AACH;IAiEE;;;;;;;;;;OAUG;IACH,gCAKC;IA5ED,yBA0DC;IAoBD;;;;;;OAMG;IACH,gBAiBC;IAZC,cAAc;IACd,wCAAmC;IAarC;;;;OAIG;IACH,cAOC;IAFG,kCAAwB;IAI5B;;;;;OAKG;IACH,aAsBC;IAED;;;;;;;;OAQG;IACH,
|
|
1
|
+
{"version":3,"file":"WebSocketAPI.d.ts","sourceRoot":"","sources":["../../../src/common/api/WebSocketAPI.js"],"names":[],"mappings":";AAAA;;;;GAIG;AACH;IAiEE;;;;;;;;;;OAUG;IACH,gCAKC;IA5ED,yBA0DC;IAoBD;;;;;;OAMG;IACH,gBAiBC;IAZC,cAAc;IACd,wCAAmC;IAarC;;;;OAIG;IACH,cAOC;IAFG,kCAAwB;IAI5B;;;;;OAKG;IACH,aAsBC;IAED,8CASC;IAED,iDASC;IAED;;;;;;;;OAQG;IACH,eAgCC;IAED;;;;;;OAMG;IACH,iBAQC;IAED;;;;;;;;OAQG;IACH,YA4CC;IAlBG,4BAAkB;IAoBtB;;;;;;;;OAQG;IACH,kBAqBC;IAED;;;;;OAKG;IACH,oBAwBC;IAfC,mBAEC;IAeH;;OAEG;IACH,uCAYC;CACF"}
|
|
@@ -137,6 +137,24 @@ class WebSocketAPI {
|
|
|
137
137
|
send();
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
addEvents(onMessage, onError) {
|
|
141
|
+
if (this.websocket) {
|
|
142
|
+
this.websocket.addEventListener('message', onMessage);
|
|
143
|
+
if (onError) {
|
|
144
|
+
this.websocket.addEventListener('error', onError);
|
|
145
|
+
this.websocket.addEventListener('close', onError);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
removeEvents(onMessage, onError) {
|
|
150
|
+
if (this.websocket) {
|
|
151
|
+
this.websocket.removeEventListener('message', onMessage);
|
|
152
|
+
if (onError) {
|
|
153
|
+
this.websocket.removeEventListener('error', onError);
|
|
154
|
+
this.websocket.removeEventListener('close', onError);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
140
158
|
/**
|
|
141
159
|
* Listen to websocket messages.
|
|
142
160
|
*
|
|
@@ -148,7 +166,8 @@ class WebSocketAPI {
|
|
|
148
166
|
*/
|
|
149
167
|
listen(params, cb, errorCb) {
|
|
150
168
|
// Remove the previous identical callback
|
|
151
|
-
this.unlisten(params, cb);
|
|
169
|
+
this.unlisten(params, cb, errorCb);
|
|
170
|
+
// We wrap the message callback to be sure we only propagate the message if it is for the right channel.
|
|
152
171
|
const onMessage = (evt) => {
|
|
153
172
|
let data = {};
|
|
154
173
|
try {
|
|
@@ -170,13 +189,7 @@ class WebSocketAPI {
|
|
|
170
189
|
}
|
|
171
190
|
});
|
|
172
191
|
};
|
|
173
|
-
|
|
174
|
-
this.websocket.addEventListener('message', onMessage);
|
|
175
|
-
if (errorCb) {
|
|
176
|
-
this.websocket.addEventListener('error', errorCb);
|
|
177
|
-
this.websocket.addEventListener('close', errorCb);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
192
|
+
this.addEvents(onMessage, errorCb);
|
|
180
193
|
return { onMessageCb: onMessage, onErrorCb: errorCb };
|
|
181
194
|
}
|
|
182
195
|
/**
|
|
@@ -187,33 +200,52 @@ class WebSocketAPI {
|
|
|
187
200
|
* @private
|
|
188
201
|
*/
|
|
189
202
|
unlisten(params, cb) {
|
|
190
|
-
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
this.subscriptions
|
|
203
|
+
[...(this.subscriptions || []), ...(this.requests || [])]
|
|
194
204
|
.filter((s) => s.params.channel === params.channel && (!cb || s.cb === cb))
|
|
195
205
|
.forEach(({ onMessageCb, onErrorCb }) => {
|
|
196
|
-
|
|
197
|
-
this.websocket.removeEventListener('message', onMessageCb);
|
|
198
|
-
if (onErrorCb) {
|
|
199
|
-
this.websocket.removeEventListener('error', onErrorCb);
|
|
200
|
-
this.websocket.removeEventListener('close', onErrorCb);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
206
|
+
this.removeEvents(onMessageCb, onErrorCb);
|
|
203
207
|
});
|
|
204
208
|
}
|
|
205
209
|
/**
|
|
206
210
|
* Sends a get request to the websocket.
|
|
211
|
+
* The callback is called only once, when the response is received or when the call returns an error.
|
|
207
212
|
*
|
|
208
213
|
* @param {Object} params Parameters for the websocket get request
|
|
209
|
-
* @param {function}
|
|
210
|
-
* @param {function}
|
|
214
|
+
* @param {function} onMessage callback on message event
|
|
215
|
+
* @param {function} onError Callback on error and close event
|
|
211
216
|
* @private
|
|
212
217
|
*/
|
|
213
218
|
get(params, cb, errorCb) {
|
|
214
|
-
const
|
|
215
|
-
this.send(
|
|
216
|
-
|
|
219
|
+
const requestString = WebSocketAPI.getRequestString('GET', params);
|
|
220
|
+
this.send(requestString);
|
|
221
|
+
// We wrap the callbacks to make sure they are called only once.
|
|
222
|
+
const once = (callback) => (...args) => {
|
|
223
|
+
callback(...args);
|
|
224
|
+
const index = this.requests.findIndex((request) => requestString === request.requestString && cb === request.cb);
|
|
225
|
+
const { onMessageCb, onErrorCb } = this.requests[index];
|
|
226
|
+
this.removeEvents(onMessageCb, onErrorCb);
|
|
227
|
+
this.requests.splice(index, 1);
|
|
228
|
+
};
|
|
229
|
+
const { onMessageCb, onErrorCb } = this.listen(params, once(cb), once(errorCb));
|
|
230
|
+
// Store requests and callbacks to be able to remove them.
|
|
231
|
+
if (!this.requests) {
|
|
232
|
+
this.requests = [];
|
|
233
|
+
}
|
|
234
|
+
const index = this.requests.findIndex((request) => requestString === request.requestString && cb === request.cb);
|
|
235
|
+
const newReq = {
|
|
236
|
+
params,
|
|
237
|
+
requestString,
|
|
238
|
+
cb,
|
|
239
|
+
errorCb,
|
|
240
|
+
onMessageCb,
|
|
241
|
+
onErrorCb,
|
|
242
|
+
};
|
|
243
|
+
if (index > -1) {
|
|
244
|
+
this.requests[index] = newReq;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
this.requests.push(newReq);
|
|
248
|
+
}
|
|
217
249
|
}
|
|
218
250
|
/**
|
|
219
251
|
* Subscribe to a given channel.
|
|
@@ -252,13 +284,7 @@ class WebSocketAPI {
|
|
|
252
284
|
unsubscribe(source, cb) {
|
|
253
285
|
const toRemove = this.subscriptions.filter((s) => s.params.channel === source && (!cb || s.cb === cb));
|
|
254
286
|
toRemove.forEach(({ onMessageCb, onErrorCb }) => {
|
|
255
|
-
|
|
256
|
-
this.websocket.removeEventListener('message', onMessageCb);
|
|
257
|
-
if (onErrorCb) {
|
|
258
|
-
this.websocket.removeEventListener('error', onErrorCb);
|
|
259
|
-
this.websocket.removeEventListener('close', onErrorCb);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
287
|
+
this.removeEvents(onMessageCb, onErrorCb);
|
|
262
288
|
});
|
|
263
289
|
this.subscriptions = this.subscriptions.filter((s) => s.params.channel !== source || (cb && s.cb !== cb));
|
|
264
290
|
// If there is no more subscriptions to this channel, and the removed subscriptions didn't register quietly,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketAPI.test.d.ts","sourceRoot":"","sources":["../../../src/common/api/WebSocketAPI.test.js"],"names":[],"mappings":""}
|