@eleven-am/pondsocket 0.1.11 → 0.1.13

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 (90) hide show
  1. package/dist/client/channel.js +200 -0
  2. package/dist/client/index.d.ts +122 -0
  3. package/{pondClient/socket.js → dist/client/index.js} +30 -44
  4. package/dist/express/index.d.ts +36 -0
  5. package/dist/express/index.js +16 -0
  6. package/dist/index.d.ts +340 -0
  7. package/dist/index.js +4 -0
  8. package/dist/server/abstracts/abstractRequest.js +40 -0
  9. package/dist/server/abstracts/abstractRequest.test.js +41 -0
  10. package/dist/server/abstracts/abstractResponse.js +6 -0
  11. package/dist/server/abstracts/middleware.js +38 -0
  12. package/dist/server/abstracts/middleware.test.js +70 -0
  13. package/dist/server/channel/channelEngine.js +279 -0
  14. package/dist/server/channel/channelEngine.test.js +377 -0
  15. package/dist/server/channel/channelRequest.test.js +29 -0
  16. package/dist/server/channel/channelResponse.test.js +134 -0
  17. package/dist/server/channel/eventRequest.js +18 -0
  18. package/dist/server/channel/eventResponse.js +141 -0
  19. package/dist/server/endpoint/connectionResponse.js +50 -0
  20. package/dist/server/endpoint/endpoint.js +269 -0
  21. package/dist/server/endpoint/endpoint.test.js +406 -0
  22. package/dist/server/endpoint/endpointResponse.test.js +43 -0
  23. package/dist/server/pondChannel/joinRequest.js +29 -0
  24. package/dist/server/pondChannel/joinResponse.js +96 -0
  25. package/dist/server/pondChannel/pondChannel.js +161 -0
  26. package/dist/server/pondChannel/pondChannelResponse.test.js +108 -0
  27. package/dist/server/presence/presenceEngine.js +112 -0
  28. package/dist/server/presence/presenceEngine.test.js +104 -0
  29. package/dist/server/server/pondSocket.js +122 -0
  30. package/{pondSocket → dist/server/server}/server.test.js +7 -21
  31. package/{pondBase/baseClass.js → dist/server/utils/matchPattern.js} +33 -43
  32. package/{pondBase/baseClass.test.js → dist/server/utils/matchPattern.test.js} +16 -25
  33. package/dist/server/utils/subjectUtils.js +68 -0
  34. package/package.json +31 -12
  35. package/.eslintrc.js +0 -28
  36. package/base.d.ts +0 -1
  37. package/base.js +0 -17
  38. package/client.d.ts +0 -1
  39. package/client.js +0 -17
  40. package/index.d.ts +0 -1
  41. package/index.js +0 -17
  42. package/jest.config.js +0 -11
  43. package/pondBase/baseClass.d.ts +0 -55
  44. package/pondBase/enums.d.ts +0 -9
  45. package/pondBase/enums.js +0 -14
  46. package/pondBase/index.d.ts +0 -6
  47. package/pondBase/index.js +0 -22
  48. package/pondBase/pondBase.d.ts +0 -41
  49. package/pondBase/pondBase.js +0 -60
  50. package/pondBase/pondBase.test.js +0 -101
  51. package/pondBase/pubSub.d.ts +0 -82
  52. package/pondBase/pubSub.js +0 -158
  53. package/pondBase/pubSub.test.js +0 -332
  54. package/pondBase/simpleBase.d.ts +0 -126
  55. package/pondBase/simpleBase.js +0 -211
  56. package/pondBase/simpleBase.test.js +0 -153
  57. package/pondBase/types.d.ts +0 -2
  58. package/pondBase/types.js +0 -2
  59. package/pondClient/channel.d.ts +0 -77
  60. package/pondClient/channel.js +0 -167
  61. package/pondClient/index.d.ts +0 -2
  62. package/pondClient/index.js +0 -18
  63. package/pondClient/socket.d.ts +0 -41
  64. package/pondSocket/channel.d.ts +0 -129
  65. package/pondSocket/channel.js +0 -287
  66. package/pondSocket/channel.test.js +0 -377
  67. package/pondSocket/channelMiddleWare.d.ts +0 -28
  68. package/pondSocket/channelMiddleWare.js +0 -36
  69. package/pondSocket/endpoint.d.ts +0 -90
  70. package/pondSocket/endpoint.js +0 -320
  71. package/pondSocket/endpoint.test.js +0 -490
  72. package/pondSocket/enums.d.ts +0 -19
  73. package/pondSocket/enums.js +0 -25
  74. package/pondSocket/index.d.ts +0 -7
  75. package/pondSocket/index.js +0 -23
  76. package/pondSocket/pondChannel.d.ts +0 -79
  77. package/pondSocket/pondChannel.js +0 -211
  78. package/pondSocket/pondChannel.test.js +0 -430
  79. package/pondSocket/pondResponse.d.ts +0 -25
  80. package/pondSocket/pondResponse.js +0 -120
  81. package/pondSocket/pondSocket.d.ts +0 -47
  82. package/pondSocket/pondSocket.js +0 -94
  83. package/pondSocket/socketMiddleWare.d.ts +0 -6
  84. package/pondSocket/socketMiddleWare.js +0 -32
  85. package/pondSocket/types.d.ts +0 -74
  86. package/pondSocket/types.js +0 -2
  87. package/socket.d.ts +0 -1
  88. package/socket.js +0 -17
  89. package/tsconfig.eslint.json +0 -5
  90. package/tsconfig.json +0 -90
