@logux/server 0.12.3 → 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.
@@ -1,171 +1,185 @@
1
+ import type {
2
+ AbstractActionCreator,
3
+ LoguxSubscribeAction,
4
+ LoguxUnsubscribeAction
5
+ } from '@logux/actions'
1
6
  import type {
2
7
  Action,
3
8
  AnyAction,
4
9
  ID,
5
10
  Log,
11
+ LogStore,
6
12
  Meta,
7
13
  ServerConnection,
8
- LogStore,
9
14
  TestTime
10
15
  } from '@logux/core'
11
- import type { Server as HTTPServer, ServerResponse, IncomingMessage } from 'http'
12
- import type {
13
- LoguxUnsubscribeAction,
14
- AbstractActionCreator,
15
- LoguxSubscribeAction
16
- } from '@logux/actions'
16
+ import type { Server as HTTPServer, IncomingMessage, ServerResponse } from 'http'
17
17
  import type { Unsubscribe } from 'nanoevents'
18
18
  import type { LogFn } from 'pino'
19
- import type { Context, ChannelContext } from '../context/index.js'
19
+
20
+ import type { ChannelContext, Context } from '../context/index.js'
20
21
  import type { ServerClient } from '../server-client/index.js'
21
22
 
22
23
  export interface ServerMeta extends Meta {
23
24
  /**
24
- * Action processing status
25
+ * All nodes subscribed to channel will receive the action.
25
26
  */
26
- status?: 'waiting' | 'processed' | 'error'
27
+ channel?: string
27
28
 
28
29
  /**
29
- * Node ID of the server received the action.
30
+ * All nodes subscribed to listed channels will receive the action.
30
31
  */
31
- server: string
32
+ channels?: string[]
32
33
 
33
34
  /**
34
- * All nodes subscribed to listed channels will receive the action.
35
+ * All nodes with listed client ID will receive the action.
35
36
  */
36
- channels?: string[]
37
+ client?: string
37
38
 
38
39
  /**
39
- * All nodes subscribed to channel will receive the action.
40
+ * All nodes with listed client IDs will receive the action.
40
41
  */
41
- channel?: string
42
+ clients?: string[]
42
43
 
43
44
  /**
44
- * All nodes with listed user IDs will receive the action.
45
+ * Client IDs, which will not receive the action.
45
46
  */
46
- users?: string[]
47
+ excludeClients?: string[]
47
48
 
48
49
  /**
49
- * All nodes with listed user ID will receive the action.
50
+ * Node with listed node ID will receive the action.
50
51
  */
51
- user?: string
52
+ node?: string
52
53
 
53
54
  /**
54
- * All nodes with listed client IDs will receive the action.
55
+ * All nodes with listed node IDs will receive the action.
55
56
  */
56
- clients?: string[]
57
+ nodes?: string[]
57
58
 
58
59
  /**
59
- * All nodes with listed client ID will receive the action.
60
+ * Node ID of the server received the action.
60
61
  */
61
- client?: string
62
+ server: string
62
63
 
63
64
  /**
64
- * All nodes with listed node IDs will receive the action.
65
+ * Action processing status
65
66
  */
66
- nodes?: string[]
67
+ status?: 'error' | 'processed' | 'waiting'
67
68
 
68
69
  /**
69
- * Node with listed node ID will receive the action.
70
+ * All nodes with listed user ID will receive the action.
70
71
  */
71
- node?: string
72
+ user?: string
72
73
 
73
74
  /**
74
- * Client IDs, which will not receive the action.
75
+ * All nodes with listed user IDs will receive the action.
75
76
  */
76
- excludeClients?: string[]
77
+ users?: string[]
77
78
  }
78
79
 
