@ndustrial/contxt-sdk 5.2.6 → 5.4.0
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/CHANGELOG.md +12 -0
- package/esm/bus/channels.js +52 -0
- package/esm/bus/channels.js.map +1 -1
- package/esm/bus/index.js +18 -2
- package/esm/bus/index.js.map +1 -1
- package/esm/bus/webSocketConnection.js +18 -10
- package/esm/bus/webSocketConnection.js.map +1 -1
- package/esm/config/defaults.js +3 -0
- package/esm/config/defaults.js.map +1 -1
- package/esm/config/index.js +2 -0
- package/esm/config/index.js.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/lib/bus/channels.js +52 -0
- package/lib/bus/channels.js.map +1 -1
- package/lib/bus/index.js +19 -2
- package/lib/bus/index.js.map +1 -1
- package/lib/bus/webSocketConnection.js +18 -10
- package/lib/bus/webSocketConnection.js.map +1 -1
- package/lib/config/defaults.js +3 -0
- package/lib/config/defaults.js.map +1 -1
- package/lib/config/index.js +2 -0
- package/lib/config/index.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bus/channels.js +54 -0
- package/src/bus/channels.spec.js +107 -0
- package/src/bus/index.js +19 -2
- package/src/bus/index.spec.js +42 -0
- package/src/bus/webSocketConnection.js +20 -14
- package/src/bus/webSocketConnection.spec.js +45 -0
- package/src/config/defaults.js +3 -0
- package/src/config/index.js +5 -0
- package/src/index.js +1 -1
- package/src/index.spec.js +9 -0
package/src/bus/channels.spec.js
CHANGED
|
@@ -344,4 +344,111 @@ describe('Bus/Channels', function() {
|
|
|
344
344
|
});
|
|
345
345
|
});
|
|
346
346
|
});
|
|
347
|
+
|
|
348
|
+
describe('peek', function() {
|
|
349
|
+
context('the required fields are provided', function() {
|
|
350
|
+
let channelFromServerAfterFormat;
|
|
351
|
+
let channelFromServerBeforeFormat;
|
|
352
|
+
let expectedOrganizationId;
|
|
353
|
+
let expectedServiceId;
|
|
354
|
+
let expectedChannelId;
|
|
355
|
+
let expectedSubscription;
|
|
356
|
+
let promise;
|
|
357
|
+
let request;
|
|
358
|
+
let toCamelCase;
|
|
359
|
+
|
|
360
|
+
beforeEach(function() {
|
|
361
|
+
channelFromServerAfterFormat = fixture.build('channel');
|
|
362
|
+
expectedSubscription = "test";
|
|
363
|
+
expectedChannelId = channelFromServerAfterFormat.id;
|
|
364
|
+
expectedOrganizationId = channelFromServerAfterFormat.organizationId;
|
|
365
|
+
expectedServiceId = channelFromServerAfterFormat.serviceId;
|
|
366
|
+
channelFromServerBeforeFormat = fixture.build(
|
|
367
|
+
'channel',
|
|
368
|
+
channelFromServerAfterFormat,
|
|
369
|
+
{ fromServer: true }
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
request = {
|
|
373
|
+
...baseRequest,
|
|
374
|
+
get: sinon.stub().resolves(channelFromServerBeforeFormat)
|
|
375
|
+
};
|
|
376
|
+
toCamelCase = sinon
|
|
377
|
+
.stub(objectUtils, 'toCamelCase')
|
|
378
|
+
.returns(channelFromServerAfterFormat);
|
|
379
|
+
|
|
380
|
+
const channels = new Channels(baseSdk, request);
|
|
381
|
+
channels._baseUrl = expectedHost;
|
|
382
|
+
|
|
383
|
+
promise = channels.peek(
|
|
384
|
+
expectedOrganizationId,
|
|
385
|
+
expectedServiceId,
|
|
386
|
+
expectedChannelId,
|
|
387
|
+
expectedSubscription
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('gets the channel from the server', function() {
|
|
392
|
+
expect(request.get).to.be.calledWith(
|
|
393
|
+
`${expectedHost}/organizations/${expectedOrganizationId}/services/${expectedServiceId}/channels/${expectedChannelId}/peek/${expectedSubscription}`
|
|
394
|
+
);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('formats the channel object', function() {
|
|
398
|
+
return promise.then(() => {
|
|
399
|
+
expect(toCamelCase).to.be.calledWith(channelFromServerBeforeFormat);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('returns the requested event', function() {
|
|
404
|
+
return expect(promise).to.be.fulfilled.and.to.eventually.deep.equal(
|
|
405
|
+
channelFromServerAfterFormat
|
|
406
|
+
);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
context('the organizationId is not provided', function() {
|
|
411
|
+
it('throws an error', function() {
|
|
412
|
+
const channels = new Channels(baseSdk, baseRequest);
|
|
413
|
+
const promise = channels.peek();
|
|
414
|
+
|
|
415
|
+
return expect(promise).to.be.rejectedWith(
|
|
416
|
+
'An organizationId is required to peek a message bus channel subscription.'
|
|
417
|
+
);
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
context('the serviceId is not provided', function() {
|
|
422
|
+
it('throws an error', function() {
|
|
423
|
+
const channels = new Channels(baseSdk, baseRequest);
|
|
424
|
+
const promise = channels.peek('1');
|
|
425
|
+
|
|
426
|
+
return expect(promise).to.be.rejectedWith(
|
|
427
|
+
'A serviceId is required to peek a message bus channel subscription.'
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
context('the channelId is not provided', function() {
|
|
433
|
+
it('throws an error', function() {
|
|
434
|
+
const channels = new Channels(baseSdk, baseRequest);
|
|
435
|
+
const promise = channels.peek('1', '2');
|
|
436
|
+
|
|
437
|
+
return expect(promise).to.be.rejectedWith(
|
|
438
|
+
'A channelId is required to peek a message bus channel subscription.'
|
|
439
|
+
);
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
context('the subscription is not provided', function() {
|
|
444
|
+
it('throws an error', function() {
|
|
445
|
+
const channels = new Channels(baseSdk, baseRequest);
|
|
446
|
+
const promise = channels.peek('1', '2', '3');
|
|
447
|
+
|
|
448
|
+
return expect(promise).to.be.rejectedWith(
|
|
449
|
+
'A subscription name is required to peek a message bus channel subscription.'
|
|
450
|
+
);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
});
|
|
347
454
|
});
|
package/src/bus/index.js
CHANGED
|
@@ -35,6 +35,20 @@ import WebSocketConnection from './webSocketConnection';
|
|
|
35
35
|
* @property {WebSocket} _webSocket The raw WebSocket connection to the message bus
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Configuration object for the Bus
|
|
40
|
+
*
|
|
41
|
+
* @typedef {Object} BusConfig
|
|
42
|
+
* @property {boolean} autoAcknowledge
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @type {BusConfig}
|
|
47
|
+
*/
|
|
48
|
+
const defaultBusConfig = {
|
|
49
|
+
autoAcknowledge: true
|
|
50
|
+
};
|
|
51
|
+
|
|
38
52
|
/**
|
|
39
53
|
* Module that provides access to the message bus. This is for Node
|
|
40
54
|
* environments. Documentation for browser environments is found under
|
|
@@ -46,8 +60,9 @@ class Bus {
|
|
|
46
60
|
/**
|
|
47
61
|
* @param {Object} sdk An instance of the SDK so the module can communicate with other modules
|
|
48
62
|
* @param {Object} request An instance of the request module tied to this module's audience.
|
|
63
|
+
* @param {BusConfig} config A config object for the Bus instance
|
|
49
64
|
*/
|
|
50
|
-
constructor(sdk, request) {
|
|
65
|
+
constructor(sdk, request, config) {
|
|
51
66
|
const baseUrl = `${sdk.config.audiences.bus.host}`;
|
|
52
67
|
const baseWebSocketUrl = `${sdk.config.audiences.bus.webSocket}`;
|
|
53
68
|
|
|
@@ -56,6 +71,7 @@ class Bus {
|
|
|
56
71
|
this._request = request;
|
|
57
72
|
this._sdk = sdk;
|
|
58
73
|
this._webSockets = {};
|
|
74
|
+
this._config = Object.assign({}, defaultBusConfig, config);
|
|
59
75
|
|
|
60
76
|
this.channels = new Channels(sdk, request, baseUrl);
|
|
61
77
|
}
|
|
@@ -101,7 +117,8 @@ class Bus {
|
|
|
101
117
|
ws.onopen = (event) => {
|
|
102
118
|
this._webSockets[organizationId] = new WebSocketConnection(
|
|
103
119
|
ws,
|
|
104
|
-
organizationId
|
|
120
|
+
organizationId,
|
|
121
|
+
this._config.autoAcknowledge
|
|
105
122
|
);
|
|
106
123
|
|
|
107
124
|
resolve(this._webSockets[organizationId]);
|
package/src/bus/index.spec.js
CHANGED
|
@@ -290,6 +290,48 @@ describe('Bus', function() {
|
|
|
290
290
|
);
|
|
291
291
|
}
|
|
292
292
|
);
|
|
293
|
+
|
|
294
|
+
context('when providing custom config', function() {
|
|
295
|
+
let bus;
|
|
296
|
+
let expectedApiToken;
|
|
297
|
+
let promise;
|
|
298
|
+
let sdk;
|
|
299
|
+
let server;
|
|
300
|
+
let busConfig
|
|
301
|
+
|
|
302
|
+
beforeEach(function() {
|
|
303
|
+
expectedApiToken = faker.internet.password();
|
|
304
|
+
|
|
305
|
+
sdk = {
|
|
306
|
+
...baseSdk,
|
|
307
|
+
auth: {
|
|
308
|
+
...baseSdk.auth,
|
|
309
|
+
getCurrentApiToken: sinon.stub().resolves(expectedApiToken)
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
server = new Server(
|
|
314
|
+
`${expectedHost}/organizations/${expectedOrganization.id}/stream`
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
busConfig = { autoAcknowledge: false };
|
|
318
|
+
bus = new Bus(sdk, baseRequest, busConfig);
|
|
319
|
+
bus._baseWebSocketUrl = expectedHost;
|
|
320
|
+
|
|
321
|
+
promise = bus.connect(expectedOrganization.id);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
afterEach(function() {
|
|
325
|
+
server.stop();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('passes the auto-acknowledge flag to the WebSocketConnection', function() {
|
|
329
|
+
return promise.then((resolvedWebSocket) => {
|
|
330
|
+
expect(resolvedWebSocket._autoAck).to.equal(busConfig.autoAcknowledge);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
});
|
|
293
335
|
});
|
|
294
336
|
|
|
295
337
|
describe('getWebSocketConnection', function() {
|
|
@@ -29,11 +29,13 @@ class WebSocketConnection {
|
|
|
29
29
|
/**
|
|
30
30
|
* @param {WebSocket} webSocket A WebSocket connection to the message bus
|
|
31
31
|
* @param {string} organizationId UUID corresponding with an organization
|
|
32
|
+
* @param {boolean} autoAcknowledge Whether the messages should be ACK'd explicitly or not
|
|
32
33
|
*/
|
|
33
|
-
constructor(webSocket, organizationId) {
|
|
34
|
+
constructor(webSocket, organizationId, autoAcknowledge = true) {
|
|
34
35
|
this._messageHandlers = {};
|
|
35
36
|
this._organizationId = organizationId;
|
|
36
37
|
this._webSocket = webSocket;
|
|
38
|
+
this._autoAck = autoAcknowledge;
|
|
37
39
|
|
|
38
40
|
if (this._webSocket) {
|
|
39
41
|
this._webSocket.onerror = this._onError;
|
|
@@ -282,20 +284,24 @@ class WebSocketConnection {
|
|
|
282
284
|
|
|
283
285
|
if (error) {
|
|
284
286
|
return resolve(errorHandler(error));
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const ack = once(() => {
|
|
291
|
+
return this._acknowledge(result.id);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
return resolve(
|
|
295
|
+
Promise.resolve(handler(result.body, ack)).then((res) => {
|
|
296
|
+
if (this._autoAck) {
|
|
293
297
|
return ack().then(() => res);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return res;
|
|
301
|
+
})
|
|
302
|
+
);
|
|
303
|
+
} catch (throwable) {
|
|
304
|
+
return reject(throwable);
|
|
299
305
|
}
|
|
300
306
|
});
|
|
301
307
|
};
|
|
@@ -1755,6 +1755,51 @@ describe('Bus/WebSocketConnection', function() {
|
|
|
1755
1755
|
});
|
|
1756
1756
|
});
|
|
1757
1757
|
});
|
|
1758
|
+
|
|
1759
|
+
context('and the client does not auto-ack', function() {
|
|
1760
|
+
let errorHandler;
|
|
1761
|
+
|
|
1762
|
+
beforeEach(function() {
|
|
1763
|
+
handler = sinon.stub().returns(null);
|
|
1764
|
+
errorHandler = sinon.stub().returns(null);
|
|
1765
|
+
|
|
1766
|
+
ws = new WebSocketConnection(
|
|
1767
|
+
expectedWebSocket,
|
|
1768
|
+
expectedOrganization.id,
|
|
1769
|
+
false
|
|
1770
|
+
);
|
|
1771
|
+
|
|
1772
|
+
promise = ws.subscribe(
|
|
1773
|
+
serviceId,
|
|
1774
|
+
channel,
|
|
1775
|
+
group,
|
|
1776
|
+
handler,
|
|
1777
|
+
errorHandler
|
|
1778
|
+
);
|
|
1779
|
+
|
|
1780
|
+
jsonRpcId = Object.keys(ws._messageHandlers)[0];
|
|
1781
|
+
|
|
1782
|
+
ws._messageHandlers[jsonRpcId]({
|
|
1783
|
+
result: {
|
|
1784
|
+
subscription
|
|
1785
|
+
}
|
|
1786
|
+
});
|
|
1787
|
+
});
|
|
1788
|
+
|
|
1789
|
+
it('doesn\'t call the ack function', function() {
|
|
1790
|
+
return promise
|
|
1791
|
+
.then(() => {
|
|
1792
|
+
return ws._messageHandlers[subscription]({
|
|
1793
|
+
result: {
|
|
1794
|
+
error: message
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
})
|
|
1798
|
+
.catch(() => {
|
|
1799
|
+
expect(acknowledge).to.not.be.called;
|
|
1800
|
+
});
|
|
1801
|
+
});
|
|
1802
|
+
});
|
|
1758
1803
|
});
|
|
1759
1804
|
|
|
1760
1805
|
context('without a group', function() {
|
package/src/config/defaults.js
CHANGED
package/src/config/index.js
CHANGED
package/src/index.js
CHANGED
|
@@ -78,7 +78,7 @@ class ContxtSdk {
|
|
|
78
78
|
this.config = new Config(config, externalModules);
|
|
79
79
|
|
|
80
80
|
this.auth = this._createAuthSession(sessionType);
|
|
81
|
-
this.bus = new Bus(this, this._createRequest('bus'));
|
|
81
|
+
this.bus = new Bus(this, this._createRequest('bus'), this.config.bus);
|
|
82
82
|
this.coordinator = new Coordinator(
|
|
83
83
|
this,
|
|
84
84
|
this._createRequest('coordinator')
|
package/src/index.spec.js
CHANGED
|
@@ -76,6 +76,15 @@ describe('ContxtSdk', function() {
|
|
|
76
76
|
expect(contxtSdk.bus).to.be.an.instanceof(Bus);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
+
it('passes bus config to the bus constructor', function() {
|
|
80
|
+
contxtSdk = new ContxtSdk({
|
|
81
|
+
config: {...baseConfig, bus: {autoAcknowledge: false}},
|
|
82
|
+
externalModules: expectedExternalModules,
|
|
83
|
+
sessionType: expectedAuthSessionType
|
|
84
|
+
});
|
|
85
|
+
expect(contxtSdk.bus._config).to.deep.equal({autoAcknowledge: false});
|
|
86
|
+
});
|
|
87
|
+
|
|
79
88
|
it('sets an instance of Config', function() {
|
|
80
89
|
expect(contxtSdk.config).to.be.an.instanceof(Config);
|
|
81
90
|
});
|