@eleven-am/pondsocket 0.1.55 → 0.1.57

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.
Files changed (71) hide show
  1. package/.eslintrc.json +387 -0
  2. package/dist/LICENSE +674 -0
  3. package/dist/README.md +139 -0
  4. package/{channel → dist/channel}/channel.js +5 -7
  5. package/{lobby → dist/lobby}/joinResponse.js +2 -2
  6. package/dist/package.json +51 -0
  7. package/{presence → dist/presence}/presence.js +16 -18
  8. package/{server → dist/server}/pondSocket.js +1 -1
  9. package/{subjects → dist/subjects}/subject.js +44 -0
  10. package/{types.d.ts → dist/types.d.ts} +0 -5
  11. package/jest.config.js +11 -0
  12. package/package.json +3 -3
  13. package/src/abstracts/abstractRequest.test.ts +49 -0
  14. package/src/abstracts/abstractRequest.ts +56 -0
  15. package/src/abstracts/abstractResponse.ts +26 -0
  16. package/src/abstracts/middleware.test.ts +75 -0
  17. package/src/abstracts/middleware.ts +50 -0
  18. package/src/channel/channel.test.ts +501 -0
  19. package/src/channel/channel.ts +305 -0
  20. package/src/channel/eventRequest.test.ts +37 -0
  21. package/src/channel/eventRequest.ts +27 -0
  22. package/src/channel/eventResponse.test.ts +249 -0
  23. package/src/channel/eventResponse.ts +172 -0
  24. package/src/client/channel.test.ts +799 -0
  25. package/src/client/channel.ts +342 -0
  26. package/src/client.ts +124 -0
  27. package/src/endpoint/endpoint.test.ts +825 -0
  28. package/src/endpoint/endpoint.ts +304 -0
  29. package/src/endpoint/response.ts +106 -0
  30. package/src/enums.ts +52 -0
  31. package/src/errors/pondError.ts +32 -0
  32. package/src/express.ts +58 -0
  33. package/src/index.ts +3 -0
  34. package/src/lobby/JoinRequest.test.ts +48 -0
  35. package/src/lobby/JoinResponse.test.ts +162 -0
  36. package/src/lobby/joinRequest.ts +32 -0
  37. package/src/lobby/joinResponse.ts +146 -0
  38. package/src/lobby/lobby.ts +182 -0
  39. package/src/matcher/matcher.test.ts +103 -0
  40. package/src/matcher/matcher.ts +105 -0
  41. package/src/node.ts +33 -0
  42. package/src/presence/presence.ts +127 -0
  43. package/src/presence/presenceEngine.test.ts +143 -0
  44. package/src/server/pondSocket.ts +153 -0
  45. package/src/subjects/subject.test.ts +163 -0
  46. package/src/subjects/subject.ts +137 -0
  47. package/src/typedefs.d.ts +451 -0
  48. package/src/types.d.ts +89 -0
  49. package/tsconfig.build.json +7 -0
  50. package/tsconfig.json +12 -0
  51. /package/{abstracts → dist/abstracts}/abstractRequest.js +0 -0
  52. /package/{abstracts → dist/abstracts}/abstractResponse.js +0 -0
  53. /package/{abstracts → dist/abstracts}/middleware.js +0 -0
  54. /package/{channel → dist/channel}/eventRequest.js +0 -0
  55. /package/{channel → dist/channel}/eventResponse.js +0 -0
  56. /package/{client → dist/client}/channel.js +0 -0
  57. /package/{client.d.ts → dist/client.d.ts} +0 -0
  58. /package/{client.js → dist/client.js} +0 -0
  59. /package/{endpoint → dist/endpoint}/endpoint.js +0 -0
  60. /package/{endpoint → dist/endpoint}/response.js +0 -0
  61. /package/{enums.js → dist/enums.js} +0 -0
  62. /package/{errors → dist/errors}/pondError.js +0 -0
  63. /package/{express.d.ts → dist/express.d.ts} +0 -0
  64. /package/{express.js → dist/express.js} +0 -0
  65. /package/{index.d.ts → dist/index.d.ts} +0 -0
  66. /package/{index.js → dist/index.js} +0 -0
  67. /package/{lobby → dist/lobby}/joinRequest.js +0 -0
  68. /package/{lobby → dist/lobby}/lobby.js +0 -0
  69. /package/{matcher → dist/matcher}/matcher.js +0 -0
  70. /package/{node.d.ts → dist/node.d.ts} +0 -0
  71. /package/{node.js → dist/node.js} +0 -0