79
80
  export interface BaseServerOptions {
80
81
  /**
81
- * Server current application subprotocol version in SemVer format.
82
+ * URL to PHP, Ruby on Rails, or other backend to process actions and
83
+ * authentication.
82
84
  */
83
- subprotocol?: string
85
+ backend?: string
84
86
 
85
87
  /**
86
- * npm’s version requirements for client subprotocol version.
88
+ * SSL certificate or path to it. Path could be relative from server
89
+ * root. It is required in production mode, because WSS is highly
90
+ * recommended.
87
91
  */
88
- supports?: string
92
+ cert?: string
89
93
 
90
94
  /**
91
- * Application root to load files and show errors.
92
- * Default is `process.cwd()`.
95
+ * Regular expression which should be cleaned from error message and stack.
93
96
  *
94
- * ```js
95
- * root: __dirname
96
- * ```
97
+ * By default it cleans `Bearer [^\s"]+`.
97
98
  */
98
- root?: string
99
+ cleanFromLog?: RegExp
99
100
 
100
101
  /**
101
- * URL of main JS file in the root dir. Shortcut to set `root` in ES modules
102
- * without `fileURLToPath`.
103
- *
104
- * ```
105
- * fileUrl: import.meta.url
106
- * ```
102
+ * CIDR masks for IP address, where control requests could came from.
107
103
  */
108
- fileUrl?: string
104
+ controlMask?: string
109
105
 
110
106
  /**
111
- * Timeout in milliseconds to disconnect connection.
112
- * Default is `70000`.
107
+ * Secret to control the server.
113
108
  */
114
- timeout?: number
109
+ controlSecret?: string
115
110
 
116
111
  /**
117
- * Milliseconds since last message to test connection by sending ping.
118
- * Default is `20000`.
112
+ * Disable health check endpoint, control HTTP API, {@link Server#http}.
113
+ *
114
+ * The server will process only WebSocket connection and ignore all other
115
+ * HTTP request (so they can be processed by other HTTP server).
119
116
  */
120
- ping?: number
117
+ disableHttpServer?: boolean
121
118
 
122
119
  /**
123
- * URL to PHP, Ruby on Rails, or other backend to process actions and
124
- * authentication.
120
+ * Development or production server mode. By default,
121
+ * it will be taken from `NODE_ENV` environment variable.
122
+ * On empty `NODE_ENV` it will be `'development'`.
125
123
  */
126
- backend?: string
124
+ env?: 'development' | 'production'
127
125
 
128
126
  /**
129
- * URL to Redis for Logux Server Pro scaling.
127
+ * URL of main JS file in the root dir. Shortcut to set `root` in ES modules
128
+ * without `fileURLToPath`.
129
+ *
130
+ * ```
131
+ * fileUrl: import.meta.url
132
+ * ```
130
133
  */
131
- redis?: string
134
+ fileUrl?: string
132
135
 
133
136
  /**
134
- * Secret to control the server.
137
+ * IP-address to bind server. Default is `127.0.0.1`.
135
138
  */
136
- controlSecret?: string
139
+ host?: string
137
140
 
138
141
  /**
139
- * CIDR masks for IP address, where control requests could came from.
142
+ * Custom random ID to be used in node ID.
140
143
  */
141
- controlMask?: string
144
+ id?: string
142
145
 
143
146
  /**
144
- * Store to save log. Will be {@link @logux/core:MemoryStore}, by default.
147
+ * SSL key or path to it. Path could be relative from server root.
148
+ * It is required in production mode, because WSS is highly recommended.
145
149
  */
146
- store?: LogStore
150
+ key?: { pem: string } | string
147
151
 
148
152
  /**
149
- * Test time to test server.
153
+ * Process ID, to display in logs.
150
154
  */
151
- time?: TestTime
155
+ pid?: number
152
156
 
153
157
  /**
154
- * Custom random ID to be used in node ID.
158
+ * Milliseconds since last message to test connection by sending ping.
159
+ * Default is `20000`.
155
160
  */
156
- id?: string
161
+ ping?: number
157
162
 
158
163
  /**
159
- * Development or production server mode. By default,
160
- * it will be taken from `NODE_ENV` environment variable.
161
- * On empty `NODE_ENV` it will be `'development'`.
164
+ * Port to bind server. It will create HTTP server manually to connect
165
+ * WebSocket server to it. Default is `31337`.
162
166
  */
163
- env?: 'production' | 'development'
167
+ port?: number
164
168
 
165
169
  /**
166
- * Process ID, to display in logs.
170
+ * URL to Redis for Logux Server Pro scaling.
167
171
  */
168
- pid?: number
172
+ redis?: string
173
+
174
+ /**
175
+ * Application root to load files and show errors.
176
+ * Default is `process.cwd()`.
177
+ *
178
+ * ```js
179
+ * root: __dirname
180
+ * ```
181
+ */
182
+ root?: string
169
183
 
170
184
  /**
171
185
  * HTTP server to serve Logux’s WebSocket and HTTP requests.
@@ -176,58 +190,45 @@ export interface BaseServerOptions {
176
190
  server?: HTTPServer
177
191
 
178
192
  /**
179
- * Port to bind server. It will create HTTP server manually to connect
180
- * WebSocket server to it. Default is `31337`.
181
- */
182
- port?: number
183
-
184
- /**
185
- * IP-address to bind server. Default is `127.0.0.1`.
193
+ * Store to save log. Will be {@link @logux/core:MemoryStore}, by default.
186
194
  */
187
- host?: string
195
+ store?: LogStore
188
196
 
189
197
  /**
190
- * SSL key or path to it. Path could be relative from server root.
191
- * It is required in production mode, because WSS is highly recommended.
198
+ * Server current application subprotocol version in SemVer format.
192
199
  */
193
- key?: string | { pem: string }
200
+ subprotocol?: string
194
201
 
195
202
  /**
196
- * SSL certificate or path to it. Path could be relative from server
197
- * root. It is required in production mode, because WSS is highly
198
- * recommended.
203
+ * npm’s version requirements for client subprotocol version.
199
204
  */
200
- cert?: string
205
+ supports?: string
201
206
 
202
207
  /**
203
- * Regular expression which should be cleaned from error message and stack.
204
- *
205
- * By default it cleans `Bearer [^\s"]+`.
208
+ * Test time to test server.
206
209
  */
207
- cleanFromLog?: RegExp
210
+ time?: TestTime
208
211
 
209
212
  /**
210
- * Disable health check endpoint, control HTTP API, {@link Server#http}.
211
- *
212
- * The server will process only WebSocket connection and ignore all other
213
- * HTTP request (so they can be processed by other HTTP server).
213
+ * Timeout in milliseconds to disconnect connection.
214
+ * Default is `70000`.
214
215
  */
215
- disableHttpServer?: boolean
216
+ timeout?: number
216
217
  }
