@logux/server 0.12.2 → 0.12.4
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 +4 -6
- package/add-sync-map/index.d.ts +32 -32
- package/add-sync-map/index.js +4 -4
- package/base-server/hello.html +1 -1
- package/base-server/index.d.ts +401 -401
- package/base-server/index.js +332 -321
- package/bind-backend-proxy/index.js +77 -77
- package/bind-control-server/index.js +1 -1
- package/context/index.d.ts +36 -36
- package/context/index.js +1 -1
- package/create-http-server/index.js +4 -4
- package/create-reporter/index.js +107 -107
- package/filter-meta/index.d.ts +1 -1
- package/human-formatter/index.js +13 -13
- package/index.d.ts +24 -24
- package/index.js +16 -16
- package/options-loader/index.js +2 -2
- package/options-loader/index.test.js +25 -24
- package/package.json +13 -13
- package/request/index.d.ts +2 -1
- package/request/test.test.js +60 -34
- package/server/index.d.ts +27 -23
- package/server/index.js +56 -56
- package/server-client/index.d.ts +41 -41
- package/server-client/index.js +61 -61
- package/test-client/index.d.ts +50 -50
- package/test-client/index.js +28 -28
- package/test-server/index.d.ts +44 -43
- package/test-server/index.js +20 -20
- package/vite.config.ts +13 -0
package/server/index.js
CHANGED
|
@@ -1,80 +1,60 @@
|
|
|
1
|
+
import glob from 'fast-glob'
|
|
1
2
|
import { join, relative } from 'path'
|
|
2
3
|
import pico from 'picocolors'
|
|
3
|
-
import glob from 'fast-glob'
|
|
4
4
|
|
|
5
|
-
import { createReporter } from '../create-reporter/index.js'
|
|
6
5
|
import { BaseServer } from '../base-server/index.js'
|
|
7
|
-
import {
|
|
6
|
+
import { createReporter } from '../create-reporter/index.js'
|
|
7
|
+
import { loadOptions, number, oneOf } from '../options-loader/index.js'
|
|
8
8
|
|
|
9
9
|
let cliOptionsSpec = {
|
|
10
|
+
envPrefix: 'LOGUX',
|
|
11
|
+
examples: [
|
|
12
|
+
'$0 --port 31337 --host 127.0.0.1',
|
|
13
|
+
'LOGUX_PORT=1337 LOGUX_HOST=127.0.0.1 $0'
|
|
14
|
+
],
|
|
10
15
|
options: {
|
|
16
|
+
backend: {
|
|
17
|
+
description: 'Backend to process actions'
|
|
18
|
+
},
|
|
19
|
+
cert: {
|
|
20
|
+
description: 'Path to SSL certificate'
|
|
21
|
+
},
|
|
22
|
+
controlMask: {
|
|
23
|
+
description: 'CIDR masks of control servers'
|
|
24
|
+
},
|
|
25
|
+
controlSecret: {
|
|
26
|
+
description: 'Secret to control Logux server'
|
|
27
|
+
},
|
|
11
28
|
host: {
|
|
12
29
|
alias: 'h',
|
|
13
30
|
description: 'Host to bind server'
|
|
14
31
|
},
|
|
15
|
-
port: {
|
|
16
|
-
alias: 'p',
|
|
17
|
-
description: 'Port to bind server',
|
|
18
|
-
parse: number
|
|
19
|
-
},
|
|
20
32
|
key: {
|
|
21
33
|
description: 'Path to SSL key'
|
|
22
34
|
},
|
|
23
|
-
cert: {
|
|
24
|
-
description: 'Path to SSL certificate'
|
|
25
|
-
},
|
|
26
|
-
supports: {
|
|
27
|
-
description: 'Range of supported client subprotocols'
|
|
28
|
-
},
|
|
29
|
-
subprotocol: {
|
|
30
|
-
description: 'Server subprotocol'
|
|
31
|
-
},
|
|
32
35
|
logger: {
|
|
33
36
|
alias: 'l',
|
|
34
37
|
description: 'Logger type',
|
|
35
38
|
parse: value => oneOf(['human', 'json'], value)
|
|
36
39
|
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
description: 'Secret to control Logux server'
|
|
42
|
-
},
|
|
43
|
-
controlMask: {
|
|
44
|
-
description: 'CIDR masks of control servers'
|
|
40
|
+
port: {
|
|
41
|
+
alias: 'p',
|
|
42
|
+
description: 'Port to bind server',
|
|
43
|
+
parse: number
|
|
45
44
|
},
|
|
46
45
|
redis: {
|
|
47
46
|
description: 'Redis URL for Logux Server Pro scaling'
|
|
47
|
+
},
|
|
48
|
+
subprotocol: {
|
|
49
|
+
description: 'Server subprotocol'
|
|
50
|
+
},
|
|
51
|
+
supports: {
|
|
52
|
+
description: 'Range of supported client subprotocols'
|
|
48
53
|
}
|
|
49
|
-
}
|
|
50
|
-
envPrefix: 'LOGUX',
|
|
51
|
-
examples: [
|
|
52
|
-
'$0 --port 31337 --host 127.0.0.1',
|
|
53
|
-
'LOGUX_PORT=1337 LOGUX_HOST=127.0.0.1 $0'
|
|
54
|
-
]
|
|
54
|
+
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export class Server extends BaseServer {
|
|
58
|
-
static loadOptions(process, defaults) {
|
|
59
|
-
let [help, options] = loadOptions(
|
|
60
|
-
cliOptionsSpec,
|
|
61
|
-
process,
|
|
62
|
-
defaults.root ? { path: join(defaults.root, '.env') } : undefined
|
|
63
|
-
)
|
|
64
|
-
if (help) {
|
|
65
|
-
process.stdout.write(help + '\n')
|
|
66
|
-
return process.exit(0)
|
|
67
|
-
}
|
|
68
|
-
try {
|
|
69
|
-
return Object.assign(defaults, options)
|
|
70
|
-
} catch (e) {
|
|
71
|
-
process.stderr.write(
|
|
72
|
-
`${pico.bgRed(pico.black(' FATAL '))} ${e.message}\n`
|
|
73
|
-
)
|
|
74
|
-
return process.exit(1)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
58
|
constructor(opts = {}) {
|
|
79
59
|
if (!opts.logger) {
|
|
80
60
|
opts.logger = 'human'
|
|
@@ -122,11 +102,22 @@ export class Server extends BaseServer {
|
|
|
122
102
|
})
|
|
123
103
|
}
|
|
124
104
|
|
|
125
|
-
|
|
105
|
+
static loadOptions(process, defaults) {
|
|
106
|
+
let [help, options] = loadOptions(
|
|
107
|
+
cliOptionsSpec,
|
|
108
|
+
process,
|
|
109
|
+
defaults.root ? { path: join(defaults.root, '.env') } : undefined
|
|
110
|
+
)
|
|
111
|
+
if (help) {
|
|
112
|
+
process.stdout.write(help + '\n')
|
|
113
|
+
return process.exit(0)
|
|
114
|
+
}
|
|
126
115
|
try {
|
|
127
|
-
return
|
|
128
|
-
} catch (
|
|
129
|
-
|
|
116
|
+
return Object.assign(defaults, options)
|
|
117
|
+
} catch (e) {
|
|
118
|
+
process.stderr.write(
|
|
119
|
+
`${pico.bgRed(pico.black(' FATAL '))} ${e.message}\n`
|
|
120
|
+
)
|
|
130
121
|
return process.exit(1)
|
|
131
122
|
}
|
|
132
123
|
}
|
|
@@ -135,8 +126,8 @@ export class Server extends BaseServer {
|
|
|
135
126
|
files = ['modules/*/index.js', 'modules/*.js', '!**/*.{test,spec}.js']
|
|
136
127
|
) {
|
|
137
128
|
let matches = await glob(files, {
|
|
138
|
-
cwd: this.options.root,
|
|
139
129
|
absolute: true,
|
|
130
|
+
cwd: this.options.root,
|
|
140
131
|
onlyFiles: true
|
|
141
132
|
})
|
|
142
133
|
|
|
@@ -158,4 +149,13 @@ export class Server extends BaseServer {
|
|
|
158
149
|
})
|
|
159
150
|
)
|
|
160
151
|
}
|
|
152
|
+
|
|
153
|
+
async listen(...args) {
|
|
154
|
+
try {
|
|
155
|
+
return BaseServer.prototype.listen.apply(this, args)
|
|
156
|
+
} catch (err) {
|
|
157
|
+
this.emitter.emit('report', 'error', { err })
|
|
158
|
+
return process.exit(1)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
161
|
}
|
package/server-client/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ServerConnection, ServerNode } from '@logux/core'
|
|
1
|
+
import type { ServerConnection, ServerNode } from '@logux/core'
|
|
2
2
|
|
|
3
|
-
import { BaseServer } from '../base-server/index.js'
|
|
3
|
+
import type { BaseServer } from '../base-server/index.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Logux client connected to server.
|
|
@@ -10,24 +10,11 @@ import { BaseServer } from '../base-server/index.js'
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
export class ServerClient {
|
|
13
|
-
/**
|
|
14
|
-
* @param app The server.
|
|
15
|
-
* @param connection The Logux connection.
|
|
16
|
-
* @param key Client number used as `app.connected` key.
|
|
17
|
-
*/
|
|
18
|
-
constructor(app: BaseServer, connection: ServerConnection, key: number)
|
|
19
|
-
|
|
20
13
|
/**
|
|
21
14
|
* Server, which received client.
|
|
22
15
|
*/
|
|
23
16
|
app: BaseServer
|
|
24
17
|
|
|
25
|
-
/**
|
|
26
|
-
* User ID. It will be filled from client’s node ID.
|
|
27
|
-
* It will be undefined before correct authentication.
|
|
28
|
-
*/
|
|
29
|
-
userId?: string
|
|
30
|
-
|
|
31
18
|
/**
|
|
32
19
|
* Unique persistence machine ID.
|
|
33
20
|
* It will be undefined before correct authentication.
|
|
@@ -35,28 +22,22 @@ export class ServerClient {
|
|
|
35
22
|
clientId?: string
|
|
36
23
|
|
|
37
24
|
/**
|
|
38
|
-
*
|
|
39
|
-
* It will be undefined before correct authentication.
|
|
40
|
-
*/
|
|
41
|
-
nodeId?: string
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Does server process some action from client.
|
|
25
|
+
* The Logux wrapper to WebSocket connection.
|
|
45
26
|
*
|
|
46
27
|
* ```js
|
|
47
|
-
* console.log(
|
|
28
|
+
* console.log(client.connection.ws.upgradeReq.headers)
|
|
48
29
|
* ```
|
|
49
30
|
*/
|
|
50
|
-
|
|
31
|
+
connection: ServerConnection
|
|
51
32
|
|
|
52
33
|
/**
|
|
53
|
-
*
|
|
34
|
+
* HTTP headers of WS connection.
|
|
54
35
|
*
|
|
55
36
|
* ```js
|
|
56
|
-
*
|
|
37
|
+
* client.httpHeaders['User-Agent']
|
|
57
38
|
* ```
|
|
58
39
|
*/
|
|
59
|
-
|
|
40
|
+
httpHeaders: { [name: string]: string }
|
|
60
41
|
|
|
61
42
|
/**
|
|
62
43
|
* Client number used as `app.connected` key.
|
|
@@ -70,31 +51,55 @@ export class ServerClient {
|
|
|
70
51
|
key: string
|
|
71
52
|
|
|
72
53
|
/**
|
|
73
|
-
*
|
|
54
|
+
* Node instance to synchronize logs.
|
|
74
55
|
*
|
|
75
56
|
* ```js
|
|
76
|
-
*
|
|
57
|
+
* if (client.node.state === 'synchronized')
|
|
77
58
|
* ```
|
|
78
59
|
*/
|
|
79
|
-
|
|
60
|
+
node: ServerNode
|
|
80
61
|
|
|
81
62
|
/**
|
|
82
|
-
*
|
|
63
|
+
* Unique node ID.
|
|
64
|
+
* It will be undefined before correct authentication.
|
|
65
|
+
*/
|
|
66
|
+
nodeId?: string
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Does server process some action from client.
|
|
83
70
|
*
|
|
84
71
|
* ```js
|
|
85
|
-
*
|
|
72
|
+
* console.log('Clients in processing:', clients.map(i => i.processing))
|
|
86
73
|
* ```
|
|
87
74
|
*/
|
|
88
|
-
|
|
75
|
+
processing: boolean
|
|
89
76
|
|
|
90
77
|
/**
|
|
91
|
-
*
|
|
78
|
+
* Client IP address.
|
|
92
79
|
*
|
|
93
80
|
* ```js
|
|
94
|
-
*
|
|
81
|
+
* const clientCity = detectLocation(client.remoteAddress)
|
|
95
82
|
* ```
|
|
96
83
|
*/
|
|
97
|
-
|
|
84
|
+
remoteAddress: string
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* User ID. It will be filled from client’s node ID.
|
|
88
|
+
* It will be undefined before correct authentication.
|
|
89
|
+
*/
|
|
90
|
+
userId?: string
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param app The server.
|
|
94
|
+
* @param connection The Logux connection.
|
|
95
|
+
* @param key Client number used as `app.connected` key.
|
|
96
|
+
*/
|
|
97
|
+
constructor(app: BaseServer, connection: ServerConnection, key: number)
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Disconnect client.
|
|
101
|
+
*/
|
|
102
|
+
destroy(): void
|
|
98
103
|
|
|
99
104
|
/**
|
|
100
105
|
* Check client subprotocol version. It uses `semver` npm package
|
|
@@ -110,9 +115,4 @@ export class ServerClient {
|
|
|
110
115
|
* @returns Is version satisfies requirements.
|
|
111
116
|
*/
|
|
112
117
|
isSubprotocol(range: string): boolean
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Disconnect client.
|
|
116
|
-
*/
|
|
117
|
-
destroy(): void
|
|
118
118
|
}
|
package/server-client/index.js
CHANGED
|
@@ -2,15 +2,15 @@ import { LoguxError, parseId } from '@logux/core'
|
|
|
2
2
|
import cookie from 'cookie'
|
|
3
3
|
import semver from 'semver'
|
|
4
4
|
|
|
5
|
-
import { FilteredNode } from '../filtered-node/index.js'
|
|
6
5
|
import { ALLOWED_META } from '../allowed-meta/index.js'
|
|
7
6
|
import { filterMeta } from '../filter-meta/index.js'
|
|
7
|
+
import { FilteredNode } from '../filtered-node/index.js'
|
|
8
8
|
|
|
9
9
|
function reportDetails(client) {
|
|
10
10
|
return {
|
|
11
11
|
connectionId: client.key,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
nodeId: client.nodeId,
|
|
13
|
+
subprotocol: client.node.remoteSubprotocol
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -32,13 +32,13 @@ export class ServerClient {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
this.node = new FilteredNode(this, app.nodeId, app.log, connection, {
|
|
35
|
-
|
|
35
|
+
auth: this.auth.bind(this),
|
|
36
36
|
inFilter: this.filter.bind(this),
|
|
37
|
-
timeout: app.options.timeout,
|
|
38
|
-
outMap: this.outMap.bind(this),
|
|
39
37
|
inMap: this.inMap.bind(this),
|
|
38
|
+
outMap: this.outMap.bind(this),
|
|
40
39
|
ping: app.options.ping,
|
|
41
|
-
|
|
40
|
+
subprotocol: app.options.subprotocol,
|
|
41
|
+
timeout: app.options.timeout
|
|
42
42
|
})
|
|
43
43
|
if (this.app.env === 'development') {
|
|
44
44
|
this.node.setLocalHeaders({ env: 'development' })
|
|
@@ -61,44 +61,6 @@ export class ServerClient {
|
|
|
61
61
|
this.app.emitter.emit('connected', this)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
isSubprotocol(range) {
|
|
65
|
-
return semver.satisfies(this.node.remoteSubprotocol, range)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
destroy() {
|
|
69
|
-
this.destroyed = true
|
|
70
|
-
this.node.destroy()
|
|
71
|
-
if (this.userId) {
|
|
72
|
-
let users = this.app.userIds.get(this.userId)
|
|
73
|
-
if (users) {
|
|
74
|
-
users = users.filter(i => i !== this)
|
|
75
|
-
if (users.length === 0) {
|
|
76
|
-
this.app.userIds.delete(this.userId)
|
|
77
|
-
} else {
|
|
78
|
-
this.app.userIds.set(this.userId, users)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (this.clientId) {
|
|
83
|
-
this.app.clientIds.delete(this.clientId)
|
|
84
|
-
this.app.nodeIds.delete(this.nodeId)
|
|
85
|
-
|
|
86
|
-
for (let channel in this.app.subscribers) {
|
|
87
|
-
let subscriber = this.app.subscribers[channel][this.nodeId]
|
|
88
|
-
if (subscriber) {
|
|
89
|
-
let action = { type: 'logux/unsubscribe', channel }
|
|
90
|
-
let actionId = this.app.log.generateId()
|
|
91
|
-
let meta = { id: actionId, time: parseInt(actionId), reasons: [] }
|
|
92
|
-
this.app.performUnsubscribe(this.nodeId, action, meta)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (!this.app.destroying) {
|
|
97
|
-
this.app.emitter.emit('disconnected', this)
|
|
98
|
-
}
|
|
99
|
-
this.app.connected.delete(this.key)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
64
|
async auth(nodeId, token) {
|
|
103
65
|
this.nodeId = nodeId
|
|
104
66
|
let { clientId, userId } = parseId(nodeId)
|
|
@@ -129,11 +91,11 @@ export class ServerClient {
|
|
|
129
91
|
let result
|
|
130
92
|
try {
|
|
131
93
|
result = await this.app.authenticator({
|
|
132
|
-
headers: this.node.remoteHeaders,
|
|
133
|
-
cookie: cookie.parse(headers.cookie || ''),
|
|
134
|
-
userId: this.userId,
|
|
135
94
|
client: this,
|
|
136
|
-
|
|
95
|
+
cookie: cookie.parse(headers.cookie || ''),
|
|
96
|
+
headers: this.node.remoteHeaders,
|
|
97
|
+
token,
|
|
98
|
+
userId: this.userId
|
|
137
99
|
})
|
|
138
100
|
} catch (e) {
|
|
139
101
|
if (e.name === 'LoguxError') {
|
|
@@ -177,15 +139,46 @@ export class ServerClient {
|
|
|
177
139
|
return result
|
|
178
140
|
}
|
|
179
141
|
|
|
180
|
-
|
|
181
|
-
|
|
142
|
+
denyBack(action, meta) {
|
|
143
|
+
this.app.emitter.emit('report', 'denied', { actionId: meta.id })
|
|
144
|
+
let [undoAction, undoMeta] = this.app.buildUndo(action, meta, 'denied')
|
|
145
|
+
undoMeta.clients = (undoMeta.clients || []).concat([this.clientId])
|
|
146
|
+
this.app.log.add(undoAction, undoMeta)
|
|
147
|
+
this.app.debugActionError(meta, `Action "${meta.id}" was denied`)
|
|
182
148
|
}
|
|
183
149
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
150
|
+
destroy() {
|
|
151
|
+
this.destroyed = true
|
|
152
|
+
this.node.destroy()
|
|
153
|
+
if (this.userId) {
|
|
154
|
+
let users = this.app.userIds.get(this.userId)
|
|
155
|
+
if (users) {
|
|
156
|
+
users = users.filter(i => i !== this)
|
|
157
|
+
if (users.length === 0) {
|
|
158
|
+
this.app.userIds.delete(this.userId)
|
|
159
|
+
} else {
|
|
160
|
+
this.app.userIds.set(this.userId, users)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
187
163
|
}
|
|
188
|
-
|
|
164
|
+
if (this.clientId) {
|
|
165
|
+
this.app.clientIds.delete(this.clientId)
|
|
166
|
+
this.app.nodeIds.delete(this.nodeId)
|
|
167
|
+
|
|
168
|
+
for (let channel in this.app.subscribers) {
|
|
169
|
+
let subscriber = this.app.subscribers[channel][this.nodeId]
|
|
170
|
+
if (subscriber) {
|
|
171
|
+
let action = { channel, type: 'logux/unsubscribe' }
|
|
172
|
+
let actionId = this.app.log.generateId()
|
|
173
|
+
let meta = { id: actionId, reasons: [], time: parseInt(actionId) }
|
|
174
|
+
this.app.performUnsubscribe(this.nodeId, action, meta)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!this.app.destroying) {
|
|
179
|
+
this.app.emitter.emit('disconnected', this)
|
|
180
|
+
}
|
|
181
|
+
this.app.connected.delete(this.key)
|
|
189
182
|
}
|
|
190
183
|
|
|
191
184
|
async filter(action, meta) {
|
|
@@ -231,11 +224,18 @@ export class ServerClient {
|
|
|
231
224
|
}
|
|
232
225
|
}
|
|
233
226
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
227
|
+
async inMap(action, meta) {
|
|
228
|
+
if (!meta.subprotocol) {
|
|
229
|
+
meta.subprotocol = this.node.remoteSubprotocol
|
|
230
|
+
}
|
|
231
|
+
return [action, meta]
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
isSubprotocol(range) {
|
|
235
|
+
return semver.satisfies(this.node.remoteSubprotocol, range)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async outMap(action, meta) {
|
|
239
|
+
return [action, filterMeta(meta)]
|
|
240
240
|
}
|
|
241
241
|
}
|
package/test-client/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { LoguxSubscribeAction, LoguxUnsubscribeAction } from '@logux/actions'
|
|
2
|
-
import { Action, AnyAction, TestLog, TestPair } from '@logux/core'
|
|
1
|
+
import type { LoguxSubscribeAction, LoguxUnsubscribeAction } from '@logux/actions'
|
|
2
|
+
import type { Action, AnyAction, TestLog, TestPair } from '@logux/core'
|
|
3
3
|
|
|
4
|
-
import { ServerMeta } from '../base-server/index.js'
|
|
5
|
-
import { TestServer } from '../test-server/index.js'
|
|
4
|
+
import type { ServerMeta } from '../base-server/index.js'
|
|
5
|
+
import type { TestServer } from '../test-server/index.js'
|
|
6
6
|
|
|
7
7
|
export class LoguxActionError extends Error {
|
|
8
8
|
action: Action
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface TestClientOptions {
|
|
12
|
+
cookie?: object
|
|
13
|
+
headers?: object
|
|
12
14
|
httpHeaders?: { [key: string]: string }
|
|
13
15
|
subprotocol?: string
|
|
14
|
-
headers?: object
|
|
15
|
-
cookie?: object
|
|
16
16
|
token?: string
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -59,11 +59,14 @@ export interface TestClientOptions {
|
|
|
59
59
|
*/
|
|
60
60
|
export class TestClient {
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
62
|
+
* Client’s ID.
|
|
63
|
+
*
|
|
64
|
+
* ```js
|
|
65
|
+
* let client = new TestClient(server, '10')
|
|
66
|
+
* client.clientId //=> '10:1'
|
|
67
|
+
* ```
|
|
65
68
|
*/
|
|
66
|
-
|
|
69
|
+
clientId: string
|
|
67
70
|
|
|
68
71
|
/**
|
|
69
72
|
* Client’s log with extra methods to check actions inside.
|
|
@@ -85,14 +88,13 @@ export class TestClient {
|
|
|
85
88
|
nodeId: string
|
|
86
89
|
|
|
87
90
|
/**
|
|
88
|
-
*
|
|
91
|
+
* Connection channel between client and server to track sent messages.
|
|
89
92
|
*
|
|
90
93
|
* ```js
|
|
91
|
-
*
|
|
92
|
-
* client.clientId //=> '10:1'
|
|
94
|
+
* console.log(client.pair.leftSent)
|
|
93
95
|
* ```
|
|
94
96
|
*/
|
|
95
|
-
|
|
97
|
+
pair: TestPair
|
|
96
98
|
|
|
97
99
|
/**
|
|
98
100
|
* User ID.
|
|
@@ -105,13 +107,27 @@ export class TestClient {
|
|
|
105
107
|
userId: string
|
|
106
108
|
|
|
107
109
|
/**
|
|
108
|
-
*
|
|
110
|
+
* @param server Test server.
|
|
111
|
+
* @param userId User ID.
|
|
112
|
+
* @param opts Other options.
|
|
113
|
+
*/
|
|
114
|
+
constructor(server: TestServer, userId: string, opts?: TestClientOptions)
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Collect actions added by server and other clients during the `test` call.
|
|
109
118
|
*
|
|
110
119
|
* ```js
|
|
111
|
-
*
|
|
120
|
+
* let answers = await client.collect(async () => {
|
|
121
|
+
* client.log.add({ type: 'pay' })
|
|
122
|
+
* await delay(10)
|
|
123
|
+
* })
|
|
124
|
+
* expect(actions).toEqual([{ type: 'paid' }])
|
|
112
125
|
* ```
|
|
126
|
+
*
|
|
127
|
+
* @param test Function, where do you expect action will be received
|
|
128
|
+
* @returns Promise with all received actions
|
|
113
129
|
*/
|
|
114
|
-
|
|
130
|
+
collect(test: () => Promise<any>): Promise<Action[]>
|
|
115
131
|
|
|
116
132
|
/**
|
|
117
133
|
* Connect to test server.
|
|
@@ -137,22 +153,6 @@ export class TestClient {
|
|
|
137
153
|
*/
|
|
138
154
|
disconnect(): Promise<void>
|
|
139
155
|
|
|
140
|
-
/**
|
|
141
|
-
* Collect actions added by server and other clients during the `test` call.
|
|
142
|
-
*
|
|
143
|
-
* ```js
|
|
144
|
-
* let answers = await client.collect(async () => {
|
|
145
|
-
* client.log.add({ type: 'pay' })
|
|
146
|
-
* await delay(10)
|
|
147
|
-
* })
|
|
148
|
-
* expect(actions).toEqual([{ type: 'paid' }])
|
|
149
|
-
* ```
|
|
150
|
-
*
|
|
151
|
-
* @param test Function, where do you expect action will be received
|
|
152
|
-
* @returns Promise with all received actions
|
|
153
|
-
*/
|
|
154
|
-
collect(test: () => Promise<any>): Promise<Action[]>
|
|
155
|
-
|
|
156
156
|
/**
|
|
157
157
|
* Send action to the sever and collect all response actions.
|
|
158
158
|
*
|
|
@@ -168,6 +168,21 @@ export class TestClient {
|
|
|
168
168
|
*/
|
|
169
169
|
process(action: AnyAction, meta?: Partial<ServerMeta>): Promise<Action[]>
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Collect actions received from server during the `test` call.
|
|
173
|
+
*
|
|
174
|
+
* ```js
|
|
175
|
+
* let answers = await client1.received(async () => {
|
|
176
|
+
* await client2.process({ type: 'resend' })
|
|
177
|
+
* })
|
|
178
|
+
* expect(actions).toEqual([{ type: 'local' }])
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @param test Function, where do you expect action will be received
|
|
182
|
+
* @returns Promise with all received actions
|
|
183
|
+
*/
|
|
184
|
+
received(test: () => any | Promise<any>): Promise<Action[]>
|
|
185
|
+
|
|
171
186
|
/**
|
|
172
187
|
* Subscribe to the channel and collect all actions dunring the subscription.
|
|
173
188
|
*
|
|
@@ -184,7 +199,7 @@ export class TestClient {
|
|
|
184
199
|
* @returns Promise with all actions from the server.
|
|
185
200
|
*/
|
|
186
201
|
subscribe(
|
|
187
|
-
channel:
|
|
202
|
+
channel: LoguxSubscribeAction | string,
|
|
188
203
|
filter?: object,
|
|
189
204
|
since?: { id: string; time: number }
|
|
190
205
|
): Promise<Action[]>
|
|
@@ -201,22 +216,7 @@ export class TestClient {
|
|
|
201
216
|
* @returns Promise until server will remove client from subscribers.
|
|
202
217
|
*/
|
|
203
218
|
unsubscribe(
|
|
204
|
-
channel:
|
|
219
|
+
channel: LoguxUnsubscribeAction | string,
|
|
205
220
|
filter?: object
|
|
206
221
|
): Promise<Action[]>
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Collect actions received from server during the `test` call.
|
|
210
|
-
*
|
|
211
|
-
* ```js
|
|
212
|
-
* let answers = await client1.received(async () => {
|
|
213
|
-
* await client2.process({ type: 'resend' })
|
|
214
|
-
* })
|
|
215
|
-
* expect(actions).toEqual([{ type: 'local' }])
|
|
216
|
-
* ```
|
|
217
|
-
*
|
|
218
|
-
* @param test Function, where do you expect action will be received
|
|
219
|
-
* @returns Promise with all received actions
|
|
220
|
-
*/
|
|
221
|
-
received(test: () => Promise<any> | any): Promise<Action[]>
|
|
222
222
|
}
|