@tchain/tcabci-read-js-client 2.4.0 → 2.5.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/README.md +1 -2
- package/client.js +101 -96
- package/client_test.js +97 -40
- package/package.json +6 -5
- package/websocket.js +344 -0
- package/websocketOptions.js +277 -0
- package/websocketOptions_test.js +129 -0
- package/websocket_test.js +539 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
export const HTTPSPort = 443,
|
|
2
|
+
HTTPPort = 80
|
|
3
|
+
|
|
4
|
+
export const DefaultTimeout = 7000,
|
|
5
|
+
LongTimeout = DefaultTimeout * 2
|
|
6
|
+
|
|
7
|
+
export class Options {
|
|
8
|
+
_host
|
|
9
|
+
_port
|
|
10
|
+
_secure
|
|
11
|
+
_timeout
|
|
12
|
+
_longpoll = false
|
|
13
|
+
_protocols = []
|
|
14
|
+
_customWS
|
|
15
|
+
_endpoints = ['ws', 'longpoll']
|
|
16
|
+
|
|
17
|
+
_maxConnectionDelay = 10000
|
|
18
|
+
_minReconnectionDelay = 1000 + Math.random() * 4000
|
|
19
|
+
_reconnectionDelayGrowFactor = 1.3
|
|
20
|
+
_minUptime = 5000
|
|
21
|
+
_maxRetries = 10
|
|
22
|
+
_maxEnqueuedMessages = Infinity
|
|
23
|
+
_startClosed = false
|
|
24
|
+
_debug = !!process.env.DEBUG
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} host
|
|
28
|
+
* @param {?number} timeout
|
|
29
|
+
* @param {?boolean} secure
|
|
30
|
+
* @param {?number} port
|
|
31
|
+
* @param {?boolean} longpoll
|
|
32
|
+
* @constructor
|
|
33
|
+
*/
|
|
34
|
+
constructor(
|
|
35
|
+
host,
|
|
36
|
+
timeout = DefaultTimeout,
|
|
37
|
+
secure = true,
|
|
38
|
+
port = HTTPSPort,
|
|
39
|
+
longpoll = false,
|
|
40
|
+
) {
|
|
41
|
+
this._host = host
|
|
42
|
+
this._port = port
|
|
43
|
+
this._secure = secure
|
|
44
|
+
this._timeout = timeout
|
|
45
|
+
this._longpoll = longpoll
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @return {boolean}
|
|
50
|
+
* @throws {Error}
|
|
51
|
+
*/
|
|
52
|
+
check() {
|
|
53
|
+
if (this._timeout > LongTimeout)
|
|
54
|
+
throw new Error(`timeout less than LongTimeout`)
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
new URL(this.url())
|
|
58
|
+
|
|
59
|
+
return true
|
|
60
|
+
} catch (e) {
|
|
61
|
+
throw e
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @return {boolean}
|
|
67
|
+
*/
|
|
68
|
+
isLongPool() {
|
|
69
|
+
// return this._longpoll
|
|
70
|
+
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {boolean} debug
|
|
76
|
+
* @return {Options}
|
|
77
|
+
*/
|
|
78
|
+
setDebug(debug) {
|
|
79
|
+
this._debug = debug
|
|
80
|
+
|
|
81
|
+
return this
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @return {boolean}
|
|
86
|
+
*/
|
|
87
|
+
debug() {
|
|
88
|
+
return this._debug
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {?string} wsEndpoint
|
|
93
|
+
* @param {?string} longpollEndpoint
|
|
94
|
+
* @throws {Error}
|
|
95
|
+
*/
|
|
96
|
+
setEndpoints(wsEndpoint = 'ws', longpollEndpoint = 'longpool') {
|
|
97
|
+
if (typeof wsEndpoint !== 'string' || typeof longpollEndpoint !== 'string')
|
|
98
|
+
throw new TypeError('invalid endpoints')
|
|
99
|
+
|
|
100
|
+
this._endpoints = [wsEndpoint, longpollEndpoint]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @return {Array<string>}
|
|
105
|
+
*/
|
|
106
|
+
endpoints() {
|
|
107
|
+
return this._endpoints
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {number} delay
|
|
112
|
+
* @return {Options}
|
|
113
|
+
*/
|
|
114
|
+
setMaxConnectionDelay(delay) {
|
|
115
|
+
this._maxConnectionDelay = delay
|
|
116
|
+
|
|
117
|
+
return this
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @return {number}
|
|
122
|
+
*/
|
|
123
|
+
maxConnectionDelay() {
|
|
124
|
+
return this._maxConnectionDelay
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {number} delay
|
|
129
|
+
* @return {Options}
|
|
130
|
+
*/
|
|
131
|
+
setMinReconnectionDelay(delay) {
|
|
132
|
+
this._minReconnectionDelay = delay
|
|
133
|
+
|
|
134
|
+
return this
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @return {number}
|
|
139
|
+
*/
|
|
140
|
+
minReconnectionDelay() {
|
|
141
|
+
return this._minReconnectionDelay
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {number} gw
|
|
146
|
+
* @return {Options}
|
|
147
|
+
*/
|
|
148
|
+
setReconnectionDelayGrowFactor(gw) {
|
|
149
|
+
this._reconnectionDelayGrowFactor = gw
|
|
150
|
+
|
|
151
|
+
return this
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @return {number}
|
|
156
|
+
*/
|
|
157
|
+
reconnectionDelayGrowFactor() {
|
|
158
|
+
return this._reconnectionDelayGrowFactor
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @param {number} ut
|
|
163
|
+
* @return {Options}
|
|
164
|
+
*/
|
|
165
|
+
setMinUptime(ut) {
|
|
166
|
+
this._minUptime = ut
|
|
167
|
+
|
|
168
|
+
return this
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @return {number}
|
|
173
|
+
*/
|
|
174
|
+
minUptime() {
|
|
175
|
+
return this._minUptime
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @param {number} retries
|
|
180
|
+
* @return {Options}
|
|
181
|
+
*/
|
|
182
|
+
setMaxRetries(retries) {
|
|
183
|
+
this._maxRetries = retries
|
|
184
|
+
|
|
185
|
+
return this
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @return {number}
|
|
190
|
+
*/
|
|
191
|
+
maxRetries() {
|
|
192
|
+
return this._maxRetries
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @param {number} em
|
|
197
|
+
* @return {Options}
|
|
198
|
+
*/
|
|
199
|
+
setMaxEnqueuedMessages(em) {
|
|
200
|
+
this._maxEnqueuedMessages = em
|
|
201
|
+
|
|
202
|
+
return this
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @return {number}
|
|
207
|
+
*/
|
|
208
|
+
maxEnqueuedMessages() {
|
|
209
|
+
return this._maxEnqueuedMessages
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param {Array<string>} protocols
|
|
214
|
+
* @return {Options}
|
|
215
|
+
* @throws {TypeError}
|
|
216
|
+
*/
|
|
217
|
+
setProtocols(protocols) {
|
|
218
|
+
if (!Array.isArray(protocols))
|
|
219
|
+
throw new TypeError('protocols must be a Array')
|
|
220
|
+
this._protocols = protocols
|
|
221
|
+
|
|
222
|
+
return this
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @return {Array<string>}
|
|
227
|
+
*/
|
|
228
|
+
protocols() {
|
|
229
|
+
return this._protocols
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @param {any} customWS
|
|
234
|
+
* @return {Options}
|
|
235
|
+
*/
|
|
236
|
+
setCustomWS(customWS) {
|
|
237
|
+
this._customWS = customWS
|
|
238
|
+
|
|
239
|
+
return this
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @return {any}
|
|
244
|
+
*/
|
|
245
|
+
customWS() {
|
|
246
|
+
return this._customWS
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @return {string}
|
|
251
|
+
*/
|
|
252
|
+
url() {
|
|
253
|
+
if (this._host.length > 2 && this._host.slice(0, 2) === 'ws') {
|
|
254
|
+
return `${this._host}${![HTTPPort, HTTPSPort].includes(this._port) ? `:${this._port}` : ''}`
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return `ws${this._secure ? 's' : ''}://${this._host}${![HTTPPort, HTTPSPort].includes(this._port) ? `:${this._port}` : ''}/${!this._longpoll ? this._endpoints[0] : this._endpoints[1]}`
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @return {{WebSocket: ?any, maxReconnectionDelay: number, minReconnectionDelay: number, reconnectionDelayGrowFactor: number, minUptime: number, connectionTimeout: number, maxRetries: number, maxEnqueuedMessages: number, startClosed: boolean, debug: boolean }}
|
|
262
|
+
*/
|
|
263
|
+
make() {
|
|
264
|
+
return {
|
|
265
|
+
...(this._customWS ? { WebSocket: this._customWS } : {}),
|
|
266
|
+
maxReconnectionDelay: this._maxConnectionDelay,
|
|
267
|
+
minReconnectionDelay: this._minReconnectionDelay,
|
|
268
|
+
reconnectionDelayGrowFactor: this._reconnectionDelayGrowFactor,
|
|
269
|
+
minUptime: this._minUptime,
|
|
270
|
+
connectionTimeout: this._timeout,
|
|
271
|
+
maxRetries: this._maxRetries,
|
|
272
|
+
maxEnqueuedMessages: this._maxEnqueuedMessages,
|
|
273
|
+
startClosed: this._startClosed,
|
|
274
|
+
debug: this._debug,
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it } from 'mocha'
|
|
2
|
+
import { expect } from 'chai'
|
|
3
|
+
import { DefaultTimeout, HTTPPort, HTTPSPort, Options } from './websocketOptions.js'
|
|
4
|
+
import WebSocket from 'ws'
|
|
5
|
+
|
|
6
|
+
describe('Options', () => {
|
|
7
|
+
it('HTTPSPort', () => {
|
|
8
|
+
expect(HTTPSPort).to.equal(443)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('HTTPPort', () => {
|
|
12
|
+
expect(HTTPPort).to.equal(80)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('constructor/1', () => {
|
|
16
|
+
const options = new Options('localhost')
|
|
17
|
+
|
|
18
|
+
expect(options).to.be.an.instanceOf(Options)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('check/0 with valid params', () => {
|
|
22
|
+
const options = new Options('localhost')
|
|
23
|
+
|
|
24
|
+
expect(options.check()).to.be.equal(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should error check/0 with invalid params', () => {
|
|
28
|
+
const options = new Options(1)
|
|
29
|
+
|
|
30
|
+
expect(options.check).to.throw(Error)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should error check/0 if exceeded timeout', () => {
|
|
34
|
+
const options = new Options('localhost', 20000)
|
|
35
|
+
|
|
36
|
+
expect(options.check).to.throw(Error)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('isLongPoll/0', () => {
|
|
40
|
+
const options = new Options('localhost')
|
|
41
|
+
|
|
42
|
+
expect(options.isLongPool()).to.be.equal(false)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('setEndpoints/2 with valid params', () => {
|
|
46
|
+
const options = new Options('localhost')
|
|
47
|
+
|
|
48
|
+
expect(() => {
|
|
49
|
+
options.setEndpoints('e1', 'e2')
|
|
50
|
+
}).to.not.throw(Error)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('should error setEndpoints/2 with invalid params', () => {
|
|
54
|
+
const options = new Options('localhost')
|
|
55
|
+
|
|
56
|
+
expect(() => {
|
|
57
|
+
options.setEndpoints(1, false)
|
|
58
|
+
}).to.throw(Error)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('setProtocols/1 with valid params', () => {
|
|
62
|
+
const options = new Options('localhost')
|
|
63
|
+
|
|
64
|
+
expect(options.setProtocols(['soap'])).to.be.eq(options)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should error setProtocols/1 with invalid params', () => {
|
|
68
|
+
const options = new Options('localhost')
|
|
69
|
+
|
|
70
|
+
expect(() => {
|
|
71
|
+
options.setProtocols('invalid')
|
|
72
|
+
}).to.throw(Error)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('protocols/0', () => {
|
|
76
|
+
const options = new Options('localhost')
|
|
77
|
+
|
|
78
|
+
options.setProtocols(['wamp', 'soap'])
|
|
79
|
+
expect(options.protocols()).to.have.deep.members(['wamp', 'soap'])
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('setCustomWS/1 with valid params', () => {
|
|
83
|
+
const options = new Options('localhost')
|
|
84
|
+
|
|
85
|
+
expect(options.setCustomWS(WebSocket)).to.be.eq(options)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('customWS/0', () => {
|
|
89
|
+
const options = new Options('localhost')
|
|
90
|
+
|
|
91
|
+
options.setCustomWS(WebSocket)
|
|
92
|
+
expect(options.customWS()).to.be.eq(WebSocket)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('url/0', () => {
|
|
96
|
+
const options = new Options('localhost.localdomain')
|
|
97
|
+
|
|
98
|
+
expect(options.url()).to.equal('wss://localhost.localdomain/ws')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('url/0 with protocol', () => {
|
|
102
|
+
const options = new Options('ws://localhost.localdomain')
|
|
103
|
+
|
|
104
|
+
expect(options.url()).to.equal('ws://localhost.localdomain')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('url/0 with protocol case two', () => {
|
|
108
|
+
const options = new Options('wss://localhost.localdomain/ws')
|
|
109
|
+
|
|
110
|
+
expect(options.url()).to.equal('wss://localhost.localdomain/ws')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('make/0', () => {
|
|
114
|
+
const options = new Options('localhost.io')
|
|
115
|
+
options.setDebug(true)
|
|
116
|
+
|
|
117
|
+
const opts = options.make()
|
|
118
|
+
|
|
119
|
+
expect(opts.maxReconnectionDelay).to.be.eq(10000)
|
|
120
|
+
expect(opts.minReconnectionDelay).to.be.at.least(1000)
|
|
121
|
+
expect(opts.reconnectionDelayGrowFactor).to.be.eq(1.3)
|
|
122
|
+
expect(opts.minUptime).to.be.eq(5000)
|
|
123
|
+
expect(opts.connectionTimeout).to.be.eq(DefaultTimeout)
|
|
124
|
+
expect(opts.maxRetries).to.be.eq(10)
|
|
125
|
+
expect(opts.maxEnqueuedMessages).to.be.eq(Infinity)
|
|
126
|
+
expect(opts.startClosed).to.be.eq(false)
|
|
127
|
+
expect(opts.debug).to.be.eq(true)
|
|
128
|
+
})
|
|
129
|
+
})
|