217
218
 
218
219
  export interface AuthenticatorOptions<Headers extends object> {
219
- headers: Headers
220
220
  client: ServerClient
221
- userId: string
222
221
  cookie: Record<string, string>
222
+ headers: Headers
223
223
  token: string
224
+ userId: string
224
225
  }
225
226
 
226
227
  export type SendBackActions =
227
- | void
228
+ | [Action, Partial<Meta>][]
228
229
  | Action
229
230
  | Action[]
230
- | [Action, Partial<Meta>][]
231
+ | void
231
232
 
232
233
  /**
233
234
  * The authentication callback.
@@ -278,7 +279,7 @@ interface Resender<
278
279
  ctx: Context<Data, Headers>,
279
280
  action: Readonly<TypeAction>,
280
281
  meta: Readonly<ServerMeta>
281
- ): Resend | Promise<Resend>
282
+ ): Promise<Resend> | Resend
282
283
  }
283
284
 
284
285
  /**
@@ -298,7 +299,7 @@ interface Processor<
298
299
  ctx: Context<Data, Headers>,
299
300
  action: Readonly<TypeAction>,
300
301
  meta: Readonly<ServerMeta>
301
- ): void | Promise<void>
302
+ ): Promise<void> | void
302
303
  }
303
304
 
304
305
  /**
@@ -376,7 +377,7 @@ interface FilterCreator<
376
377
  ctx: ChannelContext<Data, ChannelParams, Headers>,
377
378
  action: Readonly<SubscribeAction>,
378
379
  meta: Readonly<ServerMeta>
379
- ): Promise<ChannelFilter<Headers>> | ChannelFilter<Headers> | void
380
+ ): ChannelFilter<Headers> | Promise<ChannelFilter<Headers>> | void
380
381
  }
381
382
 
382
383
  /**
@@ -397,7 +398,7 @@ interface ChannelLoader<
397
398
  ctx: ChannelContext<Data, ChannelParams, Headers>,
398
399
  action: Readonly<SubscribeAction>,
399
400
  meta: Readonly<ServerMeta>
400
- ): SendBackActions | Promise<SendBackActions>
401
+ ): Promise<SendBackActions> | SendBackActions
401
402
  }
402
403
 
403
404
  /**
@@ -454,8 +455,8 @@ type ActionCallbacks<
454
455
  accessAndProcess: Processor<TypeAction, Data, Headers>
455
456
  }
456
457
  ) & {
457
- resend?: Resender<TypeAction, Data, Headers>
458
458
  finally?: ActionFinally<TypeAction, Data, Headers>
459
+ resend?: Resender<TypeAction, Data, Headers>
459
460
  }
460
461
 
461
462
  type ChannelCallbacks<
@@ -498,68 +499,68 @@ interface CleanReporter {
498
499
 
499
500
  interface AuthenticationReporter {
500
501
  connectionId: string
501
- subprotocol: string
502
502
  nodeId: string
503
+ subprotocol: string
503
504
  }
504
505
 
505
506
  interface ReportersArguments {
506
507
  add: ActionReporter
507
- useless: ActionReporter
508
+ authenticated: AuthenticationReporter
508
509
  clean: CleanReporter
509
- error: {
510
- err: Error
511
- fatal?: true
512
- actionId?: ID
513
- nodeId?: string
514
- connectionId?: string
515
- }
516
510
  clientError: {
511
+ connectionId?: string
517
512
  err: Error
518
513
  nodeId?: string
519
- connectionId?: string
520
514
  }
521
515
  connect: {
522
516
  connectionId: string
523
517
  ipAddress: string
524
518
  }
519
+ denied: CleanReporter
520
+ destroy: void
525
521
  disconnect: {
522
+ connectionId?: string
526
523
  nodeId?: string
524
+ }
525
+ error: {
526
+ actionId?: ID
527
527
  connectionId?: string
528
+ err: Error
529
+ fatal?: true
530
+ nodeId?: string
528
531
  }
529
- destroy: void
530
- unknownType: {
531
- type: string
532
- actionId: ID
532
+ listen: {
533
+ backend: string
534
+ cert: boolean
535
+ controlMask: string
536
+ controlSecret: string
537
+ environment: 'development' | 'production'
538
+ host: string
539
+ loguxServer: string
540
+ nodeId: string
541
+ notes: object
542
+ port: string
543
+ redis: string
544
+ server: boolean
545
+ subprotocol: string
546
+ supports: string
533
547
  }
534
- wrongChannel: SubscriptionReporter
535
548
  processed: {
536
549
  actionId: ID
537
550
  latency: number
538
551
  }
539
552
  subscribed: SubscriptionReporter
540
- unsubscribed: SubscriptionReporter
541
- denied: CleanReporter
542
- authenticated: AuthenticationReporter
543
553
  unauthenticated: AuthenticationReporter
554
+ unknownType: {
555
+ actionId: ID
556
+ type: string
557
+ }
558
+ unsubscribed: SubscriptionReporter
559
+ useless: ActionReporter
560
+ wrongChannel: SubscriptionReporter
544
561
  zombie: {
545
562
  nodeId: string
546
563
  }
547
- listen: {
548
- controlSecret: string
549
- controlMask: string
550
- loguxServer: string
551
- environment: 'production' | 'development'
552
- subprotocol: string
553
- supports: string
554
- backend: string
555
- server: boolean
556
- nodeId: string
557
- redis: string
558
- notes: object
559
- cert: boolean
560
- host: string
561
- port: string
562
- }
563
564
  }
564
565
 
565
566
  export interface Reporter {
@@ -570,42 +571,42 @@ export interface Reporter {
570
571
  }
571
572
 
572
573
  export type Resend =
573
- | string
574
- | string[]
575
574
  | {
576
575
  channel?: string
577
576
  channels?: string[]
578
- user?: string
579
- users?: string[]
580
577
  client?: string
581
578
  clients?: string[]
579
+ excludeClients?: string[]
582
580
  node?: string
583
581
  nodes?: string[]
584
- excludeClients?: string[]
582
+ user?: string
583
+ users?: string[]
585
584
  }
585
+ | string
586
+ | string[]
586
587
 
587
588
  export interface Logger {
588
- info(details: object, message: string): void
589
- warn(details: object, message: string): void
590
589
  error(details: object, message: string): void
591
590
  fatal(details: object, message: string): void
591
+ info(details: object, message: string): void
592
+ warn(details: object, message: string): void
592
593
  }
593
594
 
594
595
  interface Response {
596
+ body: string
595
597
  header?: {
596
598
  [name: string]: string
597
599
  }
598
- body: string
599
600
  }
600
601
 
601
602
  interface GetProcessor {
603
+ request(request: object): Promise<Response> | Response
602
604
  safe?: boolean
603
- request(request: object): Response | Promise<Response>
604
605
  }
605
606
 
606
607
  interface PostProcessor {
607
- isValid(command: object): boolean
608
608
  command(command: object, request: object): Promise<void>
609
+ isValid(command: object): boolean
609
610
  }
610
611
 
611
612
  /**
@@ -633,18 +634,30 @@ export class BaseServer<
633
634
  ServerLog extends Log = Log<ServerMeta>
634
635
  > {
635
636
  /**
636
- * @param opts Server options.
637
+ * Connected client by client ID.
638
+ *
639
+ * Do not rely on this data, when you have multiple Logux servers.
640
+ * Each server will have a different list.
637
641
  */
