0z2i6v3u5t 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/devcontainer.json +4 -0
- package/.devcontainer/setup.sh +11 -0
- package/.dockerignore +2 -0
- package/.github/CONTRIBUTING.md +52 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +59 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
- package/.github/dependabot.yml +17 -0
- package/.github/workflows/codeql.yml +76 -0
- package/.github/workflows/publish_docs.yml +25 -0
- package/.github/workflows/test.yml +78 -0
- package/.nvmrc +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +1 -0
- package/.vscode/launch.json +42 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/Dockerfile +17 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/SECURITY.md +5 -0
- package/__tests__/actions/cacheTest.ts +58 -0
- package/__tests__/actions/randomNumber.ts +26 -0
- package/__tests__/actions/recursiveAction.ts +16 -0
- package/__tests__/actions/sleepTest.ts +24 -0
- package/__tests__/actions/status.ts +17 -0
- package/__tests__/actions/swagger.ts +76 -0
- package/__tests__/actions/validationTest.ts +63 -0
- package/__tests__/cli/cli.ts +126 -0
- package/__tests__/core/api.ts +632 -0
- package/__tests__/core/cache.ts +400 -0
- package/__tests__/core/chatRoom.ts +589 -0
- package/__tests__/core/cli.ts +349 -0
- package/__tests__/core/cluster.ts +132 -0
- package/__tests__/core/config.ts +78 -0
- package/__tests__/core/errors.ts +112 -0
- package/__tests__/core/log.ts +23 -0
- package/__tests__/core/middleware.ts +427 -0
- package/__tests__/core/plugins/partialPlugin.ts +94 -0
- package/__tests__/core/plugins/withPlugin.ts +88 -0
- package/__tests__/core/plugins/withoutPlugin.ts +81 -0
- package/__tests__/core/process.ts +42 -0
- package/__tests__/core/specHelper.ts +330 -0
- package/__tests__/core/staticFile/compression.ts +99 -0
- package/__tests__/core/staticFile/staticFile.ts +180 -0
- package/__tests__/core/tasks/customQueueFunction.ts +67 -0
- package/__tests__/core/tasks/fullWorkerFlow.ts +199 -0
- package/__tests__/core/tasks/tasks.ts +605 -0
- package/__tests__/integration/browser.ts +133 -0
- package/__tests__/integration/ioredis-mock.ts +194 -0
- package/__tests__/integration/sendBuffer.ts +97 -0
- package/__tests__/integration/sendFile.ts +24 -0
- package/__tests__/integration/sharedFingerprint.ts +82 -0
- package/__tests__/integration/taskFlow.ts +110 -0
- package/__tests__/jest.ts +5 -0
- package/__tests__/modules/action.ts +103 -0
- package/__tests__/modules/config.ts +19 -0
- package/__tests__/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +24 -0
- package/__tests__/servers/web/allowedRequestHosts.ts +88 -0
- package/__tests__/servers/web/enableMultiples.ts +83 -0
- package/__tests__/servers/web/fileUpload.ts +79 -0
- package/__tests__/servers/web/jsonp.ts +57 -0
- package/__tests__/servers/web/nonMultiples.ts +83 -0
- package/__tests__/servers/web/rawBody.ts +208 -0
- package/__tests__/servers/web/returnErrorCodes.ts +55 -0
- package/__tests__/servers/web/routes/deepRoutes.ts +96 -0
- package/__tests__/servers/web/routes/routes.ts +579 -0
- package/__tests__/servers/web/routes/veryDeepRoutes.ts +92 -0
- package/__tests__/servers/web/web.ts +1031 -0
- package/__tests__/servers/websocket.ts +795 -0
- package/__tests__/tasks/runAction.ts +37 -0
- package/__tests__/template.ts.example +20 -0
- package/__tests__/testCliCommands/hello.ts +44 -0
- package/__tests__/testPlugin/public/plugin.html +1 -0
- package/__tests__/testPlugin/src/actions/pluginAction.ts +14 -0
- package/__tests__/testPlugin/src/bin/hello.ts +22 -0
- package/__tests__/testPlugin/src/initializers/pluginInitializer.ts +17 -0
- package/__tests__/testPlugin/src/tasks/pluginTask.ts +15 -0
- package/__tests__/testPlugin/tsconfig.json +10 -0
- package/__tests__/utils/utils.ts +492 -0
- package/app.json +23 -0
- package/bin/deploy-docs +39 -0
- package/client/ActionheroWebsocketClient.js +277 -0
- package/docker-compose.yml +73 -0
- package/package.json +24 -0
- package/public/chat.html +194 -0
- package/public/css/cosmo.css +12 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +115 -0
- package/public/javascript/.gitkeep +0 -0
- package/public/linkedSession.html +80 -0
- package/public/logo/actionhero-small.png +0 -0
- package/public/logo/actionhero.png +0 -0
- package/public/pixel.gif +0 -0
- package/public/simple.html +2 -0
- package/public/swagger.html +32 -0
- package/public/websocketLoadTest.html +322 -0
- package/src/actions/cacheTest.ts +58 -0
- package/src/actions/createChatRoom.ts +20 -0
- package/src/actions/randomNumber.ts +17 -0
- package/src/actions/recursiveAction.ts +13 -0
- package/src/actions/sendFile.ts +12 -0
- package/src/actions/sleepTest.ts +40 -0
- package/src/actions/status.ts +73 -0
- package/src/actions/swagger.ts +155 -0
- package/src/actions/validationTest.ts +36 -0
- package/src/bin/actionhero.ts +225 -0
- package/src/bin/methods/actions/list.ts +30 -0
- package/src/bin/methods/console.ts +26 -0
- package/src/bin/methods/generate/action.ts +58 -0
- package/src/bin/methods/generate/cli.ts +51 -0
- package/src/bin/methods/generate/initializer.ts +54 -0
- package/src/bin/methods/generate/plugin.ts +57 -0
- package/src/bin/methods/generate/server.ts +38 -0
- package/src/bin/methods/generate/task.ts +68 -0
- package/src/bin/methods/generate.ts +176 -0
- package/src/bin/methods/task/enqueue.ts +35 -0
- package/src/classes/action.ts +98 -0
- package/src/classes/actionProcessor.ts +463 -0
- package/src/classes/api.ts +51 -0
- package/src/classes/cli.ts +67 -0
- package/src/classes/config.ts +15 -0
- package/src/classes/connection.ts +321 -0
- package/src/classes/exceptionReporter.ts +9 -0
- package/src/classes/initializer.ts +59 -0
- package/src/classes/initializers.ts +5 -0
- package/src/classes/input.ts +9 -0
- package/src/classes/inputs.ts +34 -0
- package/src/classes/process/actionheroVersion.ts +15 -0
- package/src/classes/process/env.ts +16 -0
- package/src/classes/process/id.ts +34 -0
- package/src/classes/process/pid.ts +32 -0
- package/src/classes/process/projectRoot.ts +16 -0
- package/src/classes/process/typescript.ts +47 -0
- package/src/classes/process.ts +479 -0
- package/src/classes/server.ts +251 -0
- package/src/classes/task.ts +87 -0
- package/src/config/api.ts +107 -0
- package/src/config/errors.ts +162 -0
- package/src/config/logger.ts +113 -0
- package/src/config/plugins.ts +37 -0
- package/src/config/redis.ts +78 -0
- package/src/config/routes.ts +44 -0
- package/src/config/tasks.ts +84 -0
- package/src/config/web.ts +136 -0
- package/src/config/websocket.ts +62 -0
- package/src/index.ts +46 -0
- package/src/initializers/actions.ts +125 -0
- package/src/initializers/chatRoom.ts +214 -0
- package/src/initializers/connections.ts +124 -0
- package/src/initializers/exceptions.ts +155 -0
- package/src/initializers/params.ts +52 -0
- package/src/initializers/redis.ts +191 -0
- package/src/initializers/resque.ts +248 -0
- package/src/initializers/routes.ts +229 -0
- package/src/initializers/servers.ts +134 -0
- package/src/initializers/specHelper.ts +195 -0
- package/src/initializers/staticFile.ts +253 -0
- package/src/initializers/tasks.ts +188 -0
- package/src/modules/action.ts +89 -0
- package/src/modules/cache.ts +326 -0
- package/src/modules/chatRoom.ts +321 -0
- package/src/modules/config.ts +246 -0
- package/src/modules/log.ts +62 -0
- package/src/modules/redis.ts +93 -0
- package/src/modules/route.ts +59 -0
- package/src/modules/specHelper.ts +182 -0
- package/src/modules/task.ts +527 -0
- package/src/modules/utils/argv.ts +3 -0
- package/src/modules/utils/arrayStartingMatch.ts +21 -0
- package/src/modules/utils/arrayUnique.ts +15 -0
- package/src/modules/utils/collapseObjectToArray.ts +33 -0
- package/src/modules/utils/deepCopy.ts +3 -0
- package/src/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +19 -0
- package/src/modules/utils/eventLoopDelay.ts +34 -0
- package/src/modules/utils/fileUtils.ts +119 -0
- package/src/modules/utils/filterObjectForLogging.ts +51 -0
- package/src/modules/utils/filterResponseForLogging.ts +53 -0
- package/src/modules/utils/getExternalIPAddress.ts +17 -0
- package/src/modules/utils/hashMerge.ts +63 -0
- package/src/modules/utils/isPlainObject.ts +45 -0
- package/src/modules/utils/isRunning.ts +7 -0
- package/src/modules/utils/parseCookies.ts +20 -0
- package/src/modules/utils/parseHeadersForClientAddress.ts +53 -0
- package/src/modules/utils/parseIPv6URI.ts +24 -0
- package/src/modules/utils/replaceDistWithSrc.ts +9 -0
- package/src/modules/utils/safeGlob.ts +6 -0
- package/src/modules/utils/sleep.ts +8 -0
- package/src/modules/utils/sortGlobalMiddleware.ts +17 -0
- package/src/modules/utils/sourceRelativeLinkPath.ts +29 -0
- package/src/modules/utils.ts +66 -0
- package/src/server.ts +20 -0
- package/src/servers/web.ts +894 -0
- package/src/servers/websocket.ts +304 -0
- package/src/tasks/runAction.ts +29 -0
- package/tea.yaml +9 -0
- package/templates/README.md.template +17 -0
- package/templates/action.ts.template +15 -0
- package/templates/boot.js.template +9 -0
- package/templates/cli.ts.template +15 -0
- package/templates/gitignore.template +23 -0
- package/templates/initializer.ts.template +17 -0
- package/templates/package-plugin.json.template +12 -0
- package/templates/package.json.template +45 -0
- package/templates/projectMap.txt +39 -0
- package/templates/projectServer.ts.template +20 -0
- package/templates/server.ts.template +37 -0
- package/templates/task.ts.template +16 -0
- package/templates/test/action.ts.template +13 -0
- package/templates/test/task.ts.template +20 -0
- package/tsconfig.json +11 -0
@@ -0,0 +1,589 @@
|
|
1
|
+
import {
|
2
|
+
api,
|
3
|
+
Process,
|
4
|
+
config,
|
5
|
+
utils,
|
6
|
+
specHelper,
|
7
|
+
chatRoom,
|
8
|
+
Connection,
|
9
|
+
} from "./../../src";
|
10
|
+
|
11
|
+
const actionhero = new Process();
|
12
|
+
|
13
|
+
describe("Core", () => {
|
14
|
+
describe("chatRoom", () => {
|
15
|
+
beforeAll(async () => {
|
16
|
+
await actionhero.start();
|
17
|
+
|
18
|
+
for (var room in config!.general!.startingChatRooms as Record<
|
19
|
+
string,
|
20
|
+
Record<string, any>
|
21
|
+
>) {
|
22
|
+
try {
|
23
|
+
await chatRoom.destroy(room);
|
24
|
+
await chatRoom.add(room);
|
25
|
+
} catch (error) {
|
26
|
+
if (
|
27
|
+
config.errors &&
|
28
|
+
typeof config.errors.connectionRoomExists === "function"
|
29
|
+
) {
|
30
|
+
if (
|
31
|
+
!error.toString().match(config.errors.connectionRoomExists(room))
|
32
|
+
) {
|
33
|
+
throw error;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
});
|
39
|
+
|
40
|
+
afterAll(async () => {
|
41
|
+
await actionhero.stop();
|
42
|
+
});
|
43
|
+
|
44
|
+
describe("say and clients on separate servers", () => {
|
45
|
+
let client1: Connection;
|
46
|
+
let client2: Connection;
|
47
|
+
let client3: Connection;
|
48
|
+
|
49
|
+
beforeAll(async () => {
|
50
|
+
client1 = await specHelper.buildConnection();
|
51
|
+
client2 = await specHelper.buildConnection();
|
52
|
+
client3 = await specHelper.buildConnection();
|
53
|
+
|
54
|
+
client1.verbs("roomAdd", "defaultRoom");
|
55
|
+
client2.verbs("roomAdd", "defaultRoom");
|
56
|
+
client3.verbs("roomAdd", "defaultRoom");
|
57
|
+
await utils.sleep(100);
|
58
|
+
});
|
59
|
+
|
60
|
+
afterAll(async () => {
|
61
|
+
client1.destroy();
|
62
|
+
client2.destroy();
|
63
|
+
client3.destroy();
|
64
|
+
await utils.sleep(100);
|
65
|
+
});
|
66
|
+
|
67
|
+
test("all connections can join the default room and client #1 can see them", async () => {
|
68
|
+
const { room, membersCount } = await client1.verbs(
|
69
|
+
"roomView",
|
70
|
+
"defaultRoom",
|
71
|
+
);
|
72
|
+
expect(room).toEqual("defaultRoom");
|
73
|
+
expect(membersCount).toEqual(3);
|
74
|
+
});
|
75
|
+
|
76
|
+
test("all connections can join the default room and client #2 can see them", async () => {
|
77
|
+
const { room, membersCount } = await client2.verbs(
|
78
|
+
"roomView",
|
79
|
+
"defaultRoom",
|
80
|
+
);
|
81
|
+
expect(room).toEqual("defaultRoom");
|
82
|
+
expect(membersCount).toEqual(3);
|
83
|
+
});
|
84
|
+
|
85
|
+
test("all connections can join the default room and client #3 can see them", async () => {
|
86
|
+
const { room, membersCount } = await client3.verbs(
|
87
|
+
"roomView",
|
88
|
+
"defaultRoom",
|
89
|
+
);
|
90
|
+
expect(room).toEqual("defaultRoom");
|
91
|
+
expect(membersCount).toEqual(3);
|
92
|
+
});
|
93
|
+
|
94
|
+
test("clients can communicate across the cluster", async () => {
|
95
|
+
await client1.verbs("say", [
|
96
|
+
"defaultRoom",
|
97
|
+
"Hi",
|
98
|
+
"from",
|
99
|
+
"client",
|
100
|
+
"1",
|
101
|
+
]);
|
102
|
+
await utils.sleep(100);
|
103
|
+
|
104
|
+
if (!client2.messages) throw new Error("no messages for client2");
|
105
|
+
|
106
|
+
const { message, room, from } =
|
107
|
+
client2.messages[client2.messages.length - 1];
|
108
|
+
expect(message).toEqual("Hi from client 1");
|
109
|
+
expect(room).toEqual("defaultRoom");
|
110
|
+
expect(from).toEqual(client1.id);
|
111
|
+
});
|
112
|
+
});
|
113
|
+
|
114
|
+
describe("chat", () => {
|
115
|
+
beforeEach(async () => {
|
116
|
+
try {
|
117
|
+
await chatRoom.destroy("newRoom");
|
118
|
+
} catch (error) {
|
119
|
+
// it's fine
|
120
|
+
}
|
121
|
+
});
|
122
|
+
|
123
|
+
test("can check if rooms exist", async () => {
|
124
|
+
const found = await chatRoom.exists("defaultRoom");
|
125
|
+
expect(found).toEqual(true);
|
126
|
+
});
|
127
|
+
|
128
|
+
test("can check if a room does not exist", async () => {
|
129
|
+
const found = await chatRoom.exists("missingRoom");
|
130
|
+
expect(found).toEqual(false);
|
131
|
+
});
|
132
|
+
|
133
|
+
test("server can create new room", async () => {
|
134
|
+
const room = "newRoom";
|
135
|
+
let found;
|
136
|
+
found = await chatRoom.exists(room);
|
137
|
+
expect(found).toEqual(false);
|
138
|
+
await chatRoom.add(room);
|
139
|
+
found = await chatRoom.exists(room);
|
140
|
+
expect(found).toEqual(true);
|
141
|
+
});
|
142
|
+
|
143
|
+
test("server cannot create already existing room", async () => {
|
144
|
+
try {
|
145
|
+
await chatRoom.add("defaultRoom");
|
146
|
+
throw new Error("should not get here");
|
147
|
+
} catch (error) {
|
148
|
+
expect(error.toString()).toEqual("Error: room exists");
|
149
|
+
}
|
150
|
+
});
|
151
|
+
|
152
|
+
test("can enumerate all the rooms in the system", async () => {
|
153
|
+
await chatRoom.add("newRoom");
|
154
|
+
const rooms = await chatRoom.list();
|
155
|
+
expect(rooms).toHaveLength(3);
|
156
|
+
["defaultRoom", "newRoom", "otherRoom"].forEach((r) => {
|
157
|
+
expect(rooms.indexOf(r)).toBeGreaterThan(-1);
|
158
|
+
});
|
159
|
+
});
|
160
|
+
|
161
|
+
test("server can add connections to a LOCAL room", async () => {
|
162
|
+
const client = await specHelper.buildConnection();
|
163
|
+
expect(client.rooms).toHaveLength(0);
|
164
|
+
const didAdd = await chatRoom.addMember(client.id, "defaultRoom");
|
165
|
+
expect(didAdd).toEqual(true);
|
166
|
+
expect(client.rooms[0]).toEqual("defaultRoom");
|
167
|
+
client.destroy();
|
168
|
+
});
|
169
|
+
|
170
|
+
test("will not re-add a member to a room", async () => {
|
171
|
+
const client = await specHelper.buildConnection();
|
172
|
+
expect(client.rooms).toHaveLength(0);
|
173
|
+
let didAdd = await chatRoom.addMember(client.id, "defaultRoom");
|
174
|
+
expect(didAdd).toEqual(true);
|
175
|
+
try {
|
176
|
+
didAdd = await chatRoom.addMember(client.id, "defaultRoom");
|
177
|
+
throw new Error("should not get here");
|
178
|
+
} catch (error) {
|
179
|
+
expect(error.toString()).toEqual(
|
180
|
+
"Error: connection already in this room (defaultRoom)",
|
181
|
+
);
|
182
|
+
client.destroy();
|
183
|
+
}
|
184
|
+
});
|
185
|
+
|
186
|
+
test("will not add a member to a non-existent room", async () => {
|
187
|
+
const client = await specHelper.buildConnection();
|
188
|
+
expect(client.rooms).toHaveLength(0);
|
189
|
+
try {
|
190
|
+
await chatRoom.addMember(client.id, "crazyRoom");
|
191
|
+
throw new Error("should not get here");
|
192
|
+
} catch (error) {
|
193
|
+
expect(error.toString()).toEqual("Error: room does not exist");
|
194
|
+
client.destroy();
|
195
|
+
}
|
196
|
+
});
|
197
|
+
|
198
|
+
test("server will not remove a member not in a room", async () => {
|
199
|
+
const client = await specHelper.buildConnection();
|
200
|
+
try {
|
201
|
+
await chatRoom.removeMember(client.id, "defaultRoom");
|
202
|
+
throw new Error("should not get here");
|
203
|
+
} catch (error) {
|
204
|
+
expect(error.toString()).toEqual(
|
205
|
+
"Error: connection not in this room (defaultRoom)",
|
206
|
+
);
|
207
|
+
client.destroy();
|
208
|
+
}
|
209
|
+
});
|
210
|
+
|
211
|
+
test("server can remove connections to a room", async () => {
|
212
|
+
const client = await specHelper.buildConnection();
|
213
|
+
const didAdd = await chatRoom.addMember(client.id, "defaultRoom");
|
214
|
+
expect(didAdd).toEqual(true);
|
215
|
+
const didRemove = await chatRoom.removeMember(client.id, "defaultRoom");
|
216
|
+
expect(didRemove).toEqual(true);
|
217
|
+
client.destroy();
|
218
|
+
});
|
219
|
+
|
220
|
+
test("server can destroy a room and connections will be removed", async () => {
|
221
|
+
try {
|
222
|
+
// to ensure it starts empty
|
223
|
+
await chatRoom.destroy("newRoom");
|
224
|
+
} catch (error) {}
|
225
|
+
|
226
|
+
const client = await specHelper.buildConnection();
|
227
|
+
await chatRoom.add("newRoom");
|
228
|
+
const didAdd = await chatRoom.addMember(client.id, "newRoom");
|
229
|
+
expect(didAdd).toEqual(true);
|
230
|
+
expect(client.rooms[0]).toEqual("newRoom");
|
231
|
+
|
232
|
+
await chatRoom.destroy("newRoom");
|
233
|
+
expect(client.rooms).toHaveLength(0);
|
234
|
+
|
235
|
+
// testing for the receipt of this message is a race condition with room.destroy and broadcast in test
|
236
|
+
// client.messages[1].message.should.equal('this room has been deleted')
|
237
|
+
// client.messages[1].room.should.equal('newRoom')
|
238
|
+
|
239
|
+
client.destroy();
|
240
|
+
});
|
241
|
+
|
242
|
+
test("can get a list of room members", async () => {
|
243
|
+
const client = await specHelper.buildConnection();
|
244
|
+
expect(client.rooms).toHaveLength(0);
|
245
|
+
await chatRoom.add("newRoom");
|
246
|
+
await chatRoom.addMember(client.id, "newRoom");
|
247
|
+
const { room, membersCount } = await chatRoom.roomStatus("newRoom");
|
248
|
+
expect(room).toEqual("newRoom");
|
249
|
+
expect(membersCount).toEqual(1);
|
250
|
+
client.destroy();
|
251
|
+
await chatRoom.destroy("newRoom");
|
252
|
+
});
|
253
|
+
|
254
|
+
test("can see the details of the other members in the room", async () => {
|
255
|
+
const client = await specHelper.buildConnection();
|
256
|
+
const otherClient = await specHelper.buildConnection();
|
257
|
+
await chatRoom.add("newRoom");
|
258
|
+
await chatRoom.addMember(client.id, "newRoom");
|
259
|
+
await utils.sleep(100);
|
260
|
+
await chatRoom.addMember(otherClient.id, "newRoom");
|
261
|
+
|
262
|
+
const { members, membersCount } = await chatRoom.roomStatus("newRoom");
|
263
|
+
expect(membersCount).toBe(2);
|
264
|
+
expect(members).toEqual({
|
265
|
+
[client.id]: { id: client.id, joinedAt: expect.any(Number) },
|
266
|
+
[otherClient.id]: {
|
267
|
+
id: otherClient.id,
|
268
|
+
joinedAt: expect.any(Number),
|
269
|
+
},
|
270
|
+
});
|
271
|
+
expect(members[otherClient.id].joinedAt).toBeGreaterThan(
|
272
|
+
members[client.id].joinedAt,
|
273
|
+
);
|
274
|
+
|
275
|
+
client.destroy();
|
276
|
+
otherClient.destroy();
|
277
|
+
await chatRoom.destroy("newRoom");
|
278
|
+
});
|
279
|
+
|
280
|
+
describe("chat middleware", () => {
|
281
|
+
let clientA: any;
|
282
|
+
let clientB: any;
|
283
|
+
let originalGenerateMessagePayload: (message: any) => any;
|
284
|
+
|
285
|
+
beforeEach(async () => {
|
286
|
+
originalGenerateMessagePayload = api.chatRoom.generateMessagePayload;
|
287
|
+
clientA = await specHelper.buildConnection();
|
288
|
+
clientB = await specHelper.buildConnection();
|
289
|
+
});
|
290
|
+
|
291
|
+
afterEach(() => {
|
292
|
+
api.chatRoom.middleware = {};
|
293
|
+
api.chatRoom.globalMiddleware = [];
|
294
|
+
|
295
|
+
clientA.destroy();
|
296
|
+
clientB.destroy();
|
297
|
+
|
298
|
+
api.chatRoom.generateMessagePayload = originalGenerateMessagePayload;
|
299
|
+
});
|
300
|
+
|
301
|
+
test("generateMessagePayload can be overloaded", async () => {
|
302
|
+
api.chatRoom.generateMessagePayload = (message) => {
|
303
|
+
return {
|
304
|
+
thing: "stuff",
|
305
|
+
room: message.connection.room,
|
306
|
+
from: message.connection.id,
|
307
|
+
};
|
308
|
+
};
|
309
|
+
|
310
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
311
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
312
|
+
await clientA.verbs("say", ["defaultRoom", "hi there"]);
|
313
|
+
await utils.sleep(100);
|
314
|
+
const message = clientB.messages[clientB.messages.length - 1];
|
315
|
+
expect(message.thing).toEqual("stuff");
|
316
|
+
expect(message.message).toBeUndefined();
|
317
|
+
});
|
318
|
+
|
319
|
+
test("(join + leave) can add middleware to announce members", async () => {
|
320
|
+
chatRoom.addMiddleware({
|
321
|
+
name: "add chat middleware",
|
322
|
+
join: async (connection: Connection, room: string) => {
|
323
|
+
await chatRoom.broadcast(
|
324
|
+
{},
|
325
|
+
room,
|
326
|
+
`I have entered the room: ${connection.id}`,
|
327
|
+
);
|
328
|
+
},
|
329
|
+
});
|
330
|
+
|
331
|
+
chatRoom.addMiddleware({
|
332
|
+
name: "leave chat middleware",
|
333
|
+
leave: async (connection: Connection, room: string) => {
|
334
|
+
await chatRoom.broadcast(
|
335
|
+
{},
|
336
|
+
room,
|
337
|
+
`I have left the room: ${connection.id}`,
|
338
|
+
);
|
339
|
+
},
|
340
|
+
});
|
341
|
+
|
342
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
343
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
344
|
+
await clientB.verbs("roomLeave", "defaultRoom");
|
345
|
+
await utils.sleep(100);
|
346
|
+
|
347
|
+
expect(clientA.messages.pop().message).toEqual(
|
348
|
+
"I have left the room: " + clientB.id,
|
349
|
+
);
|
350
|
+
expect(clientA.messages.pop().message).toEqual(
|
351
|
+
"I have entered the room: " + clientB.id,
|
352
|
+
);
|
353
|
+
});
|
354
|
+
|
355
|
+
test("(say) can modify message payloads", async () => {
|
356
|
+
chatRoom.addMiddleware({
|
357
|
+
name: "chat middleware",
|
358
|
+
say: (
|
359
|
+
connection: Connection,
|
360
|
+
room: string,
|
361
|
+
messagePayload: { from: number; message: string },
|
362
|
+
) => {
|
363
|
+
if (messagePayload.from !== 0) {
|
364
|
+
messagePayload.message = "something else";
|
365
|
+
}
|
366
|
+
return messagePayload;
|
367
|
+
},
|
368
|
+
});
|
369
|
+
|
370
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
371
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
372
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
373
|
+
await utils.sleep(100);
|
374
|
+
|
375
|
+
const lastMessage = clientA.messages[clientA.messages.length - 1];
|
376
|
+
expect(lastMessage.message).toEqual("something else");
|
377
|
+
});
|
378
|
+
|
379
|
+
test("can add middleware in a particular order and will be passed modified messagePayloads", async () => {
|
380
|
+
chatRoom.addMiddleware({
|
381
|
+
name: "chat middleware 1",
|
382
|
+
priority: 1000,
|
383
|
+
say: (
|
384
|
+
connection: Connection,
|
385
|
+
room: string,
|
386
|
+
messagePayload: { from: number; message: string },
|
387
|
+
) => {
|
388
|
+
messagePayload.message = "MIDDLEWARE 1";
|
389
|
+
return messagePayload;
|
390
|
+
},
|
391
|
+
});
|
392
|
+
|
393
|
+
chatRoom.addMiddleware({
|
394
|
+
name: "chat middleware 2",
|
395
|
+
priority: 2000,
|
396
|
+
say: (
|
397
|
+
connection: Connection,
|
398
|
+
room: string,
|
399
|
+
messagePayload: { from: number; message: string },
|
400
|
+
) => {
|
401
|
+
messagePayload.message = messagePayload.message + " MIDDLEWARE 2";
|
402
|
+
return messagePayload;
|
403
|
+
},
|
404
|
+
});
|
405
|
+
|
406
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
407
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
408
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
409
|
+
await utils.sleep(100);
|
410
|
+
|
411
|
+
const lastMessage = clientA.messages[clientA.messages.length - 1];
|
412
|
+
expect(lastMessage.message).toEqual("MIDDLEWARE 1 MIDDLEWARE 2");
|
413
|
+
});
|
414
|
+
|
415
|
+
test("say middleware can block execution", async () => {
|
416
|
+
chatRoom.addMiddleware({
|
417
|
+
name: "chat middleware",
|
418
|
+
say: () => {
|
419
|
+
throw new Error("messages blocked");
|
420
|
+
},
|
421
|
+
});
|
422
|
+
|
423
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
424
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
425
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
426
|
+
await utils.sleep(100);
|
427
|
+
|
428
|
+
// welcome message is passed, no join/leave/or say messages
|
429
|
+
expect(clientA.messages).toHaveLength(1);
|
430
|
+
expect(clientA.messages[0].welcome).toMatch(/Welcome/);
|
431
|
+
});
|
432
|
+
|
433
|
+
test("join middleware can block execution", async () => {
|
434
|
+
chatRoom.addMiddleware({
|
435
|
+
name: "chat middleware",
|
436
|
+
join: () => {
|
437
|
+
throw new Error("joining rooms blocked");
|
438
|
+
},
|
439
|
+
});
|
440
|
+
|
441
|
+
try {
|
442
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
443
|
+
throw new Error("should not get here");
|
444
|
+
} catch (error) {
|
445
|
+
expect(error.toString()).toEqual("Error: joining rooms blocked");
|
446
|
+
expect(clientA.rooms).toHaveLength(0);
|
447
|
+
}
|
448
|
+
});
|
449
|
+
|
450
|
+
test("leave middleware can block execution", async () => {
|
451
|
+
chatRoom.addMiddleware({
|
452
|
+
name: "chat middleware",
|
453
|
+
leave: () => {
|
454
|
+
throw new Error("Hotel California");
|
455
|
+
},
|
456
|
+
});
|
457
|
+
|
458
|
+
const didJoin = await clientA.verbs("roomAdd", "defaultRoom");
|
459
|
+
expect(didJoin).toEqual(true);
|
460
|
+
expect(clientA.rooms).toHaveLength(1);
|
461
|
+
expect(clientA.rooms[0]).toEqual("defaultRoom");
|
462
|
+
|
463
|
+
try {
|
464
|
+
await clientA.verbs("roomLeave", "defaultRoom");
|
465
|
+
throw new Error("should not get here");
|
466
|
+
} catch (error) {
|
467
|
+
expect(error.toString()).toEqual("Error: Hotel California");
|
468
|
+
expect(clientA.rooms).toHaveLength(1);
|
469
|
+
}
|
470
|
+
});
|
471
|
+
|
472
|
+
test("(say verb with async keyword) can modify message payloads", async () => {
|
473
|
+
chatRoom.addMiddleware({
|
474
|
+
name: "chat middleware",
|
475
|
+
say: async (
|
476
|
+
connection: Connection,
|
477
|
+
room: string,
|
478
|
+
messagePayload: any,
|
479
|
+
) => {
|
480
|
+
if (messagePayload.from !== 0) {
|
481
|
+
messagePayload.message = "something else";
|
482
|
+
}
|
483
|
+
return messagePayload;
|
484
|
+
},
|
485
|
+
});
|
486
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
487
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
488
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
489
|
+
await utils.sleep(100);
|
490
|
+
const lastMessage = clientA.messages[clientA.messages.length - 1];
|
491
|
+
expect(lastMessage.message).toEqual("something else");
|
492
|
+
});
|
493
|
+
|
494
|
+
test("can add middleware in a particular order and will be passed modified messagePayloads with both being async functions", async () => {
|
495
|
+
chatRoom.addMiddleware({
|
496
|
+
name: "chat middleware 1",
|
497
|
+
priority: 1000,
|
498
|
+
say: async (
|
499
|
+
connection: Connection,
|
500
|
+
room: string,
|
501
|
+
messagePayload: any,
|
502
|
+
) => {
|
503
|
+
messagePayload.message = "MIDDLEWARE 1";
|
504
|
+
return messagePayload;
|
505
|
+
},
|
506
|
+
});
|
507
|
+
|
508
|
+
chatRoom.addMiddleware({
|
509
|
+
name: "chat middleware 2",
|
510
|
+
priority: 2000,
|
511
|
+
say: async (
|
512
|
+
connection: Connection,
|
513
|
+
room: string,
|
514
|
+
messagePayload: any,
|
515
|
+
) => {
|
516
|
+
messagePayload.message = messagePayload.message + " MIDDLEWARE 2";
|
517
|
+
return messagePayload;
|
518
|
+
},
|
519
|
+
});
|
520
|
+
|
521
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
522
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
523
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
524
|
+
await utils.sleep(100);
|
525
|
+
|
526
|
+
const lastMessage = clientA.messages[clientA.messages.length - 1];
|
527
|
+
expect(lastMessage.message).toEqual("MIDDLEWARE 1 MIDDLEWARE 2");
|
528
|
+
});
|
529
|
+
|
530
|
+
test("say async function middleware can block execution", async () => {
|
531
|
+
chatRoom.addMiddleware({
|
532
|
+
name: "chat middleware",
|
533
|
+
say: async () => {
|
534
|
+
throw new Error("messages blocked");
|
535
|
+
},
|
536
|
+
});
|
537
|
+
|
538
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
539
|
+
await clientB.verbs("roomAdd", "defaultRoom");
|
540
|
+
await clientB.verbs("say", ["defaultRoom", "something", "awesome"]);
|
541
|
+
await utils.sleep(100);
|
542
|
+
|
543
|
+
// welcome message is passed, no join/leave/or say messages
|
544
|
+
expect(clientA.messages).toHaveLength(1);
|
545
|
+
expect(clientA.messages[0].welcome).toMatch(/Welcome/);
|
546
|
+
});
|
547
|
+
|
548
|
+
test("join async function middleware can block execution", async () => {
|
549
|
+
chatRoom.addMiddleware({
|
550
|
+
name: "chat middleware",
|
551
|
+
join: async () => {
|
552
|
+
throw new Error("joining rooms blocked");
|
553
|
+
},
|
554
|
+
});
|
555
|
+
|
556
|
+
try {
|
557
|
+
await clientA.verbs("roomAdd", "defaultRoom");
|
558
|
+
throw new Error("should not get here");
|
559
|
+
} catch (error) {
|
560
|
+
expect(error.toString()).toEqual("Error: joining rooms blocked");
|
561
|
+
expect(clientA.rooms).toHaveLength(0);
|
562
|
+
}
|
563
|
+
});
|
564
|
+
|
565
|
+
test("leave async function middleware can block execution", async () => {
|
566
|
+
chatRoom.addMiddleware({
|
567
|
+
name: "chat middleware",
|
568
|
+
leave: async () => {
|
569
|
+
throw new Error("Hotel California");
|
570
|
+
},
|
571
|
+
});
|
572
|
+
|
573
|
+
const didJoin = await clientA.verbs("roomAdd", "defaultRoom");
|
574
|
+
expect(didJoin).toEqual(true);
|
575
|
+
expect(clientA.rooms).toHaveLength(1);
|
576
|
+
expect(clientA.rooms[0]).toEqual("defaultRoom");
|
577
|
+
|
578
|
+
try {
|
579
|
+
await clientA.verbs("roomLeave", "defaultRoom");
|
580
|
+
throw new Error("should not get here");
|
581
|
+
} catch (error) {
|
582
|
+
expect(error.toString()).toEqual("Error: Hotel California");
|
583
|
+
expect(clientA.rooms).toHaveLength(1);
|
584
|
+
}
|
585
|
+
});
|
586
|
+
});
|
587
|
+
});
|
588
|
+
});
|
589
|
+
});
|