@logux/server 0.10.1 → 0.10.5
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/base-server/index.d.ts +56 -29
- package/base-server/index.js +13 -8
- package/bind-control-server/index.js +1 -1
- package/create-reporter/index.js +9 -3
- package/human-formatter/index.js +3 -33
- package/options-loader/index.js +3 -6
- package/options-loader/index.test.js +257 -0
- package/package.json +12 -12
- package/server/index.js +4 -2
package/base-server/index.d.ts
CHANGED
|
@@ -247,9 +247,11 @@ interface Authorizer<
|
|
|
247
247
|
Data extends object,
|
|
248
248
|
Headers extends object
|
|
249
249
|
> {
|
|
250
|
-
(
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
(
|
|
251
|
+
ctx: Context<Data, Headers>,
|
|
252
|
+
action: Readonly<TypeAction>,
|
|
253
|
+
meta: Readonly<ServerMeta>
|
|
254
|
+
): boolean | Promise<boolean>
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
/**
|
|
@@ -265,9 +267,11 @@ interface Resender<
|
|
|
265
267
|
Data extends object,
|
|
266
268
|
Headers extends object
|
|
267
269
|
> {
|
|
268
|
-
(
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
(
|
|
271
|
+
ctx: Context<Data, Headers>,
|
|
272
|
+
action: Readonly<TypeAction>,
|
|
273
|
+
meta: Readonly<ServerMeta>
|
|
274
|
+
): Resend | Promise<Resend>
|
|
271
275
|
}
|
|
272
276
|
|
|
273
277
|
/**
|
|
@@ -285,8 +289,8 @@ interface Processor<
|
|
|
285
289
|
> {
|
|
286
290
|
(
|
|
287
291
|
ctx: Context<Data, Headers>,
|
|
288
|
-
action: TypeAction
|
|
289
|
-
meta: ServerMeta
|
|
292
|
+
action: Readonly<TypeAction>,
|
|
293
|
+
meta: Readonly<ServerMeta>
|
|
290
294
|
): void | Promise<void>
|
|
291
295
|
}
|
|
292
296
|
|
|
@@ -303,7 +307,11 @@ interface ActionFinally<
|
|
|
303
307
|
Data extends object,
|
|
304
308
|
Headers extends object
|
|
305
309
|
> {
|
|
306
|
-
(
|
|
310
|
+
(
|
|
311
|
+
ctx: Context<Data, Headers>,
|
|
312
|
+
action: Readonly<TypeAction>,
|
|
313
|
+
meta: Readonly<ServerMeta>
|
|
314
|
+
): void
|
|
307
315
|
}
|
|
308
316
|
|
|
309
317
|
/**
|
|
@@ -315,7 +323,11 @@ interface ActionFinally<
|
|
|
315
323
|
* @returns Should action be sent to client.
|
|
316
324
|
*/
|
|
317
325
|
interface ChannelFilter<Headers extends object> {
|
|
318
|
-
(
|
|
326
|
+
(
|
|
327
|
+
ctx: Context<{}, Headers>,
|
|
328
|
+
action: Readonly<Action>,
|
|
329
|
+
meta: Readonly<ServerMeta>
|
|
330
|
+
): boolean
|
|
319
331
|
}
|
|
320
332
|
|
|
321
333
|
/**
|
|
@@ -334,8 +346,8 @@ interface ChannelAuthorizer<
|
|
|
334
346
|
> {
|
|
335
347
|
(
|
|
336
348
|
ctx: ChannelContext<Data, ChannelParams, Headers>,
|
|
337
|
-
action: SubscribeAction
|
|
338
|
-
meta: ServerMeta
|
|
349
|
+
action: Readonly<SubscribeAction>,
|
|
350
|
+
meta: Readonly<ServerMeta>
|
|
339
351
|
): boolean | Promise<boolean>
|
|
340
352
|
}
|
|
341
353
|
|
|
@@ -355,8 +367,8 @@ interface FilterCreator<
|
|
|
355
367
|
> {
|
|
356
368
|
(
|
|
357
369
|
ctx: ChannelContext<Data, ChannelParams, Headers>,
|
|
358
|
-
action: SubscribeAction
|
|
359
|
-
meta: ServerMeta
|
|
370
|
+
action: Readonly<SubscribeAction>,
|
|
371
|
+
meta: Readonly<ServerMeta>
|
|
360
372
|
): Promise<ChannelFilter<Headers>> | ChannelFilter<Headers> | void
|
|
361
373
|
}
|
|
362
374
|
|
|
@@ -376,8 +388,8 @@ interface ChannelLoader<
|
|
|
376
388
|
> {
|
|
377
389
|
(
|
|
378
390
|
ctx: ChannelContext<Data, ChannelParams, Headers>,
|
|
379
|
-
action: SubscribeAction
|
|
380
|
-
meta: ServerMeta
|
|
391
|
+
action: Readonly<SubscribeAction>,
|
|
392
|
+
meta: Readonly<ServerMeta>
|
|
381
393
|
): SendBackActions | Promise<SendBackActions>
|
|
382
394
|
}
|
|
383
395
|
|
|
@@ -397,8 +409,8 @@ interface ChannelFinally<
|
|
|
397
409
|
> {
|
|
398
410
|
(
|
|
399
411
|
ctx: ChannelContext<Data, ChannelParams, Headers>,
|
|
400
|
-
action: SubscribeAction
|
|
401
|
-
meta: ServerMeta
|
|
412
|
+
action: Readonly<SubscribeAction>,
|
|
413
|
+
meta: Readonly<ServerMeta>
|
|
402
414
|
): void
|
|
403
415
|
}
|
|
404
416
|
|
|
@@ -418,7 +430,7 @@ interface ChannelUnsubscribe<
|
|
|
418
430
|
(
|
|
419
431
|
ctx: ChannelContext<Data, ChannelParams, Headers>,
|
|
420
432
|
action: LoguxUnsubscribeAction,
|
|
421
|
-
meta: ServerMeta
|
|
433
|
+
meta: Readonly<ServerMeta>
|
|
422
434
|
): void
|
|
423
435
|
}
|
|
424
436
|
|
|
@@ -464,8 +476,8 @@ type ChannelCallbacks<
|
|
|
464
476
|
}
|
|
465
477
|
|
|
466
478
|
interface ActionReporter {
|
|
467
|
-
action: Action
|
|
468
|
-
meta: ServerMeta
|
|
479
|
+
action: Readonly<Action>
|
|
480
|
+
meta: Readonly<ServerMeta>
|
|
469
481
|
}
|
|
470
482
|
|
|
471
483
|
interface SubscriptionReporter {
|
|
@@ -585,7 +597,7 @@ interface GetProcessor {
|
|
|
585
597
|
}
|
|
586
598
|
|
|
587
599
|
interface PostProcessor {
|
|
588
|
-
isValid(command: object):
|
|
600
|
+
isValid(command: object): boolean
|
|
589
601
|
command(command: object, request: object): Promise<void>
|
|
590
602
|
}
|
|
591
603
|
|
|
@@ -817,7 +829,7 @@ export class BaseServer<
|
|
|
817
829
|
*/
|
|
818
830
|
on(
|
|
819
831
|
event: 'error',
|
|
820
|
-
listener: (err: Error, action: Action, meta: ServerMeta) => void
|
|
832
|
+
listener: (err: Error, action: Action, meta: Readonly<ServerMeta>) => void
|
|
821
833
|
): Unsubscribe
|
|
822
834
|
|
|
823
835
|
/**
|
|
@@ -843,7 +855,16 @@ export class BaseServer<
|
|
|
843
855
|
* @param listener Action listener.
|
|
844
856
|
*/
|
|
845
857
|
on(
|
|
846
|
-
event: '
|
|
858
|
+
event: 'add' | 'clean' | 'backendSent',
|
|
859
|
+
listener: (action: Action, meta: Readonly<ServerMeta>) => void
|
|
860
|
+
): Unsubscribe
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* @param event The event name.
|
|
864
|
+
* @param listener Action listener.
|
|
865
|
+
*/
|
|
866
|
+
on(
|
|
867
|
+
event: 'preadd',
|
|
847
868
|
listener: (action: Action, meta: ServerMeta) => void
|
|
848
869
|
): Unsubscribe
|
|
849
870
|
|
|
@@ -855,7 +876,7 @@ export class BaseServer<
|
|
|
855
876
|
event: 'processed' | 'backendGranted' | 'backendProcessed',
|
|
856
877
|
listener: (
|
|
857
878
|
action: Action,
|
|
858
|
-
meta: ServerMeta
|
|
879
|
+
meta: Readonly<ServerMeta>,
|
|
859
880
|
latencyMilliseconds: number
|
|
860
881
|
) => void
|
|
861
882
|
): Unsubscribe
|
|
@@ -868,7 +889,7 @@ export class BaseServer<
|
|
|
868
889
|
event: 'subscribed',
|
|
869
890
|
listener: (
|
|
870
891
|
action: LoguxSubscribeAction,
|
|
871
|
-
meta: ServerMeta
|
|
892
|
+
meta: Readonly<ServerMeta>,
|
|
872
893
|
latencyMilliseconds: number
|
|
873
894
|
) => void
|
|
874
895
|
): Unsubscribe
|
|
@@ -879,7 +900,7 @@ export class BaseServer<
|
|
|
879
900
|
*/
|
|
880
901
|
on(
|
|
881
902
|
event: 'subscribing',
|
|
882
|
-
listener: (action: LoguxSubscribeAction, meta: ServerMeta) => void
|
|
903
|
+
listener: (action: LoguxSubscribeAction, meta: Readonly<ServerMeta>) => void
|
|
883
904
|
): Unsubscribe
|
|
884
905
|
|
|
885
906
|
/**
|
|
@@ -888,7 +909,10 @@ export class BaseServer<
|
|
|
888
909
|
*/
|
|
889
910
|
on(
|
|
890
911
|
event: 'unsubscribed',
|
|
891
|
-
listener: (
|
|
912
|
+
listener: (
|
|
913
|
+
action: LoguxUnsubscribeAction,
|
|
914
|
+
meta: Readonly<ServerMeta>
|
|
915
|
+
) => void
|
|
892
916
|
): Unsubscribe
|
|
893
917
|
|
|
894
918
|
/**
|
|
@@ -1058,7 +1082,10 @@ export class BaseServer<
|
|
|
1058
1082
|
* @param meta Action’s meta.
|
|
1059
1083
|
* @returns Promise until new action will be resend to clients and processed.
|
|
1060
1084
|
*/
|
|
1061
|
-
process(
|
|
1085
|
+
process(
|
|
1086
|
+
action: AnyAction,
|
|
1087
|
+
meta?: Partial<ServerMeta>
|
|
1088
|
+
): Promise<Readonly<ServerMeta>>
|
|
1062
1089
|
|
|
1063
1090
|
/**
|
|
1064
1091
|
* Undo action from client.
|
package/base-server/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { createHttpServer } from '../create-http-server/index.js'
|
|
|
14
14
|
import { ServerClient } from '../server-client/index.js'
|
|
15
15
|
import { Context } from '../context/index.js'
|
|
16
16
|
|
|
17
|
+
const SKIP_PROCESS = Symbol('skipProcess')
|
|
17
18
|
const RESEND_META = ['channels', 'users', 'clients', 'nodes']
|
|
18
19
|
|
|
19
20
|
function optionError(msg) {
|
|
@@ -48,11 +49,15 @@ export async function wasNot403(cb) {
|
|
|
48
49
|
|
|
49
50
|
function normalizeTypeCallbacks(name, callbacks) {
|
|
50
51
|
if (callbacks && callbacks.accessAndProcess) {
|
|
51
|
-
callbacks.access = (...args) => {
|
|
52
|
+
callbacks.access = (ctx, ...args) => {
|
|
52
53
|
return wasNot403(async () => {
|
|
53
|
-
await callbacks.accessAndProcess(...args)
|
|
54
|
+
await callbacks.accessAndProcess(ctx, ...args)
|
|
55
|
+
ctx[SKIP_PROCESS] = true
|
|
54
56
|
})
|
|
55
57
|
}
|
|
58
|
+
callbacks.process = async (ctx, ...args) => {
|
|
59
|
+
if (!ctx[SKIP_PROCESS]) await callbacks.accessAndProcess(ctx, ...args)
|
|
60
|
+
}
|
|
56
61
|
}
|
|
57
62
|
if (!callbacks || !callbacks.access) {
|
|
58
63
|
throw new Error(`${name} must have access callback`)
|
|
@@ -373,12 +378,12 @@ export class BaseServer {
|
|
|
373
378
|
if (!this.authenticator) {
|
|
374
379
|
throw new Error('You must set authentication callback by server.auth()')
|
|
375
380
|
}
|
|
376
|
-
this.
|
|
377
|
-
this.ws = new WebSocket.Server({ server: this.
|
|
381
|
+
this.httpServer = await createHttpServer(this.options)
|
|
382
|
+
this.ws = new WebSocket.Server({ server: this.httpServer })
|
|
378
383
|
if (!this.options.server) {
|
|
379
384
|
await new Promise((resolve, reject) => {
|
|
380
385
|
this.ws.on('error', reject)
|
|
381
|
-
this.
|
|
386
|
+
this.httpServer.listen(this.options.port, this.options.host, resolve)
|
|
382
387
|
})
|
|
383
388
|
}
|
|
384
389
|
bindControlServer(this, this.httpListener)
|
|
@@ -390,12 +395,12 @@ export class BaseServer {
|
|
|
390
395
|
this.ws.close()
|
|
391
396
|
})
|
|
392
397
|
)
|
|
393
|
-
if (this.
|
|
398
|
+
if (this.httpServer) {
|
|
394
399
|
this.unbind.push(
|
|
395
400
|
() =>
|
|
396
401
|
new Promise(resolve => {
|
|
397
|
-
this.
|
|
398
|
-
this.
|
|
402
|
+
this.httpServer.on('close', resolve)
|
|
403
|
+
this.httpServer.close()
|
|
399
404
|
})
|
|
400
405
|
)
|
|
401
406
|
}
|
|
@@ -18,7 +18,7 @@ function isValidBody(body) {
|
|
|
18
18
|
|
|
19
19
|
export function bindControlServer(app, custom) {
|
|
20
20
|
let masks = app.options.controlMask.split(/,\s*/).map(i => ip.cidrSubnet(i))
|
|
21
|
-
app.
|
|
21
|
+
app.httpServer.on('request', async (req, res) => {
|
|
22
22
|
let urlString = req.url
|
|
23
23
|
if (/^\/\w+%3F/.test(urlString)) urlString = decodeURIComponent(urlString)
|
|
24
24
|
let reqUrl = new URL(urlString, 'http://localhost')
|
package/create-reporter/index.js
CHANGED
|
@@ -222,14 +222,19 @@ function createLogger(options) {
|
|
|
222
222
|
)
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
function cleanFromKeys(obj, regexp) {
|
|
225
|
+
function cleanFromKeys(obj, regexp, seen) {
|
|
226
226
|
let result = {}
|
|
227
227
|
for (let key in obj) {
|
|
228
228
|
let v = obj[key]
|
|
229
229
|
if (typeof v === 'string') {
|
|
230
230
|
result[key] = v.replace(regexp, '[SECRET]')
|
|
231
231
|
} else if (typeof v === 'object' && !Array.isArray(v) && v !== null) {
|
|
232
|
-
|
|
232
|
+
if (seen.includes(v)) {
|
|
233
|
+
throw new Error('Circular reference in action')
|
|
234
|
+
}
|
|
235
|
+
seen.push(v)
|
|
236
|
+
result[key] = cleanFromKeys(v, regexp, seen)
|
|
237
|
+
seen.pop()
|
|
233
238
|
} else {
|
|
234
239
|
result[key] = v
|
|
235
240
|
}
|
|
@@ -242,8 +247,9 @@ export function createReporter(options) {
|
|
|
242
247
|
function reporter(type, details) {
|
|
243
248
|
let report = REPORTERS[type](details)
|
|
244
249
|
let level = report.level || 'info'
|
|
250
|
+
let seen = []
|
|
245
251
|
reporter.logger[level](
|
|
246
|
-
cleanFromKeys(report.details || details || {}, cleanFromLog),
|
|
252
|
+
cleanFromKeys(report.details || details || {}, cleanFromLog, seen),
|
|
247
253
|
report.msg.replace(cleanFromLog, '[SECRET]')
|
|
248
254
|
)
|
|
249
255
|
}
|
package/human-formatter/index.js
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
green,
|
|
3
|
-
bgGreen,
|
|
4
|
-
yellow,
|
|
5
|
-
bgYellow,
|
|
6
|
-
red,
|
|
7
|
-
bgRed,
|
|
8
|
-
black,
|
|
9
|
-
white,
|
|
10
|
-
gray,
|
|
11
|
-
dim,
|
|
12
|
-
bold,
|
|
13
|
-
options as colorette
|
|
14
|
-
} from 'colorette'
|
|
1
|
+
import { createColors } from 'nanocolors'
|
|
15
2
|
import stripAnsi from 'strip-ansi'
|
|
16
3
|
import yyyymmdd from 'yyyy-mm-dd'
|
|
17
4
|
import path from 'path'
|
|
@@ -183,25 +170,8 @@ function prettyStackTrace(c, stack, basepath) {
|
|
|
183
170
|
}
|
|
184
171
|
|
|
185
172
|
export function humanFormatter(options) {
|
|
186
|
-
let c =
|
|
187
|
-
|
|
188
|
-
bgGreen,
|
|
189
|
-
yellow,
|
|
190
|
-
bgYellow,
|
|
191
|
-
red,
|
|
192
|
-
bgRed,
|
|
193
|
-
black,
|
|
194
|
-
white,
|
|
195
|
-
gray,
|
|
196
|
-
dim,
|
|
197
|
-
bold
|
|
198
|
-
}
|
|
199
|
-
this.color = true
|
|
200
|
-
if (options.color === false || !colorette.enabled) {
|
|
201
|
-
this.color = false
|
|
202
|
-
let empty = str => str
|
|
203
|
-
for (let color in c) c[color] = empty
|
|
204
|
-
}
|
|
173
|
+
let c = createColors(options.color)
|
|
174
|
+
this.color = c.isColorSupported
|
|
205
175
|
let basepath = options.basepath || process.cwd()
|
|
206
176
|
if (basepath.slice(-1) !== path.sep) basepath += path.sep
|
|
207
177
|
this.basepath = basepath
|
package/options-loader/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bold, cyan, yellow, green, red } from '
|
|
1
|
+
import { bold, cyan, yellow, green, red } from 'nanocolors'
|
|
2
2
|
import dotenv from 'dotenv'
|
|
3
3
|
|
|
4
4
|
export function loadOptions(spec, process, env) {
|
|
@@ -31,11 +31,8 @@ export function loadOptions(spec, process, env) {
|
|
|
31
31
|
key.startsWith(spec.envPrefix)
|
|
32
32
|
)
|
|
33
33
|
)
|
|
34
|
-
envArgs = parseValues(
|
|
35
|
-
|
|
36
|
-
mapArgs(Object.assign(envArgs, dotenvArgs), namesMap)
|
|
37
|
-
)
|
|
38
|
-
return [null, Object.assign(envArgs, cliArgs)]
|
|
34
|
+
envArgs = parseValues(spec, mapArgs({ ...envArgs, ...dotenvArgs }, namesMap))
|
|
35
|
+
return [null, { ...envArgs, ...cliArgs }]
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
function gatherCliArgs(argv) {
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
|
|
3
|
+
import { loadOptions, oneOf, number } from './index.js'
|
|
4
|
+
|
|
5
|
+
function fakeProcess(argv, env = {}) {
|
|
6
|
+
return { argv, env }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
describe('loadOptions', () => {
|
|
10
|
+
it('returns help', () => {
|
|
11
|
+
let [help, options] = loadOptions(
|
|
12
|
+
{
|
|
13
|
+
options: {
|
|
14
|
+
port: {
|
|
15
|
+
description: 'port',
|
|
16
|
+
parse: number
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
examples: ['$0']
|
|
20
|
+
},
|
|
21
|
+
fakeProcess(['node', 'test/test.js', '--help'])
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
expect(help).toMatchSnapshot()
|
|
25
|
+
expect(options).toBeNull()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('uses CLI args for options', () => {
|
|
29
|
+
let [, options] = loadOptions(
|
|
30
|
+
{
|
|
31
|
+
options: {
|
|
32
|
+
port: {
|
|
33
|
+
description: 'port',
|
|
34
|
+
parse: number
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
fakeProcess(['', '--port', '1337'])
|
|
39
|
+
)
|
|
40
|
+
expect(options.port).toEqual(1337)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('uses env for options', () => {
|
|
44
|
+
let [, options] = loadOptions(
|
|
45
|
+
{
|
|
46
|
+
options: {
|
|
47
|
+
port: {
|
|
48
|
+
description: 'port',
|
|
49
|
+
parse: number
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
envPrefix: 'LOGUX'
|
|
53
|
+
},
|
|
54
|
+
fakeProcess([], {
|
|
55
|
+
LOGUX_PORT: '31337'
|
|
56
|
+
}),
|
|
57
|
+
{}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
expect(options.port).toEqual(31337)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('uses dotenv file for options', () => {
|
|
64
|
+
let [, options] = loadOptions(
|
|
65
|
+
{
|
|
66
|
+
options: {
|
|
67
|
+
port: {
|
|
68
|
+
description: 'port',
|
|
69
|
+
parse: number
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
envPrefix: 'LOGUX'
|
|
73
|
+
},
|
|
74
|
+
fakeProcess([], {}),
|
|
75
|
+
{
|
|
76
|
+
path: resolve(process.cwd(), 'options-loader/test.env')
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
expect(options.port).toEqual(31337)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('composes correct env and CLI names for argument with complex name', () => {
|
|
84
|
+
let [, options] = loadOptions(
|
|
85
|
+
{
|
|
86
|
+
options: {
|
|
87
|
+
somePort: {
|
|
88
|
+
description: 'port',
|
|
89
|
+
parse: number
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
envPrefix: 'LOGUX'
|
|
93
|
+
},
|
|
94
|
+
fakeProcess(['--some-port', '1'], {
|
|
95
|
+
LOGUX_SOME_PORT: '1'
|
|
96
|
+
}),
|
|
97
|
+
{}
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
expect(options.somePort).toEqual(1)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('uses combined options', () => {
|
|
104
|
+
let [, options] = loadOptions(
|
|
105
|
+
{
|
|
106
|
+
options: {
|
|
107
|
+
key: {
|
|
108
|
+
description: 'port'
|
|
109
|
+
},
|
|
110
|
+
cert: {
|
|
111
|
+
description: 'cert'
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
envPrefix: 'LOGUX'
|
|
115
|
+
},
|
|
116
|
+
fakeProcess(['', '--key', './key.pem'], { LOGUX_CERT: './cert.pem' })
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
expect(options.cert).toEqual('./cert.pem')
|
|
120
|
+
expect(options.key).toEqual('./key.pem')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('uses arg and env in given priority', () => {
|
|
124
|
+
let optionsSpec = {
|
|
125
|
+
options: {
|
|
126
|
+
port: {
|
|
127
|
+
description: 'port',
|
|
128
|
+
parse: number
|
|
129
|
+
},
|
|
130
|
+
key: {
|
|
131
|
+
description: 'key'
|
|
132
|
+
},
|
|
133
|
+
cert: {
|
|
134
|
+
description: 'cert'
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
envPrefix: 'LOGUX'
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let [, options1] = loadOptions(
|
|
141
|
+
optionsSpec,
|
|
142
|
+
fakeProcess(['', '--port', '3'], { LOGUX_PORT: '2' }),
|
|
143
|
+
undefined
|
|
144
|
+
)
|
|
145
|
+
let [, options2] = loadOptions(
|
|
146
|
+
optionsSpec,
|
|
147
|
+
fakeProcess([], { LOGUX_PORT: '2' }),
|
|
148
|
+
undefined
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
expect(options1.port).toEqual(3)
|
|
152
|
+
expect(options2.port).toEqual(2)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('parses aliases', () => {
|
|
156
|
+
let [, options] = loadOptions(
|
|
157
|
+
{
|
|
158
|
+
options: {
|
|
159
|
+
port: {
|
|
160
|
+
alias: 'p',
|
|
161
|
+
description: 'port'
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
fakeProcess(['', '-p', '1'])
|
|
166
|
+
)
|
|
167
|
+
expect(options.port).toEqual('1')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('parses multiple args', () => {
|
|
171
|
+
let [, options] = loadOptions(
|
|
172
|
+
{
|
|
173
|
+
options: {
|
|
174
|
+
port: {
|
|
175
|
+
alias: 'p',
|
|
176
|
+
description: 'port'
|
|
177
|
+
},
|
|
178
|
+
key: {
|
|
179
|
+
description: 'key'
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
fakeProcess(['', '-p', '1', '--key', '1'])
|
|
184
|
+
)
|
|
185
|
+
expect(options.port).toEqual('1')
|
|
186
|
+
expect(options.key).toEqual('1')
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it('throws on missing values', () => {
|
|
190
|
+
expect(() =>
|
|
191
|
+
loadOptions(
|
|
192
|
+
{
|
|
193
|
+
options: {
|
|
194
|
+
port: {
|
|
195
|
+
description: 'port'
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
fakeProcess(['', '--port'])
|
|
200
|
+
)
|
|
201
|
+
).toThrowErrorMatchingSnapshot()
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('throws on unknown args', () => {
|
|
205
|
+
expect(() =>
|
|
206
|
+
loadOptions(
|
|
207
|
+
{
|
|
208
|
+
options: {
|
|
209
|
+
port: {
|
|
210
|
+
description: 'port'
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
fakeProcess(['', '--unknown', '1'])
|
|
215
|
+
)
|
|
216
|
+
).toThrowErrorMatchingSnapshot()
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it('throws on unparsed args', () => {
|
|
220
|
+
expect(() =>
|
|
221
|
+
loadOptions(
|
|
222
|
+
{
|
|
223
|
+
options: {
|
|
224
|
+
port: {
|
|
225
|
+
description: 'port',
|
|
226
|
+
parse: number
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
fakeProcess(['', '--port', 'W_W'])
|
|
231
|
+
)
|
|
232
|
+
).toThrowErrorMatchingSnapshot()
|
|
233
|
+
})
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
describe('parsers', () => {
|
|
237
|
+
describe('oneOf', () => {
|
|
238
|
+
it('should return error on invalid values', () => {
|
|
239
|
+
let result = oneOf(['1', '2'], '3')
|
|
240
|
+
expect(result[0]).toMatchSnapshot()
|
|
241
|
+
})
|
|
242
|
+
it('should return null on correct values', () => {
|
|
243
|
+
expect(oneOf(['1', '2'], '1')).toEqual([null, '1'])
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
describe('number', () => {
|
|
248
|
+
it('should return error on invalid values', () => {
|
|
249
|
+
let result = number('not a number')
|
|
250
|
+
expect(result[0]).toMatchSnapshot()
|
|
251
|
+
})
|
|
252
|
+
it('should return null on correct values', () => {
|
|
253
|
+
expect(number('1')).toEqual([null, 1])
|
|
254
|
+
expect(number('1why parseInt is so permissive')).toEqual([null, 1])
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logux/server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "Build own Logux server or make proxy between WebSocket and HTTP backend on any language",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"logux",
|
|
@@ -27,24 +27,24 @@
|
|
|
27
27
|
"./package.json": "./package.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@logux/actions": "^0.2.
|
|
31
|
-
"@logux/core": "^0.7.
|
|
30
|
+
"@logux/actions": "^0.2.1",
|
|
31
|
+
"@logux/core": "^0.7.2",
|
|
32
32
|
"@types/node-fetch": "^2.5.10",
|
|
33
33
|
"JSONStream": "^1.3.5",
|
|
34
|
-
"colorette": "^1.2.2",
|
|
35
34
|
"cookie": "^0.4.1",
|
|
36
|
-
"dotenv": "^
|
|
37
|
-
"globby": "^11.0.
|
|
35
|
+
"dotenv": "^10.0.0",
|
|
36
|
+
"globby": "^11.0.4",
|
|
38
37
|
"ip": "^1.1.5",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
38
|
+
"nanocolors": "^0.2.12",
|
|
39
|
+
"nanodelay": "^2.0.1",
|
|
40
|
+
"nanoevents": "^6.0.1",
|
|
41
|
+
"nanoid": "^3.1.28",
|
|
42
42
|
"node-fetch": "^2.6.1",
|
|
43
|
-
"pino": "^6.
|
|
43
|
+
"pino": "^6.13.3",
|
|
44
44
|
"semver": "^7.3.5",
|
|
45
|
-
"strip-ansi": "^7.0.
|
|
45
|
+
"strip-ansi": "^7.0.1",
|
|
46
46
|
"url-pattern": "^1.0.3",
|
|
47
|
-
"ws": "^7.
|
|
47
|
+
"ws": "^7.5.0",
|
|
48
48
|
"yyyy-mm-dd": "^1.0.2"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join, relative } from 'path'
|
|
2
2
|
import globby from 'globby'
|
|
3
|
-
import { bgRed, black } from '
|
|
3
|
+
import { bgRed, black } from 'nanocolors'
|
|
4
4
|
|
|
5
5
|
import { createReporter } from '../create-reporter/index.js'
|
|
6
6
|
import { BaseServer } from '../base-server/index.js'
|
|
@@ -130,7 +130,9 @@ export class Server extends BaseServer {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
async autoloadModules(
|
|
133
|
+
async autoloadModules(
|
|
134
|
+
files = ['modules/*/index.js', 'modules/*.js', '!**/*.{test,spec}.js']
|
|
135
|
+
) {
|
|
134
136
|
let matches = await globby(files, {
|
|
135
137
|
cwd: this.options.root,
|
|
136
138
|
absolute: true,
|