638
- constructor(opts: BaseServerOptions)
642
+ clientIds: Map<string, ServerClient>
639
643
 
640
644
  /**
641
- * Server options.
645
+ * Connected clients.
642
646
  *
643
647
  * ```js
644
- * console.log('Server options', server.options.subprotocol)
648
+ * for (let client of server.connected.values()) {
649
+ * console.log(client.remoteAddress)
650
+ * }
645
651
  * ```
646
652
  */
647
- options: BaseServerOptions
653
+ connected: Map<string, ServerClient>
654
+
655
+ /**
656
+ * Add callback to internal HTTP server.
657
+ */
658
+ controls: {
659
+ [path: string]: GetProcessor | PostProcessor
660
+ }
648
661
 
649
662
  /**
650
663
  * Production or development mode.
@@ -655,16 +668,7 @@ export class BaseServer<
655
668
  * }
656
669
  * ```
657
670
  */
658
- env: 'production' | 'development'
659
-
660
- /**
661
- * Server unique ID.
662
- *
663
- * ```js
664
- * console.log('Error was raised on ' + server.nodeId)
665
- * ```
666
- */
667
- nodeId: string
671
+ env: 'development' | 'production'
668
672
 
669
673
  /**
670
674
  * Server actions log.
@@ -676,23 +680,33 @@ export class BaseServer<
676
680
  log: ServerLog
677
681
 
678
682
  /**
679
- * Connected clients.
683
+ * Console for custom log records. It uses `pino` API.
680
684
  *
681
685
  * ```js
682
- * for (let client of server.connected.values()) {
683
- * console.log(client.remoteAddress)
684
- * }
686
+ * server.on('connected', client => {
687
+ * server.logger.info(
688
+ * { domain: client.httpHeaders.domain },
689
+ * 'Client domain'
690
+ * )
691
+ * })
685
692
  * ```
686
693
  */
687
- connected: Map<string, ServerClient>
694
+ logger: {
695
+ debug: LogFn
696
+ error: LogFn
697
+ fatal: LogFn
698
+ info: LogFn
699
+ warn: LogFn
700
+ }
688
701
 
689
702
  /**
690
- * Connected client by client ID.
703
+ * Server unique ID.
691
704
  *
692
- * Do not rely on this data, when you have multiple Logux servers.
693
- * Each server will have a different list.
705
+ * ```js
706
+ * console.log('Error was raised on ' + server.nodeId)
707
+ * ```
694
708
  */