@@ -0,0 +1,451 @@
1
+ import { Server as HTTPServer } from 'http';
2
+
3
+ import { WebSocketServer } from 'ws';
4
+
5
+ import {
6
+ UserPresences,
7
+ UserAssigns,
8
+ PondEvent,
9
+ PondAssigns,
10
+ PondMessage,
11
+ UserData,
12
+ PondPresence,
13
+ Unsubscribe,
14
+ PresencePayload,
15
+ PondPath,
16
+ JoinParams,
17
+ IncomingConnection,
18
+ // eslint-disable-next-line import/no-unresolved
19
+ } from './types';
20
+
21
+ export enum ChannelState {
22
+ IDLE = 'IDLE',
23
+ JOINING = 'JOINING',
24
+ JOINED = 'JOINED',
25
+ STALLED = 'STALLED',
26
+ CLOSED = 'CLOSED',
27
+ }
28
+
29
+ export declare class AbstractRequest<Path extends string> {
30
+ event: PondEvent<Path>;
31
+
32
+ channelNme: string;
33
+
34
+ assigns: UserAssigns;
35
+
36
+ presence: UserPresences;
37
+ }
38
+
39
+ export declare abstract class PondResponse {
40
+ /**
41
+ * @desc Rejects the request with the given error message
42
+ * @param message - the error message
43
+ * @param errorCode - the error code
44
+ * @param assigns - the data to assign to the client
45
+ */
46
+ abstract reject (message?: string, errorCode?: number, assigns?: PondAssigns): void;
47
+
48
+ /**
49
+ * @desc Emits a direct message to the client
50
+ * @param event - the event name
51
+ * @param payload - the payload to send
52
+ * @param assigns - the data to assign to the client
53
+ */
54
+ abstract send (event: string, payload: PondMessage, assigns?: PondAssigns): void;
55
+
56
+ /**
57
+ * @desc Accepts the request and optionally assigns data to the client
58
+ * @param assigns - the data to assign to the client
59
+ */
60
+ abstract accept (assigns?: PondAssigns): void;
61
+ }
62
+
63
+ export declare class EventRequest<Path extends string> extends AbstractRequest<Path> {
64
+ user: UserData;
65
+ }
66
+
67
+ export declare class EventResponse extends PondResponse {
68
+ /**
69
+ * @desc Accepts the request and optionally assigns data to the client
70
+ * @param assigns - the data to assign to the client
71
+ */
72
+ accept (assigns?: PondAssigns): EventResponse;
73
+
74
+ /**
75
+ * @desc Rejects the request and optionally assigns data to the client
76
+ * @param message - the error message
77
+ * @param errorCode - the error code
78
+ * @param assigns - the data to assign to the client
79
+ */
80
+ reject (message?: string, errorCode?: number, assigns?: PondAssigns): EventResponse;
81
+
82
+ /**
83
+ * @desc Emits a direct message to the client
84
+ * @param event - the event name
85
+ * @param payload - the payload to send
86
+ * @param assigns - the data to assign to the client
87
+ */
88
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): void;
89
+
90
+ /**
91
+ * @desc Sends a message to all clients in the channel
92
+ * @param event - the event to send
93
+ * @param payload - the payload to send
94
+ */
95
+ broadcast (event: string, payload: PondMessage): EventResponse;
96
+
97
+ /**
98
+ * @desc Sends a message to all clients in the channel except the client making the request
99
+ * @param event - the event to send
100
+ * @param payload - the payload to send
101
+ */
102
+ broadcastFromUser (event: string, payload: PondMessage): EventResponse;
103
+
104
+ /**
105
+ * @desc Sends a message to a set of clients in the channel
106
+ * @param event - the event to send
107
+ * @param payload - the payload to send
108
+ * @param userIds - the ids of the clients to send the message to
109
+ */
110
+ sendToUsers (event: string, payload: PondMessage, userIds: string[]): EventResponse;
111
+
112
+ /**
113
+ * @desc Tracks a user's presence in the channel
114
+ * @param presence - the initial presence data
115
+ * @param userId - the id of the user to track
116
+ */
117
+ trackPresence (presence: PondPresence, userId?: string): EventResponse;
118
+
119
+ /**
120
+ * @desc Updates a user's presence in the channel
121
+ * @param presence - the updated presence data
122
+ * @param userId - the id of the user to update
123
+ */
124
+ updatePresence (presence: PondPresence, userId?: string): EventResponse;
125
+
126
+ /**
127
+ * @desc Removes a user's presence from the channel
128
+ * @param userId - the id of the user to remove
129
+ */
130
+ unTrackPresence (userId?: string): EventResponse;
131
+
132
+ /**
133
+ * @desc Evicts a user from the channel
134
+ * @param reason - the reason for the eviction
135
+ * @param userId - the id of the user to evict,
136
+ */
137
+ evictUser (reason: string, userId?: string): void;
138
+
139
+ /**
140
+ * @desc Closes the channel from the server side for all clients
141
+ * @param reason - the reason for closing the channel
142
+ */
143
+ closeChannel (reason: string): void;
144
+ }
145
+
146
+ export declare class Channel {
147
+ /**
148
+ * @desc Gets the current connection state of the channel.
149
+ */
150
+ get channelState (): ChannelState;
151
+
152
+ /**
153
+ * @desc Connects to the channel.
154
+ */
155
+ join (): void;
156
+
157
+ /**
158
+ * @desc Disconnects from the channel.
159
+ */
160
+ leave (): void;
161
+
162
+ /**
163
+ * @desc Monitors the channel for messages.
164
+ * @param callback - The callback to call when a message is received.
165
+ */
166
+ onMessage (callback: (event: string, message: PondMessage) => void): Unsubscribe;
167
+
168
+ /**
169
+ * @desc Monitors the channel for messages.
170
+ * @param event - The event to monitor.
171
+ * @param callback - The callback to call when a message is received.
172
+ */
173
+ onMessageEvent (event: string, callback: (message: PondMessage) => void): Unsubscribe;
174
+
175
+ /**
176
+ * @desc Monitors the channel state of the channel.
177
+ * @param callback - The callback to call when the connection state changes.
178
+ */
179
+ onChannelStateChange (callback: (connected: ChannelState) => void): Unsubscribe;
180
+
181
+ /**
182
+ * @desc Detects when clients join the channel.
183
+ * @param callback - The callback to call when a client joins the channel.
184
+ */
185
+ onJoin (callback: (presence: PondPresence) => void): Unsubscribe;
186
+
187
+ /**
188
+ * @desc Detects when clients leave the channel.
189
+ * @param callback - The callback to call when a client leaves the channel.
190
+ */
191
+ onLeave (callback: (presence: PondPresence) => void): Unsubscribe;
192
+
193
+ /**
194
+ * @desc Detects when clients change their presence in the channel.
195
+ * @param callback - The callback to call when a client changes their presence in the channel.
196
+ */
197
+ onPresenceChange (callback: (presence: PresencePayload) => void): Unsubscribe;
198
+
199
+ /**
200
+ * @desc Sends a message to specific clients in the channel.
201
+ * @param event - The event to send.
202
+ * @param payload - The message to send.
203
+ * @param recipient - The clients to send the message to.
204
+ */
205
+ sendMessage (event: string, payload: PondMessage, recipient: string[]): void;
206
+
207
+ /**
208
+ * @desc Broadcasts a message to every other client in the channel except yourself.
209
+ * @param event - The event to send.
210
+ * @param payload - The message to send.
211
+ */
212
+ broadcastFrom (event: string, payload: PondMessage): void;
213
+
214
+ /**
215
+ * @desc Broadcasts a message to the channel, including yourself.
216
+ * @param event - The event to send.
217
+ * @param payload - The message to send.
218
+ */
219
+ broadcast (event: string, payload: PondMessage): void;
220
+
221
+ /**
222
+ * @desc Gets the current presence of the channel.
223
+ */
224
+ getPresence (): PondPresence[];
225
+
226
+ /**
227
+ * @desc Monitors the presence of the channel.
228
+ * @param callback - The callback to call when the presence changes.
229
+ */
230
+ onUsersChange (callback: (users: PondPresence[]) => void): Unsubscribe;
231
+
232
+ /**
233
+ * @desc Gets the current connection state of the channel.
234
+ */
235
+ isConnected (): boolean;
236
+
237
+ /**
238
+ * @desc Monitors the connection state of the channel.
239
+ * @param callback - The callback to call when the connection state changes.
240
+ */
241
+ onConnectionChange (callback: (connected: boolean) => void): Unsubscribe;
242
+ }
243
+
244
+ export declare class Endpoint {
245
+ /**
246
+ * @desc Adds a new PondChannel to this path on this endpoint
247
+ * @param path - The path to add the channel to
248
+ * @param handler - The handler to use to authenticate the client
249
+ *
250
+ * @example
251
+ * const channel = endpoint.createChannel('/chat', (request, response) => {
252
+ * if (request.user.assigns.admin)
253
+ * response.accept();
254
+ *
255
+ * else
256
+ * response.reject('You are not an admin', 403);
257
+ * });
258
+ */
259
+ createChannel<Path extends string> (path: PondPath<Path>, handler: (request: JoinRequest<Path>, response: JoinResponse) => void | Promise<void>): PondChannel;
260
+
261
+ /**
262
+ * @desc Broadcasts a message to all clients connected to this endpoint
263
+ * @param event - The event to broadcast
264
+ * @param payload - The payload to broadcast
265
+ */
266
+ broadcast (event: string, payload: PondMessage): void;
267
+
268
+ /**
269
+ * @desc Closes specific clients connected to this endpoint
270
+ * @param clientIds - The id for the client / clients to close
271
+ */
272
+ closeConnection (clientIds: string | string[]): void;
273
+ }
274
+
275
+ export declare class JoinRequest<Path extends string> extends AbstractRequest<Path> {
276
+ joinParams: JoinParams;
277
+
278
+ user: UserData;
279
+ }
280
+
281
+ export declare class JoinResponse extends PondResponse {
282
+ #private;
283
+
284
+ /**
285
+ * @desc Accepts the request and optionally assigns data to the client
286
+ * @param assigns - the data to assign to the client
287
+ */
288
+ accept (assigns?: PondAssigns): JoinResponse;
289
+
290
+ /**
291
+ * @desc Rejects the request and optionally assigns data to the client
292
+ * @param message - the error message
293
+ * @param errorCode - the error code
294
+ */
295
+ reject (message?: string, errorCode?: number): JoinResponse;
296
+
297
+ /**
298
+ * @desc Emits a direct message to the client
299
+ * @param event - the event name
300
+ * @param payload - the payload to send
301
+ * @param assigns - the data to assign to the client
302
+ */
303
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): this;
304
+
305
+ /**
306
+ * @desc Emits a message to all clients in the channel
307
+ * @param event - the event name
308
+ * @param payload - the payload to send
309
+ */
310
+ broadcast (event: string, payload: PondMessage): JoinResponse;
311
+
312
+ /**
313
+ * @desc Emits a message to all clients in the channel except the sender
314
+ * @param event - the event name
315
+ * @param payload - the payload to send
316
+ */
317
+ broadcastFromUser (event: string, payload: PondMessage): JoinResponse;
318
+
319
+ /**
320
+ * @desc Emits a message to a specific set of clients
321
+ * @param event - the event name
322
+ * @param payload - the payload to send
323
+ * @param userIds - the ids of the clients to send the message to
324
+ */
325
+ sendToUsers (event: string, payload: PondMessage, userIds: string[]): JoinResponse;
326
+
327
+ /**
328
+ * @desc tracks the presence of a client
329
+ * @param presence - the presence data to track
330
+ */
331
+ trackPresence (presence: PondPresence): JoinResponse;
332
+ }
333
+
334
+ export declare class ConnectionResponse extends PondResponse {
335
+ /**
336
+ * @desc Accepts the request and optionally assigns data to the client
337
+ * @param assigns - the data to assign to the client
338
+ */
339
+ accept (assigns?: PondAssigns): void;
340
+
341
+ /**
342
+ * @desc Rejects the request with the given error message
343
+ * @param message - the error message
344
+ * @param errorCode - the error code
345
+ */
346
+ reject (message?: string, errorCode?: number): void;
347
+
348
+ /**
349
+ * @desc Emits a direct message to the client
350
+ * @param event - the event name
351
+ * @param payload - the payload to send
352
+ * @param assigns - the data to assign to the client
353
+ */
354
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): void;
355
+ }
356
+
357
+ export declare class PondChannel {
358
+ /**
359
+ * @desc Handles an event request made by a user
360
+ * @param event - The event to listen for
361
+ * @param handler - The handler to execute when the event is received
362
+ * @example
363
+ * pond.onEvent('echo', (request, response) => {
364
+ * response.send('echo', {
365
+ * message: request.event.payload,
366
+ * });
367
+ * });
368
+ */
369
+ onEvent<Event extends string> (event: PondPath<Event>, handler: (request: EventRequest<Event>, response: EventResponse) => void | Promise<void>): void;
370
+
371
+ /**
372
+ * @desc Broadcasts a message to all users in a channel
373
+ * @param event - The event to broadcast
374
+ * @param payload - The payload to send
375
+ * @param channelName - The channel to broadcast to (if not specified, broadcast to all channels)
376
+ * @example
377
+ * pond.broadcast('echo', {
378
+ * message: 'Hello World',
379
+ * timestamp: Date.now(),
380
+ * channel: 'my_channel',
381
+ *});
382
+ */
383
+ broadcast (event: string, payload: PondMessage, channelName?: string): void;
384
+ }
385
+
386
+ export declare class PondSocket {
387
+ constructor (server?: HTTPServer, socketServer?: WebSocketServer);
388
+
389
+ /**
390
+ * @desc Specifies the port to listen on
391
+ * @param args - the arguments to pass to the server
392
+ */
393
+ listen (...args: any[]): HTTPServer<typeof import('http').IncomingMessage, typeof import('http').ServerResponse>;
394
+
395
+ /**
396
+ * @desc Closes the server
397
+ * @param callback - the callback to call when the server is closed
398
+ */
399
+ close (callback?: () => void): HTTPServer<typeof import('http').IncomingMessage, typeof import('http').ServerResponse>;
400
+
401
+ /**
402
+ * @desc Accepts a new socket upgrade request on the provided endpoint using the handler function to authenticate the socket
403
+ * @param path - the pattern to accept || can also be a regex
404
+ * @param handler - the handler function to authenticate the socket
405
+ * @example
406
+ * const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
407
+ * const token = req.query.token;
408
+ * if (!token)
409
+ * return res.reject('No token provided');
410
+ * res.accept({
411
+ * assign: {
412
+ * token
413
+ * }
414
+ * });
415
+ * })
416
+ */
417
+ createEndpoint<Path extends string> (path: PondPath<Path>, handler: (request: IncomingConnection<Path>, response: ConnectionResponse) => void | Promise<void>): Endpoint;
418
+ }
419
+
420
+ export declare class PondClient {
421
+ constructor (endpoint: string, params?: Record<string, any>);
422
+
423
+ /**
424
+ * @desc Connects to the server and returns the socket.
425
+ */
426
+ connect (backoff?: number): void;
427
+
428
+ /**
429
+ * @desc Returns the current state of the socket.
430
+ */
431
+ getState (): boolean;
432
+
433
+ /**
434
+ * @desc Disconnects the socket.
435
+ */
436
+ disconnect (): void;
437
+
438
+ /**
439
+ * @desc Creates a channel with the given name and params.
440
+ * @param name - The name of the channel.
441
+ * @param params - The params to send to the server.
442
+ */
443
+ createChannel (name: string, params?: JoinParams): Channel;
444
+
445
+ /**
446
+ * @desc Subscribes to the connection state.
447
+ * @param callback - The callback to call when the state changes.
448
+ */
449
+ onConnectionChange (callback: (state: boolean) => void): Unsubscribe;
450
+ }
451
+
package/src/types.d.ts ADDED
@@ -0,0 +1,89 @@
1
+ import { IncomingHttpHeaders } from 'http';
2
+
3
+ import { PresenceEventTypes, ChannelReceiver, ClientActions } from './enums';
4
+
5
+ export type Unsubscribe = () => void;
6
+
7
+ type IsParam<Path> = Path extends `:${infer Param}` ? Param : never;
8
+
9
+ type FilteredParams<Path> = Path extends `${infer First}/${infer Second}`
10
+ ? IsParam<First> | FilteredParams<Second>
11
+ : IsParam<Path>
12
+
13
+ export type Params<Path> = {
14
+ [Key in FilteredParams<Path>]: string
15
+ }
16
+
17
+ export type PondPath<Path extends string> = Path | RegExp;
18
+
19
+ export type EventParams<Path> = {
20
+ query: Record<string, string>;
21
+ params: Params<Path>;
22
+ }
23
+
24
+ type Primitives = number | string | boolean | null | undefined;
25
+
26
+ type PondObject = {
27
+ [key: string]: Primitives | PondObject | PondObject[];
28
+ }
29
+
30
+ export type PondPresence = PondObject;
31
+ export type PondMessage = PondObject;
32
+ export type PondAssigns = PondObject;
33
+ export type JoinParams = PondObject;
34
+
35
+ export interface PresencePayload extends PondObject {
36
+ changed: PondPresence;
37
+ presence: PondPresence[];
38
+ }
39
+
40
+ export interface UserPresences {
41
+ [userId: string]: PondPresence;
42
+ }
43
+
44
+ export interface UserAssigns {
45
+ [userId: string]: PondAssigns;
46
+ }
47
+
48
+ export type ChannelReceivers = ChannelReceiver | string[];
49
+
50
+ export interface Event {
51
+ action: 'SYSTEM' | 'BROADCAST' | 'ERROR';
52
+ event: string;
53
+ payload: PondMessage;
54
+ channelName: string;
55
+ }
56
+
57
+ interface PresenceEventMessage {
58
+ action: 'PRESENCE';
59
+ event: PresenceEventTypes;
60
+ channelName: string;
61
+ payload: PresencePayload;
62
+ }
63
+
64
+ export type ChannelEvent = Event | PresenceEventMessage;
65
+
66
+ export type PondEvent<Path> = EventParams<Path> & {
67
+ payload: PondMessage;
68
+ event: string;
69
+ }
70
+
71
+ export type IncomingConnection<Path> = EventParams<Path> & {
72
+ id: string;
73
+ headers: IncomingHttpHeaders;
74
+ address: string;
75
+ }
76
+
77
+ export interface ClientMessage {
78
+ action: ClientActions;
79
+ channelName: string;
80
+ event: string;
81
+ payload: PondMessage;
82
+ addresses?: ChannelReceivers;
83
+ }
84
+
85
+ export interface UserData {
86
+ assigns: PondAssigns;
87
+ presence: PondPresence;
88
+ id: string;
89
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": [
4
+ "src/**/*.spec.ts",
5
+ "src/**/*.test.ts"
6
+ ]
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2015",
4
+ "module": "commonjs",
5
+ "declaration": false,
6
+ "outDir": "./dist",
7
+ "esModuleInterop": true,
8
+ "strict": true,
9
+ },
10
+ "include": ["src/**/*"],
11
+ "exclude": ["node_modules", "**/__tests__/*"]
12
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes