@logux/server 0.13.0 → 0.14.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 +3 -23
- package/add-http-pages/index.js +24 -0
- package/base-server/index.d.ts +95 -97
- package/base-server/index.js +78 -70
- package/context/index.d.ts +43 -66
- package/context/index.js +18 -16
- package/create-reporter/index.js +55 -76
- package/human-formatter/index.js +52 -82
- package/index.js +1 -9
- package/options-loader/index.js +46 -14
- package/options-loader/index.test.js +3 -3
- package/options-loader/test.env +2 -0
- package/package.json +11 -21
- package/request/index.d.ts +1 -99
- package/request/index.js +2 -40
- package/server/index.d.ts +24 -37
- package/server/index.js +11 -16
- package/server-client/index.d.ts +0 -15
- package/server-client/index.js +21 -9
- package/test-client/index.d.ts +19 -5
- package/test-client/index.js +2 -2
- package/test-server/index.d.ts +20 -10
- package/test-server/index.js +21 -2
- package/bind-backend-proxy/index.js +0 -325
- package/bind-control-server/index.js +0 -136
- package/request/test.test.js +0 -134
- /package/{base-server → add-http-pages}/hello.html +0 -0
package/base-server/index.js
CHANGED
|
@@ -2,14 +2,13 @@ import { LoguxNotFoundError } from '@logux/actions'
|
|
|
2
2
|
import { Log, MemoryStore, parseId, ServerConnection } from '@logux/core'
|
|
3
3
|
import { createNanoEvents } from 'nanoevents'
|
|
4
4
|
import { nanoid } from 'nanoid'
|
|
5
|
-
import {
|
|
5
|
+
import { readFile } from 'node:fs/promises'
|
|
6
6
|
import { dirname, join } from 'node:path'
|
|
7
7
|
import { fileURLToPath } from 'node:url'
|
|
8
8
|
import UrlPattern from 'url-pattern'
|
|
9
9
|
import { WebSocketServer } from 'ws'
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { bindControlServer } from '../bind-control-server/index.js'
|
|
11
|
+
import { addHttpPages } from '../add-http-pages/index.js'
|
|
13
12
|
import { Context } from '../context/index.js'
|
|
14
13
|
import { createHttpServer } from '../create-http-server/index.js'
|
|
15
14
|
import { ServerClient } from '../server-client/index.js'
|
|
@@ -24,17 +23,6 @@ function optionError(msg) {
|
|
|
24
23
|
throw error
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
let helloCache
|
|
28
|
-
async function readHello() {
|
|
29
|
-
if (!helloCache) {
|
|
30
|
-
let hello = await fs.readFile(
|
|
31
|
-
join(fileURLToPath(import.meta.url), '..', 'hello.html')
|
|
32
|
-
)
|
|
33
|
-
helloCache = hello.toString()
|
|
34
|
-
}
|
|
35
|
-
return helloCache
|
|
36
|
-
}
|
|
37
|
-
|
|
38
26
|
export async function wasNot403(cb) {
|
|
39
27
|
try {
|
|
40
28
|
await cb()
|
|
@@ -103,17 +91,11 @@ export class BaseServer {
|
|
|
103
91
|
this.options = opts
|
|
104
92
|
this.env = this.options.env || process.env.NODE_ENV || 'development'
|
|
105
93
|
|
|
106
|
-
if (
|
|
107
|
-
typeof this.options.subprotocol === 'undefined' &&
|
|
108
|
-
typeof this.options.backend === 'undefined'
|
|
109
|
-
) {
|
|
94
|
+
if (typeof this.options.subprotocol === 'undefined') {
|
|
110
95
|
throw optionError('Missed `subprotocol` option in server constructor')
|
|
111
96
|
}
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
typeof this.options.backend === 'undefined'
|
|
115
|
-
) {
|
|
116
|
-
throw optionError('Missed `supports` option in server constructor')
|
|
97
|
+
if (typeof this.options.minSubprotocol === 'undefined') {
|
|
98
|
+
throw optionError('Missed `minSubprotocol` option in server constructor')
|
|
117
99
|
}
|
|
118
100
|
|
|
119
101
|
if (this.options.key && !this.options.cert) {
|
|
@@ -135,7 +117,9 @@ export class BaseServer {
|
|
|
135
117
|
}
|
|
136
118
|
|
|
137
119
|
this.options.root = this.options.root || process.cwd()
|
|
138
|
-
|
|
120
|
+
if (typeof this.options.port === 'string') {
|
|
121
|
+
this.options.port = parseInt(this.options.port, 10)
|
|
122
|
+
}
|
|
139
123
|
|
|
140
124
|
let store = this.options.store || new MemoryStore()
|
|
141
125
|
|
|
@@ -167,7 +151,6 @@ export class BaseServer {
|
|
|
167
151
|
}
|
|
168
152
|
if (
|
|
169
153
|
!isLogux &&
|
|
170
|
-
!this.options.backend &&
|
|
171
154
|
!this.types[action.type] &&
|
|
172
155
|
!this.getRegexProcessor(action.type)
|
|
173
156
|
) {
|
|
@@ -339,27 +322,11 @@ export class BaseServer {
|
|
|
339
322
|
this.queues = new Map()
|
|
340
323
|
this.actionToQueue = new Map()
|
|
341
324
|
|
|
342
|
-
this.
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return {
|
|
346
|
-
body: await readHello(),
|
|
347
|
-
headers: { 'Content-Type': 'text/html' }
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
safe: true
|
|
351
|
-
},
|
|
352
|
-
'GET /health': {
|
|
353
|
-
request: () => ({
|
|
354
|
-
body: 'Logux Server: OK\n',
|
|
355
|
-
headers: { 'Content-Type': 'text/plain' }
|
|
356
|
-
}),
|
|
357
|
-
safe: true
|
|
358
|
-
}
|
|
359
|
-
}
|
|
325
|
+
this.httpListeners = {}
|
|
326
|
+
this.httpAllListeners = []
|
|
327
|
+
addHttpPages(this)
|
|
360
328
|
|
|
361
329
|
this.listenNotes = {}
|
|
362
|
-
bindBackendProxy(this)
|
|
363
330
|
|
|
364
331
|
let end = (actionId, queue, queueKey, ...args) => {
|
|
365
332
|
this.actionToQueue.delete(actionId)
|
|
@@ -555,13 +522,17 @@ export class BaseServer {
|
|
|
555
522
|
return undefined
|
|
556
523
|
}
|
|
557
524
|
|
|
558
|
-
http(listener) {
|
|
525
|
+
http(method, url, listener) {
|
|
559
526
|
if (this.options.disableHttpServer) {
|
|
560
527
|
throw new Error(
|
|
561
528
|
'`server.http()` can not be called when `disableHttpServer` enabled'
|
|
562
529
|
)
|
|
563
530
|
}
|
|
564
|
-
|
|
531
|
+
if (!url) {
|
|
532
|
+
this.httpAllListeners.push(method)
|
|
533
|
+
} else {
|
|
534
|
+
this.httpListeners[`${method} ${url}`] = listener
|
|
535
|
+
}
|
|
565
536
|
}
|
|
566
537
|
|
|
567
538
|
internalUnknownType(action, meta) {
|
|
@@ -618,29 +589,39 @@ export class BaseServer {
|
|
|
618
589
|
this.httpServer.listen(this.options.port, this.options.host, resolve)
|
|
619
590
|
})
|
|
620
591
|
}
|
|
621
|
-
bindControlServer(this, this.httpListener)
|
|
622
592
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
593
|
+
let processing = 0
|
|
594
|
+
let waiting
|
|
595
|
+
this.unbind.push(() => {
|
|
596
|
+
return new Promise(resolve => {
|
|
597
|
+
let end = () => {
|
|
598
|
+
this.ws.close(resolve)
|
|
599
|
+
this.httpServer.close()
|
|
600
|
+
}
|
|
601
|
+
if (processing === 0) {
|
|
602
|
+
end()
|
|
603
|
+
} else {
|
|
604
|
+
waiting = end
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
})
|
|
608
|
+
|
|
609
|
+
if (!this.options.disableHttpServer) {
|
|
610
|
+
this.httpServer.on('request', async (req, res) => {
|
|
611
|
+
if (this.destroying) {
|
|
612
|
+
res.writeHead(503, { 'Content-Type': 'text/plain' })
|
|
613
|
+
res.end('The server is shutting down\n')
|
|
614
|
+
return
|
|
615
|
+
}
|
|
616
|
+
processing += 1
|
|
617
|
+
await this.processHttp(req, res)
|
|
618
|
+
processing -= 1
|
|
619
|
+
if (processing === 0 && waiting) waiting()
|
|
620
|
+
})
|
|
638
621
|
}
|
|
639
622
|
|
|
640
623
|
let pkg = JSON.parse(
|
|
641
|
-
await
|
|
642
|
-
join(fileURLToPath(import.meta.url), '..', '..', 'package.json')
|
|
643
|
-
)
|
|
624
|
+
await readFile(join(import.meta.dirname, '..', 'package.json'))
|
|
644
625
|
)
|
|
645
626
|
|
|
646
627
|
this.ws.on('connection', (ws, req) => {
|
|
@@ -648,20 +629,17 @@ export class BaseServer {
|
|
|
648
629
|
this.addClient(new ServerConnection(ws))
|
|
649
630
|
})
|
|
650
631
|
this.emitter.emit('report', 'listen', {
|
|
651
|
-
backend: this.options.backend,
|
|
652
632
|
cert: !!this.options.cert,
|
|
653
|
-
controlMask: this.options.controlMask,
|
|
654
|
-
controlSecret: this.options.controlSecret,
|
|
655
633
|
environment: this.env,
|
|
656
634
|
host: this.options.host,
|
|
657
635
|
loguxServer: pkg.version,
|
|
636
|
+
minSubprotocol: this.options.minSubprotocol,
|
|
658
637
|
nodeId: this.nodeId,
|
|
659
638
|
notes: this.listenNotes,
|
|
660
639
|
port: this.options.port,
|
|
661
640
|
redis: this.options.redis,
|
|
662
641
|
server: !!this.options.server,
|
|
663
|
-
subprotocol: this.options.subprotocol
|
|
664
|
-
supports: this.options.supports
|
|
642
|
+
subprotocol: this.options.subprotocol
|
|
665
643
|
})
|
|
666
644
|
}
|
|
667
645
|
|
|
@@ -772,6 +750,32 @@ export class BaseServer {
|
|
|
772
750
|
this.emitter.emit('processed', action, meta, latency)
|
|
773
751
|
}
|
|
774
752
|
|
|
753
|
+
async processHttp(req, res) {
|
|
754
|
+
let urlString = req.url
|
|
755
|
+
if (/^\/\w+%3F/.test(urlString)) {
|
|
756
|
+
urlString = decodeURIComponent(urlString)
|
|
757
|
+
}
|
|
758
|
+
let reqUrl = new URL(urlString, 'http://localhost')
|
|
759
|
+
let rule = this.httpListeners[req.method + ' ' + reqUrl.pathname]
|
|
760
|
+
|
|
761
|
+
if (!rule) {
|
|
762
|
+
let processed = false
|
|
763
|
+
for (let listener of this.httpAllListeners) {
|
|
764
|
+
let result = await listener(req, res)
|
|
765
|
+
if (result === true) {
|
|
766
|
+
processed = true
|
|
767
|
+
break
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (!processed) {
|
|
771
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' })
|
|
772
|
+
res.end('Not found\n')
|
|
773
|
+
}
|
|
774
|
+
} else {
|
|
775
|
+
await rule(req, res)
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
775
779
|
rememberBadAuth(ip) {
|
|
776
780
|
this.authAttempts[ip] = (this.authAttempts[ip] || 0) + 1
|
|
777
781
|
this.setTimeout(() => {
|
|
@@ -869,6 +873,10 @@ export class BaseServer {
|
|
|
869
873
|
}
|
|
870
874
|
}
|
|
871
875
|
|
|
876
|
+
sendOnConnect(loader) {
|
|
877
|
+
this.connectLoader = loader
|
|
878
|
+
}
|
|
879
|
+
|
|
872
880
|
setTimeout(callback, ms) {
|
|
873
881
|
this.lastTimeout += 1
|
|
874
882
|
let id = this.lastTimeout
|
package/context/index.d.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import type { AnyAction } from '@logux/core'
|
|
2
2
|
|
|
3
3
|
import type { ServerMeta } from '../base-server/index.js'
|
|
4
|
+
import type { ServerClient } from '../server-client/index.js'
|
|
4
5
|
import type { Server } from '../server/index.js'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
* Action context.
|
|
8
|
-
*
|
|
9
|
-
* ```js
|
|
10
|
-
* server.type('FOO', {
|
|
11
|
-
* access (ctx, action, meta) {
|
|
12
|
-
* return ctx.isSubprotocol('3.x') ? check3(action) : check4(action)
|
|
13
|
-
* }
|
|
14
|
-
* })
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
7
|
+
export class ConnectContext<Headers extends object = unknown> {
|
|
18
8
|
/**
|
|
19
9
|
* Unique persistence client ID.
|
|
20
10
|
*
|
|
@@ -24,23 +14,6 @@ export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
|
24
14
|
*/
|
|
25
15
|
clientId: string
|
|
26
16
|
|
|
27
|
-
/**
|
|
28
|
-
* Open structure to save some data between different steps of processing.
|
|
29
|
-
*
|
|
30
|
-
* ```js
|
|
31
|
-
* server.type('RENAME', {
|
|
32
|
-
* access (ctx, action, meta) {
|
|
33
|
-
* ctx.data.user = findUser(ctx.userId)
|
|
34
|
-
* return ctx.data.user.hasAccess(action.projectId)
|
|
35
|
-
* }
|
|
36
|
-
* process (ctx, action, meta) {
|
|
37
|
-
* return ctx.data.user.rename(action.projectId, action.name)
|
|
38
|
-
* }
|
|
39
|
-
* })
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
data: Data
|
|
43
|
-
|
|
44
17
|
/**
|
|
45
18
|
* Client’s headers.
|
|
46
19
|
*
|
|
@@ -53,15 +26,6 @@ export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
|
53
26
|
*/
|
|
54
27
|
headers: Headers
|
|
55
28
|
|
|
56
|
-
/**
|
|
57
|
-
* Was action created by Logux server.
|
|
58
|
-
*
|
|
59
|
-
* ```js
|
|
60
|
-
* access: (ctx, action, meta) => ctx.isServer
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
isServer: boolean
|
|
64
|
-
|
|
65
29
|
/**
|
|
66
30
|
* Unique node ID.
|
|
67
31
|
*
|
|
@@ -77,10 +41,9 @@ export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
|
77
41
|
server: Server
|
|
78
42
|
|
|
79
43
|
/**
|
|
80
|
-
* Action creator application subprotocol version
|
|
81
|
-
* Use {@link Context#isSubprotocol} to check it.
|
|
44
|
+
* Action creator application subprotocol version.
|
|
82
45
|
*/
|
|
83
|
-
subprotocol:
|
|
46
|
+
subprotocol: number
|
|
84
47
|
|
|
85
48
|
/**
|
|
86
49
|
* User ID taken node ID.
|
|
@@ -92,32 +55,9 @@ export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
|
92
55
|
* }
|
|
93
56
|
* ```
|
|
94
57
|
*/
|
|
95
|
-
userId:
|
|
58
|
+
userId: string
|
|
96
59
|
|
|
97
|
-
|
|
98
|
-
* @param nodeId Unique node ID.
|
|
99
|
-
* @param clientId Unique persistence client ID.
|
|
100
|
-
* @param userId User ID taken node ID.
|
|
101
|
-
* @param subprotocol Action creator application subprotocol version
|
|
102
|
-
* in SemVer format.
|
|
103
|
-
* @param server Logux server
|
|
104
|
-
*/
|
|
105
|
-
constructor(server: Server, meta: ServerMeta)
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Check creator subprotocol version. It uses `semver` npm package
|
|
109
|
-
* to parse requirements.
|
|
110
|
-
*
|
|
111
|
-
* ```js
|
|
112
|
-
* if (ctx.isSubprotocol('2.x')) {
|
|
113
|
-
* useOldAPI()
|
|
114
|
-
* }
|
|
115
|
-
* ```
|
|
116
|
-
*
|
|
117
|
-
* @param range npm’s version requirements.
|
|
118
|
-
* @returns Is version satisfies requirements.
|
|
119
|
-
*/
|
|
120
|
-
isSubprotocol(range: string): boolean
|
|
60
|
+
constructor(server: Server, client: ServerClient)
|
|
121
61
|
|
|
122
62
|
/**
|
|
123
63
|
* Send action back to the client.
|
|
@@ -135,6 +75,43 @@ export class Context<Data extends object = {}, Headers extends object = {}> {
|
|
|
135
75
|
sendBack(action: AnyAction, meta?: Partial<ServerMeta>): Promise<void>
|
|
136
76
|
}
|
|
137
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Action context.
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export class Context<
|
|
83
|
+
Data extends object = unknown,
|
|
84
|
+
Headers extends object = unknown
|
|
85
|
+
> extends ConnectContext<Headers> {
|
|
86
|
+
/**
|
|
87
|
+
* Open structure to save some data between different steps of processing.
|
|
88
|
+
*
|
|
89
|
+
* ```js
|
|
90
|
+
* server.type('RENAME', {
|
|
91
|
+
* access (ctx, action, meta) {
|
|
92
|
+
* ctx.data.user = findUser(ctx.userId)
|
|
93
|
+
* return ctx.data.user.hasAccess(action.projectId)
|
|
94
|
+
* }
|
|
95
|
+
* process (ctx, action, meta) {
|
|
96
|
+
* return ctx.data.user.rename(action.projectId, action.name)
|
|
97
|
+
* }
|
|
98
|
+
* })
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
data: Data
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Was action created by Logux server.
|
|
105
|
+
*
|
|
106
|
+
* ```js
|
|
107
|
+
* access: (ctx, action, meta) => ctx.isServer
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
isServer: boolean
|
|
111
|
+
|
|
112
|
+
constructor(server: Server, meta: ServerMeta)
|
|
113
|
+
}
|
|
114
|
+
|
|
138
115
|
/**
|
|
139
116
|
* Subscription context.
|
|
140
117
|
*
|
package/context/index.js
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import { parseId } from '@logux/core'
|
|
2
|
-
import semver from 'semver'
|
|
3
2
|
|
|
4
3
|
export class Context {
|
|
5
4
|
constructor(server, meta) {
|
|
6
5
|
this.server = server
|
|
7
6
|
this.data = {}
|
|
8
7
|
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let client = server.clientIds.get(this.clientId)
|
|
16
|
-
|
|
17
|
-
if (meta.subprotocol) {
|
|
18
|
-
this.subprotocol = meta.subprotocol
|
|
19
|
-
} else if (client) {
|
|
8
|
+
let client
|
|
9
|
+
if (meta.node) {
|
|
10
|
+
client = meta
|
|
11
|
+
this.nodeId = client.nodeId
|
|
12
|
+
this.userId = client.userId
|
|
13
|
+
this.clientId = client.clientId
|
|
20
14
|
this.subprotocol = client.node.remoteSubprotocol
|
|
15
|
+
} else {
|
|
16
|
+
let parsed = parseId(meta.id)
|
|
17
|
+
this.nodeId = parsed.nodeId
|
|
18
|
+
this.userId = parsed.userId
|
|
19
|
+
this.clientId = parsed.clientId
|
|
20
|
+
this.isServer = this.userId === 'server'
|
|
21
|
+
client = server.clientIds.get(this.clientId)
|
|
22
|
+
if (meta.subprotocol) {
|
|
23
|
+
this.subprotocol = meta.subprotocol
|
|
24
|
+
} else if (client) {
|
|
25
|
+
this.subprotocol = client.node.remoteSubprotocol
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
if (client) {
|
|
@@ -27,10 +33,6 @@ export class Context {
|
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
isSubprotocol(range) {
|
|
31
|
-
return semver.satisfies(this.subprotocol, range)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
36
|
sendBack(action, meta = {}) {
|
|
35
37
|
return this.server.log.add(action, {
|
|
36
38
|
clients: [this.clientId],
|
package/create-reporter/index.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import os from 'node:os'
|
|
2
|
-
import {
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
|
-
import pico from 'picocolors'
|
|
5
|
-
import pino from 'pino'
|
|
2
|
+
import { sep } from 'node:path'
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
export const PATH_TO_PRETTIFYING_PINO_TRANSPORT = join(
|
|
9
|
-
__dirname,
|
|
10
|
-
'../human-formatter/index.js'
|
|
11
|
-
)
|
|
4
|
+
import humanFormatter from '../human-formatter/index.js'
|
|
12
5
|
|
|
13
6
|
const ERROR_CODES = {
|
|
14
7
|
EACCES: (e, environment) => {
|
|
@@ -27,13 +20,14 @@ const ERROR_CODES = {
|
|
|
27
20
|
}
|
|
28
21
|
},
|
|
29
22
|
EADDRINUSE: e => {
|
|
23
|
+
let port = String(e.port)
|
|
30
24
|
let wayToFix = {
|
|
31
25
|
darwin: `$ sudo lsof -i ${e.port}\n` + '$ sudo kill -9 `<processid>`',
|
|
32
26
|
linux:
|
|
33
27
|
'$ su - root\n' +
|
|
34
28
|
`# netstat -nlp | grep ${e.port}\n` +
|
|
35
29
|
'Proto Local Address State PID/Program name\n' +
|
|
36
|
-
`tcp 0.0.0.0:${
|
|
30
|
+
`tcp 0.0.0.0:${port.padEnd(8)}LISTEN \`777\`/node\n` +
|
|
37
31
|
'# sudo kill -9 `777`',
|
|
38
32
|
win32:
|
|
39
33
|
'Run `cmd.exe` as an administrator\n' +
|
|
@@ -49,13 +43,7 @@ const ERROR_CODES = {
|
|
|
49
43
|
'or previous version of this server was not killed.\n\n' +
|
|
50
44
|
(wayToFix[os.platform()] || '')
|
|
51
45
|
}
|
|
52
|
-
}
|
|
53
|
-
LOGUX_NO_CONTROL_SECRET: e => ({
|
|
54
|
-
msg: e.message,
|
|
55
|
-
note:
|
|
56
|
-
'Call `npx nanoid` and set result as `controlSecret` ' +
|
|
57
|
-
'or `LOGUX_CONTROL_SECRET` environment variable'
|
|
58
|
-
})
|
|
46
|
+
}
|
|
59
47
|
}
|
|
60
48
|
|
|
61
49
|
const REPORTERS = {
|
|
@@ -134,9 +122,9 @@ const REPORTERS = {
|
|
|
134
122
|
let details = {
|
|
135
123
|
environment: r.environment,
|
|
136
124
|
loguxServer: r.loguxServer,
|
|
125
|
+
minSubprotocol: r.minSubprotocol,
|
|
137
126
|
nodeId: r.nodeId,
|
|
138
|
-
subprotocol: r.subprotocol
|
|
139
|
-
supports: r.supports
|
|
127
|
+
subprotocol: r.subprotocol
|
|
140
128
|
}
|
|
141
129
|
|
|
142
130
|
if (r.environment === 'development') {
|
|
@@ -155,15 +143,6 @@ const REPORTERS = {
|
|
|
155
143
|
details.healthCheck = `${httpProtocol}${r.host}:${r.port}/health`
|
|
156
144
|
}
|
|
157
145
|
|
|
158
|
-
if (r.controlSecret) {
|
|
159
|
-
details.controlListen = `http://${r.host}:${r.port}/`
|
|
160
|
-
details.controlMask = r.controlMask
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (r.backend) {
|
|
164
|
-
details.backendSend = r.backend
|
|
165
|
-
}
|
|
166
|
-
|
|
167
146
|
if (r.redis) {
|
|
168
147
|
details.redis = r.redis
|
|
169
148
|
}
|
|
@@ -191,53 +170,9 @@ const REPORTERS = {
|
|
|
191
170
|
msg: 'Wrong channel name'
|
|
192
171
|
}),
|
|
193
172
|
|
|
194
|
-
wrongControlIp: () => ({
|
|
195
|
-
level: 'warn',
|
|
196
|
-
msg: 'IP address of control request do not pass the mask'
|
|
197
|
-
}),
|
|
198
|
-
|
|
199
|
-
wrongControlSecret: () => ({
|
|
200
|
-
level: 'warn',
|
|
201
|
-
msg: 'Wrong secret in control request'
|
|
202
|
-
}),
|
|
203
|
-
|
|
204
173
|
zombie: () => ({ level: 'warn', msg: 'Zombie client was disconnected' })
|
|
205
174
|
}
|
|
206
175
|
|
|
207
|
-
function createLogger(options) {
|
|
208
|
-
if (options.logger === 'human' || options.logger.type === 'human') {
|
|
209
|
-
let env = options.env || process.env.NODE_ENV || 'development'
|
|
210
|
-
let color =
|
|
211
|
-
env !== 'development' ? false : pico.createColors().isColorSupported
|
|
212
|
-
let basepath = options.root || process.cwd()
|
|
213
|
-
if (basepath.slice(-1) !== sep) basepath += sep
|
|
214
|
-
|
|
215
|
-
let logger = pino(
|
|
216
|
-
pino.transport({
|
|
217
|
-
options: {
|
|
218
|
-
basepath,
|
|
219
|
-
color,
|
|
220
|
-
destination: options.logger.destination
|
|
221
|
-
},
|
|
222
|
-
target: PATH_TO_PRETTIFYING_PINO_TRANSPORT
|
|
223
|
-
})
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
// NOTE: needed only for tests
|
|
227
|
-
logger._basepath = basepath
|
|
228
|
-
logger._color = color
|
|
229
|
-
|
|
230
|
-
return logger
|
|
231
|
-
}
|
|
232
|
-
return pino(
|
|
233
|
-
{
|
|
234
|
-
name: 'logux-server',
|
|
235
|
-
timestamp: pino.stdTimeFunctions.isoTime
|
|
236
|
-
},
|
|
237
|
-
options.logger.stream || pino.destination()
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
176
|
function cleanFromKeys(obj, regexp, seen) {
|
|
242
177
|
let result = {}
|
|
243
178
|
for (let key in obj) {
|
|
@@ -270,12 +205,56 @@ export function createReporter(options) {
|
|
|
270
205
|
)
|
|
271
206
|
}
|
|
272
207
|
|
|
273
|
-
|
|
274
|
-
typeof options.logger !== 'string' && 'info' in options.logger
|
|
275
|
-
if (customLoggerProvided) {
|
|
208
|
+
if (typeof options.logger !== 'string' && 'info' in options.logger) {
|
|
276
209
|
reporter.logger = options.logger
|
|
277
210
|
} else {
|
|
278
|
-
|
|
211
|
+
let format
|
|
212
|
+
if (options.logger === 'human' || options.logger.type === 'human') {
|
|
213
|
+
let basepath = options.root || process.cwd()
|
|
214
|
+
if (basepath.slice(-1) !== sep) basepath += sep
|
|
215
|
+
format = humanFormatter({ basepath })
|
|
216
|
+
} else {
|
|
217
|
+
format = record => JSON.stringify(record) + '\n'
|
|
218
|
+
}
|
|
219
|
+
let stream = options.logger?.stream ?? process.stderr
|
|
220
|
+
|
|
221
|
+
function createRecord(level, details, msg) {
|
|
222
|
+
/* c8 ignore next 4 */
|
|
223
|
+
if (typeof details === 'string') {
|
|
224
|
+
msg = details
|
|
225
|
+
details = {}
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
level,
|
|
229
|
+
time: new Date().toISOString(),
|
|
230
|
+
pid: process.pid,
|
|
231
|
+
...details,
|
|
232
|
+
msg
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
reporter.logger = {
|
|
237
|
+
/* c8 ignore next 3 */
|
|
238
|
+
debug(details, msg) {
|
|
239
|
+
stream.write(format(createRecord(20, details, msg)))
|
|
240
|
+
},
|
|
241
|
+
info(details, msg) {
|
|
242
|
+
stream.write(format(createRecord(30, details, msg)))
|
|
243
|
+
},
|
|
244
|
+
warn(details, msg) {
|
|
245
|
+
stream.write(format(createRecord(40, details, msg)))
|
|
246
|
+
},
|
|
247
|
+
error(details, msg) {
|
|
248
|
+
stream.write(format(createRecord(50, details, msg)))
|
|
249
|
+
},
|
|
250
|
+
fatal(details, msg) {
|
|
251
|
+
if (stream.flushSync) {
|
|
252
|
+
stream.flushSync(format(createRecord(60, details, msg)))
|
|
253
|
+
} else {
|
|
254
|
+
stream.write(format(createRecord(60, details, msg)))
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
279
258
|
}
|
|
280
259
|
return reporter
|
|
281
260
|
}
|