695
- clientIds: Map<string, ServerClient>
709
+ nodeId: string
696
710
 
697
711
  /**
698
712
  * Connected client by node ID.
@@ -703,12 +717,13 @@ export class BaseServer<
703
717
  nodeIds: Map<string, ServerClient>
704
718
 
705
719
  /**
706
- * Connected client by user ID.
720
+ * Server options.
707
721
  *
708
- * Do not rely on this data, when you have multiple Logux servers.
709
- * Each server will have a different list.
722
+ * ```js
723
+ * console.log('Server options', server.options.subprotocol)
724
+ * ```
710
725
  */
711
- userIds: Map<string, ServerClient[]>
726
+ options: BaseServerOptions
712
727
 
713
728
  /**
714
729
  * Clients subscribed to some channel.
@@ -726,31 +741,30 @@ export class BaseServer<
726
741
  }
727
742
 
728
743
  /**
729
- * Add callback to internal HTTP server.
744
+ * Connected client by user ID.
745
+ *
746
+ * Do not rely on this data, when you have multiple Logux servers.
747
+ * Each server will have a different list.
730
748
  */
731
- controls: {
732
- [path: string]: GetProcessor | PostProcessor
733
- }
749
+ userIds: Map<string, ServerClient[]>
734
750
 
735
751
  /**
736
- * Console for custom log records. It uses `pino` API.
752
+ * @param opts Server options.
753
+ */
754
+ constructor(opts: BaseServerOptions)
755
+
756
+ /**
757
+ * Add new client for server. You should call this method manually
758
+ * mostly for test purposes.
737
759
  *
738
760
  * ```js
739
- * server.on('connected', client => {
740
- * server.logger.info(
741
- * { domain: client.httpHeaders.domain },
742
- * 'Client domain'
743
- * )
744
- * })
761
+ * server.addClient(test.right)
745
762
  * ```
763
+ *
764
+ * @param connection Logux connection to client.
765
+ * @returns Client ID.
746
766
  */
747
- logger: {
748
- fatal: LogFn
749
- error: LogFn
750
- warn: LogFn
751
- info: LogFn
752
- debug: LogFn
753
- }
767
+ addClient(connection: ServerConnection): number
754
768
 
755
769
  /**
756
770
  * Set authenticate function. It will receive client credentials
@@ -768,11 +782,75 @@ export class BaseServer<
768
782
  auth(authenticator: Authenticator<Headers>): void
769
783
 
770
784
  /**
771
- * Start WebSocket server and listen for clients.
785
+ * Define the channel.
772
786
  *
773
- * @returns When the server has been bound.
787
+ * ```js
788
+ * server.channel('user/:id', {
789
+ * access (ctx, action, meta) {
790
+ * return ctx.params.id === ctx.userId
791
+ * }
792
+ * filter (ctx, action, meta) {
793
+ * return (otherCtx, otherAction, otherMeta) => {
794
+ * return !action.hidden
795
+ * }
796
+ * }
797
+ * async load (ctx, action, meta) {
798
+ * const user = await db.loadUser(ctx.params.id)
799
+ * ctx.sendBack({ type: 'USER_NAME', name: user.name })
800
+ * }
801
+ * })
802
+ * ```
803
+ *
804
+ * @param pattern Pattern for channel name.
805
+ * @param callbacks Callback during subscription process.
774
806
  */
775
- listen(): Promise<void>
807
+ channel<
808
+ ChannelParams extends object = {},
809
+ Data extends object = {},
810
+ SubscribeAction extends LoguxSubscribeAction = LoguxSubscribeAction
811
+ >(
812
+ pattern: string,
813
+ callbacks: ChannelCallbacks<SubscribeAction, Data, ChannelParams, Headers>
814
+ ): void
815
+
816
+ /**
817
+ * @param pattern Regular expression for channel name.
818
+ * @param callbacks Callback during subscription process.
819
+ */
820
+ channel<
821
+ ChannelParams extends string[] = string[],
822
+ Data extends object = {},
823
+ SubscribeAction extends LoguxSubscribeAction = LoguxSubscribeAction
824
+ >(
825
+ pattern: RegExp,
826
+ callbacks: ChannelCallbacks<SubscribeAction, Data, ChannelParams, Headers>
827
+ ): void
828
+
829
+ /**
830
+ * Send runtime error stacktrace to all clients.
831
+ *
832
+ * ```js
833
+ * process.on('uncaughtException', e => {
834
+ * server.debugError(e)
835
+ * })
836
+ * ```
837
+ *
838
+ * @param error Runtime error instance.
839
+ */
840
+ debugError(error: Error): void
841
+
842
+ /**
843
+ * Stop server and unbind all listeners.
844
+ *
845
+ * ```js
846
+ * afterEach(() => {
847
+ * testServer.destroy()
848
+ * })
849
+ * ```
850
+ *
851
+ * @returns Promise when all listeners will be removed.
852
+ */
853
+ destroy(): Promise<void>
776
854
 