@@ -0,0 +1,340 @@
1
+ import { Server as HTTPServer, IncomingMessage, IncomingHttpHeaders } from 'http';
2
+ import internal from 'stream';
3
+
4
+ // eslint-disable-next-line import/no-unresolved
5
+ import { Express } from 'express';
6
+ import { WebSocketServer, WebSocket } from 'ws';
7
+
8
+ export type PondPath = string | RegExp;
9
+ type NextFunction = () => void;
10
+ export type JoinParams = Record<string, any>;
11
+ type PondAssigns = Record<string, any>;
12
+ export type PondMessage = Record<string, any>;
13
+ export type PondPresence = Record<string, any>;
14
+ export type EndpointHandler = (req: IncomingConnection, res: ConnectionResponse) => void;
15
+ type SocketCache = Pick<RequestCache, 'socket' | 'clientId' | 'assigns'>;
16
+ type AuthorizeMiddleware = (request: JoinRequest, response: JoinResponse) => void | Promise<void>;
17
+ type SocketMiddlewareFunction = (req: IncomingMessage, socket: internal.Duplex, head: Buffer, next: NextFunction) => void;
18
+
19
+ interface RequestCache {
20
+ clientId: string;
21
+ socket: WebSocket;
22
+ channelName: string;
23
+ assigns: PondAssigns;
24
+ joinParams: Record<string, any>;
25
+ params: Record<string, string>;
26
+ query: Record<string, string>;
27
+ }
28
+ interface UserAssigns {
29
+ [userId: string]: PondAssigns;
30
+ }
31
+ interface UserData {
32
+ assigns: PondAssigns;
33
+ presence: PondPresence;
34
+ id: string;
35
+ }
36
+ interface EventObject {
37
+ event: string;
38
+ params: Record<string, string>;
39
+ query: Record<string, string>;
40
+ payload: PondMessage;
41
+ }
42
+ interface IncomingConnection {
43
+ id: string;
44
+ params: Record<string, string>;
45
+ query: Record<string, string>;
46
+ headers: IncomingHttpHeaders;
47
+ address: string;
48
+ }
49
+ interface UserPresences {
50
+ [userId: string]: PondPresence;
51
+ }
52
+
53
+ declare class AbstractRequest {
54
+ get event (): EventObject;
55
+
56
+ get channelNme (): string;
57
+
58
+ get assigns (): UserAssigns;
59
+
60
+ get presence (): UserPresences;
61
+ }
62
+
63
+ declare class EventRequest extends AbstractRequest {
64
+ get user (): UserData;
65
+ }
66
+
67
+ declare class EventResponse {
68
+ /**
69
+ * @desc Checks if the response has been sent
70
+ */
71
+ get responseSent (): boolean;
72
+
73
+ /**
74
+ * @desc Accepts the request and optionally assigns data to the client
75
+ * @param assigns - the data to assign to the client
76
+ */
77
+ accept (assigns?: PondAssigns): EventResponse;
78
+
79
+ /**
80
+ * @desc Rejects the request and optionally assigns data to the client
81
+ * @param message - the error message
82
+ * @param errorCode - the error code
83
+ * @param assigns - the data to assign to the client
84
+ */
85
+ reject (message?: string, errorCode?: number, assigns?: PondAssigns): EventResponse;
86
+
87
+ /**
88
+ * @desc Emits a direct message to the client
89
+ * @param event - the event name
90
+ * @param payload - the payload to send
91
+ * @param assigns - the data to assign to the client
92
+ */
93
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): EventResponse;
94
+
95
+ /**
96
+ * @desc Sends a message to all clients in the channel
97
+ * @param event - the event to send
98
+ * @param payload - the payload to send
99
+ */
100
+ broadcast (event: string, payload: PondMessage): EventResponse;
101
+
102
+ /**
103
+ * @desc Sends a message to all clients in the channel except the client making the request
104
+ * @param event - the event to send
105
+ * @param payload - the payload to send
106
+ */
107
+ broadcastFromUser (event: string, payload: PondMessage): EventResponse;
108
+
109
+ /**
110
+ * @desc Sends a message to a set of clients in the channel
111
+ * @param event - the event to send
112
+ * @param payload - the payload to send
113
+ * @param userIds - the ids of the clients to send the message to
114
+ */
115
+ sendToUsers (event: string, payload: PondMessage, userIds: string[]): EventResponse;
116
+
117
+ /**
118
+ * @desc Tracks a user's presence in the channel
119
+ * @param presence - the initial presence data
120
+ * @param userId - the id of the user to track
121
+ */
122
+ trackPresence (presence: PondPresence, userId?: string): EventResponse;
123
+
124
+ /**
125
+ * @desc Updates a user's presence in the channel
126
+ * @param presence - the updated presence data
127
+ * @param userId - the id of the user to update
128
+ */
129
+ updatePresence (presence: PondPresence, userId?: string): EventResponse;
130
+
131
+ /**
132
+ * @desc Removes a user's presence from the channel
133
+ * @param userId - the id of the user to remove
134
+ */
135
+ unTrackPresence (userId?: string): EventResponse;
136
+
137
+ /**
138
+ * @desc Evicts a user from the channel
139
+ * @param reason - the reason for the eviction
140
+ * @param userId - the id of the user to evict,
141
+ */
142
+ evictUser (reason: string, userId?: string): void;
143
+
144
+ /**
145
+ * @desc Closes the channel from the server side for all clients
146
+ * @param reason - the reason for closing the channel
147
+ */
148
+ closeChannel (reason: string): void;
149
+ }
150
+
151
+ declare class JoinRequest extends AbstractRequest {
152
+ get joinParams (): JoinParams;
153
+
154
+ get user (): UserData;
155
+
156
+ get event (): EventObject;
157
+ }
158
+
159
+ declare class JoinResponse {
160
+ get responseSent (): boolean;
161
+
162
+ /**
163
+ * @desc Accepts the request and optionally assigns data to the client
164
+ * @param assigns - the data to assign to the client
165
+ */
166
+ accept (assigns?: PondAssigns): JoinResponse;
167
+
168
+ /**
169
+ * @desc Rejects the request and optionally assigns data to the client
170
+ * @param message - the error message
171
+ * @param errorCode - the error code
172
+ */
173
+ reject (message?: string, errorCode?: number): JoinResponse;
174
+
175
+ /**
176
+ * @desc Emits a direct message to the client
177
+ * @param event - the event name
178
+ * @param payload - the payload to send
179
+ * @param assigns - the data to assign to the client
180
+ */
181
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): this;
182
+
183
+ /**
184
+ * @desc Emits a message to all clients in the channel
185
+ * @param event - the event name
186
+ * @param payload - the payload to send
187
+ */
188
+ broadcast (event: string, payload: PondMessage): JoinResponse;
189
+
190
+ /**
191
+ * @desc Emits a message to all clients in the channel except the sender
192
+ * @param event - the event name
193
+ * @param payload - the payload to send
194
+ */
195
+ broadcastFromUser (event: string, payload: PondMessage): JoinResponse;
196
+
197
+ /**
198
+ * @desc Emits a message to a specific set of clients
199
+ * @param event - the event name
200
+ * @param payload - the payload to send
201
+ * @param userIds - the ids of the clients to send the message to
202
+ */
203
+ sendToUsers (event: string, payload: PondMessage, userIds: string[]): JoinResponse;
204
+
205
+ /**
206
+ * @desc tracks the presence of a client
207
+ * @param presence - the presence data to track
208
+ */
209
+ trackPresence (presence: PondPresence): JoinResponse;
210
+ }
211
+
212
+ declare class PondChannel {
213
+ /**
214
+ * @desc Authorize a user to join a channel
215
+ * @param handler - The handler to authorize the user
216
+ * @example
217
+ * const pond = new PondChannelEngine();
218
+ * pond.onJoinRequest((request, response) => {
219
+ * if (request.event.assigns.admin)
220
+ * response.accept();
221
+ * else
222
+ * response.reject('You are not an admin', 403);
223
+ * });
224
+ */
225
+ onJoinRequest (handler: AuthorizeMiddleware): void;
226
+
227
+ /**
228
+ * @desc Handles an event request made by a user
229
+ * @param event - The event to listen for
230
+ * @param handler - The handler to execute when the event is received
231
+ * @example
232
+ * pond.onEvent('echo', (request, response) => {
233
+ * response.send('echo', {
234
+ * message: request.payload,
235
+ * });
236
+ * });
237
+ */
238
+ onEvent (event: PondPath, handler: (request: EventRequest, response: EventResponse) => void | Promise<void>): void;
239
+ }
240
+
241
+ declare class ConnectionResponse {
242
+ /**
243
+ * @desc Accepts the request and optionally assigns data to the client
244
+ * @param assigns - the data to assign to the client
245
+ */
246
+ accept (assigns?: PondAssigns): void;
247
+
248
+ /**
249
+ * @desc Rejects the request with the given error message
250
+ * @param message - the error message
251
+ * @param errorCode - the error code
252
+ */
253
+ reject (message?: string, errorCode?: number): void;
254
+
255
+ /**
256
+ * @desc Emits a direct message to the client
257
+ * @param event - the event name
258
+ * @param payload - the payload to send
259
+ * @param assigns - the data to assign to the client
260
+ */
261
+ send (event: string, payload: PondMessage, assigns?: PondAssigns): void;
262
+ }
263
+
264
+ export declare class Endpoint {
265
+ /**
266
+ * @desc Adds a new PondChannel to this path on this endpoint
267
+ * @param path - The path to add the channel to
268
+ * @param channel - The channel to add
269
+ *
270
+ * @example
271
+ * endpoint.useChannel('/chat', pondChannelInstance);
272
+ */
273
+ useChannel (path: PondPath, channel: PondChannel): void;
274
+
275
+ /**
276
+ * @desc List all clients connected to this endpoint
277
+ */
278
+ listConnections (): string[];
279
+
280
+ /**
281
+ * @desc Gets all clients connected to this endpoint
282
+ */
283
+ getClients (): SocketCache[];
284
+
285
+ /**
286
+ * @desc Broadcasts a message to all clients connected to this endpoint
287
+ * @param event - The event to broadcast
288
+ * @param payload - The payload to broadcast
289
+ */
290
+ broadcast (event: string, payload: PondMessage): void;
291
+
292
+ /**
293
+ * @desc Closes specific clients connected to this endpoint
294
+ * @param clientIds - The id for the client / clients to close
295
+ */
296
+ closeConnection (clientIds: string | string[]): void;
297
+ }
298
+
299
+ declare class PondSocket {
300
+ constructor (server?: HTTPServer, socketServer?: WebSocketServer);
301
+
302
+ /**
303
+ * @desc Specifies the port to listen on
304
+ * @param port - the port to listen on
305
+ * @param callback - the callback to call when the server is listening
306
+ */
307
+ listen (port: number, callback: (port?: number) => void): HTTPServer<typeof IncomingMessage, typeof import('http').ServerResponse>;
308
+
309
+ /**
310
+ * @desc Closes the server
311
+ * @param callback - the callback to call when the server is closed
312
+ */
313
+ close (callback?: () => void): HTTPServer<typeof IncomingMessage, typeof import('http').ServerResponse>;
314
+
315
+ /**
316
+ * @desc Accepts a new socket upgrade request on the provided endpoint using the handler function to authenticate the socket
317
+ * @param path - the pattern to accept || can also be a regex
318
+ * @param handler - the handler function to authenticate the socket
319
+ * @example
320
+ * const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
321
+ * const token = req.query.token;
322
+ * if (!token)
323
+ * return res.reject('No token provided');
324
+ * res.accept({
325
+ * assign: {
326
+ * token
327
+ * }
328
+ * });
329
+ * })
330
+ */
331
+ createEndpoint (path: PondPath, handler: EndpointHandler): Endpoint;
332
+
333
+ /**
334
+ * @desc Adds a middleware function to the socket server
335
+ * @param middleware - the middleware function to add
336
+ */
337
+ use (middleware: SocketMiddlewareFunction): void;
338
+ }
339
+
340
+ export default PondSocket;
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pondSocket_1 = require("./server/server/pondSocket");
4
+ exports.default = pondSocket_1.PondSocket;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractRequest = void 0;
4
+ const matchPattern_1 = require("../utils/matchPattern");
5
+ class AbstractRequest {
6
+ constructor(event, engine, payload) {
7
+ this._engine = engine;
8
+ this._event = event;
9
+ this._eventObject = null;
10
+ this._payload = payload;
11
+ }
12
+ get event() {
13
+ var _a, _b;
14
+ return {
15
+ event: this._event,
16
+ params: ((_a = this._eventObject) === null || _a === void 0 ? void 0 : _a.params) || {},
17
+ query: ((_b = this._eventObject) === null || _b === void 0 ? void 0 : _b.query) || {},
18
+ payload: this._payload,
19
+ };
20
+ }
21
+ get channelNme() {
22
+ return this._engine.name;
23
+ }
24
+ get assigns() {
25
+ return this._engine.getAssigns();
26
+ }
27
+ get presence() {
28
+ return this._engine.getPresence();
29
+ }
30
+ /**
31
+ * @desc Parses the event and returns true if the event matches the path
32
+ * @param path - the path to match
33
+ */
34
+ _parseQueries(path) {
35
+ const match = new matchPattern_1.MatchPattern();
36
+ this._eventObject = match.parseEvent(path, this._event);
37
+ return this._eventObject !== null;
38
+ }
39
+ }
40
+ exports.AbstractRequest = AbstractRequest;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const abstractRequest_1 = require("./abstractRequest");
4
+ const createMockChannelEngine = () => ({
5
+ name: 'test',
6
+ getAssigns: () => ({}),
7
+ getPresence: () => ({}),
8
+ });
9
+ describe('AbstractRequest', () => {
10
+ it('should be able to be instantiated', () => {
11
+ const request = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), {});
12
+ expect(request).toBeTruthy();
13
+ expect(request.channelNme).toBe('test');
14
+ expect(request.assigns).toEqual({});
15
+ expect(request.presence).toEqual({});
16
+ });
17
+ it('should be able to parse queries', () => {
18
+ const request = new abstractRequest_1.AbstractRequest('/1234?choke=balls', createMockChannelEngine(), {});
19
+ expect(request.event).toEqual({
20
+ event: '/1234?choke=balls',
21
+ payload: {},
22
+ params: {},
23
+ query: {},
24
+ });
25
+ expect(request._parseQueries('/:id')).toBe(true);
26
+ expect(request.event).toEqual({
27
+ event: '/1234?choke=balls',
28
+ params: { id: '1234' },
29
+ query: { choke: 'balls' },
30
+ payload: {},
31
+ });
32
+ });
33
+ it('should be return the value of the payload', () => {
34
+ const request = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), { test: 'test' });
35
+ expect(request.event.payload).toEqual({ test: 'test' });
36
+ const request2 = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), { test: 'test',
37
+ test2: 'test2' });
38
+ expect(request2.event.payload).toEqual({ test: 'test',
39
+ test2: 'test2' });
40
+ });
41
+ });
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PondResponse = void 0;
4
+ class PondResponse {
5
+ }
6
+ exports.PondResponse = PondResponse;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Middleware = void 0;
4
+ class Middleware {
5
+ constructor(second) {
6
+ this._stack = [];
7
+ if (second) {
8
+ this._stack.push(...second._stack);
9
+ }
10
+ }
11
+ /**
12
+ * @desc Adds a middleware function to the middleware stack
13
+ * @param middleware - the middleware function to add
14
+ */
15
+ use(middleware) {
16
+ this._stack.push(middleware);
17
+ }
18
+ /**
19
+ * @desc Runs the middleware stack
20
+ * @param req - the request object
21
+ * @param res - the response object
22
+ * @param final - the final function to call
23
+ */
24
+ run(req, res, final) {
25
+ const temp = this._stack.concat();
26
+ const nextFunction = () => {
27
+ const middleware = temp.shift();
28
+ if (middleware && !res.responseSent) {
29
+ void middleware(req, res, nextFunction);
30
+ }
31
+ else if (!res.responseSent) {
32
+ final();
33
+ }
34
+ };
35
+ nextFunction();
36
+ }
37
+ }
38
+ exports.Middleware = Middleware;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const middleware_1 = require("./middleware");
13
+ describe('Middleware', () => {
14
+ it('should be able to add middleware to the stack', () => {
15
+ const middleware = new middleware_1.Middleware();
16
+ middleware.use(() => { });
17
+ expect(middleware['_stack'].length).toBe(1);
18
+ });
19
+ it('should be able to run middleware', () => __awaiter(void 0, void 0, void 0, function* () {
20
+ const middleware = new middleware_1.Middleware();
21
+ const mock = jest.fn();
22
+ middleware.use(mock);
23
+ yield middleware.run({}, {}, () => { });
24
+ expect(mock).toHaveBeenCalled();
25
+ }));
26
+ it('should be able to run multiple middleware', () => __awaiter(void 0, void 0, void 0, function* () {
27
+ const middleware = new middleware_1.Middleware();
28
+ const mock = jest.fn();
29
+ middleware.use((_, __, next) => {
30
+ mock('first');
31
+ next();
32
+ });
33
+ middleware.use((_, __, next) => {
34
+ mock('second');
35
+ next();
36
+ });
37
+ yield middleware.run({}, {}, () => { });
38
+ expect(mock).toHaveBeenCalledTimes(2);
39
+ expect(mock.mock.calls[0][2]).toBe(mock.mock.calls[1][2]);
40
+ }));
41
+ it('should be merge middleware in the correct order', () => __awaiter(void 0, void 0, void 0, function* () {
42
+ const middleware = new middleware_1.Middleware();
43
+ const mock = jest.fn();
44
+ middleware.use(mock);
45
+ middleware.use(mock);
46
+ const middleware2 = new middleware_1.Middleware(middleware);
47
+ expect(middleware2['_stack'].length).toBe(2);
48
+ }));
49
+ it('should call the final function when the middleware stack is empty', () => __awaiter(void 0, void 0, void 0, function* () {
50
+ const middleware = new middleware_1.Middleware();
51
+ const mock = jest.fn();
52
+ yield middleware.run({}, {}, mock);
53
+ expect(mock).toHaveBeenCalled();
54
+ }));
55
+ it('should be able to run middleware in the correct order when using a second middleware', () => __awaiter(void 0, void 0, void 0, function* () {
56
+ const middleware = new middleware_1.Middleware();
57
+ const mock = jest.fn();
58
+ middleware.use((_, __, next) => {
59
+ mock('first');
60
+ next();
61
+ });
62
+ middleware.use((_, __, next) => {
63
+ mock('second');
64
+ next();
65
+ });
66
+ const middleware2 = new middleware_1.Middleware(middleware);
67
+ yield middleware2.run({}, {}, () => { });
68
+ expect(mock.mock.calls[0][2]).toBe(mock.mock.calls[1][2]);
69
+ }));
70
+ });