777
855
  /**
778
856
  * Add non-WebSocket HTTP request processor.
@@ -794,6 +872,59 @@ export class BaseServer<
794
872
  */
795
873
  http(listener: (req: IncomingMessage, res: ServerResponse) => void): void
796
874
 
875
+ /**
876
+ * Start WebSocket server and listen for clients.
877
+ *
878
+ * @returns When the server has been bound.
879
+ */
880
+ listen(): Promise<void>
881
+
882
+ /**
883
+ * @param event The event name.
884
+ * @param listener Event listener.
885
+ */
886
+ on(event: 'subscriptionCancelled', listener: () => void): Unsubscribe
887
+
888
+ /**
889
+ * @param event The event name.
890
+ * @param listener Subscription listener.
891
+ */
892
+ on(
893
+ event: 'subscribing',
894
+ listener: (action: LoguxSubscribeAction, meta: Readonly<ServerMeta>) => void
895
+ ): Unsubscribe
896
+
897
+ /**
898
+ * @param event The event name.
899
+ * @param listener Processing listener.
900
+ */
901
+ on(
902
+ event: 'backendGranted' | 'backendProcessed' | 'processed',
903
+ listener: (
904
+ action: Action,
905
+ meta: Readonly<ServerMeta>,
906
+ latencyMilliseconds: number
907
+ ) => void
908
+ ): Unsubscribe
909
+
910
+ /**
911
+ * @param event The event name.
912
+ * @param listener Action listener.
913
+ */
914
+ on(
915
+ event: 'add' | 'backendSent' | 'clean',
916
+ listener: (action: Action, meta: Readonly<ServerMeta>) => void
917
+ ): Unsubscribe
918
+
919
+ /**
920
+ * @param event The event name.
921
+ * @param listener Client listener.
922
+ */
923
+ on(
924
+ event: 'connected' | 'disconnected',
925
+ listener: (client: ServerClient) => void
926
+ ): Unsubscribe
927
+
797
928
  /**
798
929
  * Subscribe for synchronization events. It implements nanoevents API.
799
930
  * Supported events:
@@ -826,7 +957,7 @@ export class BaseServer<
826
957
  * @returns Unbind listener from event.
827
958
  */
828
959
  on(
829
- event: 'fatal' | 'clientError',
960
+ event: 'clientError' | 'fatal',
830
961
  listener: (err: Error) => void
831
962
  ): Unsubscribe
832
963
 
@@ -839,15 +970,6 @@ export class BaseServer<
839
970
  listener: (err: Error, action: Action, meta: Readonly<ServerMeta>) => void
840
971
  ): Unsubscribe
841
972
 
842
- /**
843
- * @param event The event name.
844
- * @param listener Client listener.
845
- */
846
- on(
847
- event: 'connected' | 'disconnected',
848
- listener: (client: ServerClient) => void
849
- ): Unsubscribe
850
-
851
973
  /**
852
974
  * @param event The event name.
853
975
  * @param listener Client listener.
@@ -857,15 +979,6 @@ export class BaseServer<
857
979
  listener: (client: ServerClient, latencyMilliseconds: number) => void
858
980
  ): Unsubscribe
859
981
 
860
- /**
861
- * @param event The event name.
862
- * @param listener Action listener.
863
- */
864
- on(
865
- event: 'add' | 'clean' | 'backendSent',
866
- listener: (action: Action, meta: Readonly<ServerMeta>) => void
867
- ): Unsubscribe
868
-
869
982
  /**
870
983
  * @param event The event name.
871
984
  * @param listener Action listener.
@@ -875,19 +988,6 @@ export class BaseServer<
875
988
  listener: (action: Action, meta: ServerMeta) => void
876
989
  ): Unsubscribe
877
990
 
878
- /**
879
- * @param event The event name.
880
- * @param listener Processing listener.
881
- */
882
- on(
883
- event: 'processed' | 'backendGranted' | 'backendProcessed',
884
- listener: (
885
- action: Action,
886
- meta: Readonly<ServerMeta>,
887
- latencyMilliseconds: number
888
- ) => void
889
- ): Unsubscribe
890
-
891
991
  /**
892
992
  * @param event The event name.
893
993
  * @param listener Subscription listener.
@@ -901,15 +1001,6 @@ export class BaseServer<
901
1001
  ) => void
902
1002
  ): Unsubscribe
903
1003
 
904
- /**
905
- * @param event The event name.
906
- * @param listener Subscription listener.
907
- */
908
- on(
909
- event: 'subscribing',
910
- listener: (action: LoguxSubscribeAction, meta: Readonly<ServerMeta>) => void
911
- ): Unsubscribe
912
-
913
1004
  /**
914
1005
  * @param event The event name.
915
1006
  * @param listener Subscription listener.
@@ -922,12 +1013,6 @@ export class BaseServer<
922
1013
  ) => void
923
1014
  ): Unsubscribe
924
1015
 
925
- /**
926
- * @param event The event name.
927
- * @param listener Event listener.
928
- */
929
- on(event: 'subscriptionCancelled', listener: () => void): Unsubscribe
930
-
931
1016
  /**
932
1017
  * @param event The event name.
933
1018
  * @param listener Report listener.
@@ -935,52 +1020,26 @@ export class BaseServer<
935
1020
  on(event: 'report', listener: Reporter): Unsubscribe
936
1021
 
937
1022
  /**
938
- * Stop server and unbind all listeners.
939
- *
940
- * ```js
941
- * afterEach(() => {
942
- * testServer.destroy()
943
- * })
944
- * ```
945
- *
946
- * @returns Promise when all listeners will be removed.
947
- */
948
- destroy(): Promise<void>
949
-
950
- /**
951
- * Define action type’s callbacks.
1023
+ * Set callbacks for unknown channel subscription.
952
1024
  *
953
- * ```js
954
- * server.type('CHANGE_NAME', {
955
- * access (ctx, action, meta) {
956
- * return action.user === ctx.userId
957
- * },
958
- * resend (ctx, action) {
959
- * return `user/${ action.user }`
960
- * }
961
- * process (ctx, action, meta) {
962
- * if (isFirstOlder(lastNameChange(action.user), meta)) {
963
- * return db.changeUserName({ id: action.user, name: action.name })
1025
+ *```js
1026
+ * server.otherChannel({
1027
+ * async access (ctx, action, meta) {
1028
+ * const res = await phpBackend.checkChannel(ctx.params[0], ctx.userId)
1029
+ * if (res.code === 404) {
1030
+ * this.wrongChannel(action, meta)
1031
+ * return false
1032
+ * } else {
1033
+ * return response.body === 'granted'
964
1034
  * }
965
1035
  * }
966
1036
  * })
967
1037
  * ```
968
1038
  *
969
- * @param name The action’s type or action’s type matching rule as RegExp..
970
- * @param callbacks Callbacks for actions with this type.
971
- */
972
- type<TypeAction extends Action = AnyAction, Data extends object = {}>(
973
- name: TypeAction['type'] | RegExp,
974
- callbacks: ActionCallbacks<TypeAction, Data, Headers>
975
- ): void
976
-
977
- /**
978
- * @param actionCreator Action creator function.
979
- * @param callbacks Callbacks for action created by creator.
1039
+ * @param callbacks Callback during subscription process.
980
1040
  */
981
- type<Creator extends AbstractActionCreator, Data extends object = {}>(
982
- actionCreator: Creator,
983
- callbacks: ActionCallbacks<ReturnType<Creator>, Data, Headers>
1041
+ otherChannel<Data extends object = {}>(
1042
+ callbacks: ChannelCallbacks<LoguxSubscribeAction, Data, [string], Headers>
984
1043
  ): void
985
1044
 
986
1045
  /**
@@ -1013,74 +1072,6 @@ export class BaseServer<
1013
1072
  callbacks: ActionCallbacks<Action, Data, Headers>
1014
1073
  ): void
1015
1074
 
1016
- /**
1017
- * Define the channel.
1018
- *
1019
- * ```js
1020
- * server.channel('user/:id', {
1021
- * access (ctx, action, meta) {
1022
- * return ctx.params.id === ctx.userId
1023
- * }
1024
- * filter (ctx, action, meta) {
1025
- * return (otherCtx, otherAction, otherMeta) => {
1026
- * return !action.hidden
1027
- * }
1028
- * }
1029
- * async load (ctx, action, meta) {
1030
- * const user = await db.loadUser(ctx.params.id)
1031
- * ctx.sendBack({ type: 'USER_NAME', name: user.name })
1032
- * }
1033
- * })
1034
- * ```
1035
- *
1036
- * @param pattern Pattern for channel name.
1037
- * @param callbacks Callback during subscription process.
1038
- */
1039
- channel<
1040
- ChannelParams extends object = {},
1041
- Data extends object = {},
1042
- SubscribeAction extends LoguxSubscribeAction = LoguxSubscribeAction
1043
- >(
1044
- pattern: string,
1045
- callbacks: ChannelCallbacks<SubscribeAction, Data, ChannelParams, Headers>
1046
- ): void
1047
-
1048
- /**
1049
- * @param pattern Regular expression for channel name.
1050
- * @param callbacks Callback during subscription process.
1051
- */
1052
- channel<
1053
- ChannelParams extends string[] = string[],
1054
- Data extends object = {},
1055
- SubscribeAction extends LoguxSubscribeAction = LoguxSubscribeAction
1056
- >(
1057
- pattern: RegExp,
1058
- callbacks: ChannelCallbacks<SubscribeAction, Data, ChannelParams, Headers>
1059
- ): void
1060
-
1061
- /**
1062
- * Set callbacks for unknown channel subscription.
1063
- *
1064
- *```js
1065
- * server.otherChannel({
1066
- * async access (ctx, action, meta) {
1067
- * const res = await phpBackend.checkChannel(ctx.params[0], ctx.userId)
1068
- * if (res.code === 404) {
1069
- * this.wrongChannel(action, meta)
1070
- * return false
1071
- * } else {
1072
- * return response.body === 'granted'
1073
- * }
1074
- * }
1075
- * })
1076
- * ```
1077
- *
1078
- * @param callbacks Callback during subscription process.
1079
- */
1080
- otherChannel<Data extends object = {}>(
1081
- callbacks: ChannelCallbacks<LoguxSubscribeAction, Data, [string], Headers>
1082
- ): void
1083
-
1084
1075
  /**
1085
1076
  * Add new action to the server and return the Promise until it will be
1086
1077
  * resend to clients and processed.
@@ -1094,41 +1085,6 @@ export class BaseServer<
1094
1085
  meta?: Partial<ServerMeta>
1095
1086
  ): Promise<Readonly<ServerMeta>>
1096
1087
 
1097
- /**
1098
- * Undo action from client.
1099
- *
1100
- * ```js
1101
- * if (couldNotFixConflict(action, meta)) {
1102
- * server.undo(action, meta)
1103
- * }
1104
- * ```
1105
- *
1106
- * @param action The original action to undo.
1107
- * @param meta The action’s metadata.
1108
- * @param reason Optional code for reason. Default is `'error'`.
1109
- * @param extra Extra fields to `logux/undo` action.
1110
- * @returns When action was saved to the log.
1111
- */
1112
- undo(
1113
- action: Action,
1114
- meta: ServerMeta,
1115
- reason?: string,
1116
- extra?: object
1117
- ): Promise<void>
1118
-
1119
- /**
1120
- * Send runtime error stacktrace to all clients.
1121
- *
1122
- * ```js
1123
- * process.on('uncaughtException', e => {
1124
- * server.debugError(e)
1125
- * })
1126
- * ```
1127
- *
1128
- * @param error Runtime error instance.
1129
- */
1130
- debugError(error: Error): void
1131
-
1132
1088
  /**
1133
1089
  * Send action, received by other server, to all clients of current server.
1134
1090
  * This method is for multi-server configuration only.
@@ -1147,7 +1103,7 @@ export class BaseServer<
1147
1103
  * @param action New action.
1148
1104
  * @param meta Action’s metadata.
1149
1105
  */
1150
- sendAction(action: Action, meta: ServerMeta): void | Promise<void>
1106
+ sendAction(action: Action, meta: ServerMeta): Promise<void> | void
1151
1107
 
1152
1108
  /**
1153
1109
  * Send `logux/subscribed` if client was not already subscribed.
@@ -1162,17 +1118,62 @@ export class BaseServer<
1162
1118
  subscribe(nodeId: string, channel: string): void
1163
1119
 
1164
1120
  /**
1165
- * Add new client for server. You should call this method manually
1166
- * mostly for test purposes.
1121
+ * @param actionCreator Action creator function.
1122
+ * @param callbacks Callbacks for action created by creator.
1123
+ */
1124
+ type<Creator extends AbstractActionCreator, Data extends object = {}>(
1125
+ actionCreator: Creator,
1126
+ callbacks: ActionCallbacks<ReturnType<Creator>, Data, Headers>
1127
+ ): void
1128
+
1129
+ /**
1130
+ * Define action type’s callbacks.
1167
1131
  *
1168
1132
  * ```js
1169
- * server.addClient(test.right)
1133
+ * server.type('CHANGE_NAME', {
1134
+ * access (ctx, action, meta) {
1135
+ * return action.user === ctx.userId
1136
+ * },
1137
+ * resend (ctx, action) {
1138
+ * return `user/${ action.user }`
1139
+ * }
1140
+ * process (ctx, action, meta) {
1141
+ * if (isFirstOlder(lastNameChange(action.user), meta)) {
1142
+ * return db.changeUserName({ id: action.user, name: action.name })
1143
+ * }
1144
+ * }
1145
+ * })
1170
1146
  * ```
1171
1147
  *
1172
- * @param connection Logux connection to client.
1173
- * @returns Client ID.
1148
+ * @param name The action’s type or action’s type matching rule as RegExp..
1149
+ * @param callbacks Callbacks for actions with this type.
1174
1150
  */
1175
- addClient(connection: ServerConnection): number
1151
+ type<TypeAction extends Action = AnyAction, Data extends object = {}>(
1152
+ name: RegExp | TypeAction['type'],
1153
+ callbacks: ActionCallbacks<TypeAction, Data, Headers>
1154
+ ): void
1155
+
1156
+ /**
1157
+ * Undo action from client.
1158
+ *
1159
+ * ```js
1160
+ * if (couldNotFixConflict(action, meta)) {
1161
+ * server.undo(action, meta)
1162
+ * }
1163
+ * ```
1164
+ *
1165
+ * @param action The original action to undo.
1166
+ * @param meta The action’s metadata.
1167
+ * @param reason Optional code for reason. Default is `'error'`.
1168
+ * @param extra Extra fields to `logux/undo` action.
1169
+ * @returns When action was saved to the log.
1170
+ */
1171
+ undo(
1172
+ action: Action,
1173
+ meta: ServerMeta,
1174
+ reason?: string,
1175
+ extra?: object
1176
+ ): Promise<void>
1176
1177
 
1177
1178
  /**
1178
1179
  * If you receive action with unknown type, this method will mark this action