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.
Files changed (211) hide show
  1. package/.devcontainer/devcontainer.json +4 -0
  2. package/.devcontainer/setup.sh +11 -0
  3. package/.dockerignore +2 -0
  4. package/.github/CONTRIBUTING.md +52 -0
  5. package/.github/FUNDING.yml +3 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.yml +59 -0
  7. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
  9. package/.github/dependabot.yml +17 -0
  10. package/.github/workflows/codeql.yml +76 -0
  11. package/.github/workflows/publish_docs.yml +25 -0
  12. package/.github/workflows/test.yml +78 -0
  13. package/.nvmrc +1 -0
  14. package/.prettierignore +1 -0
  15. package/.prettierrc +1 -0
  16. package/.vscode/launch.json +42 -0
  17. package/CODE_OF_CONDUCT.md +76 -0
  18. package/Dockerfile +17 -0
  19. package/LICENSE +21 -0
  20. package/README.md +3 -0
  21. package/SECURITY.md +5 -0
  22. package/__tests__/actions/cacheTest.ts +58 -0
  23. package/__tests__/actions/randomNumber.ts +26 -0
  24. package/__tests__/actions/recursiveAction.ts +16 -0
  25. package/__tests__/actions/sleepTest.ts +24 -0
  26. package/__tests__/actions/status.ts +17 -0
  27. package/__tests__/actions/swagger.ts +76 -0
  28. package/__tests__/actions/validationTest.ts +63 -0
  29. package/__tests__/cli/cli.ts +126 -0
  30. package/__tests__/core/api.ts +632 -0
  31. package/__tests__/core/cache.ts +400 -0
  32. package/__tests__/core/chatRoom.ts +589 -0
  33. package/__tests__/core/cli.ts +349 -0
  34. package/__tests__/core/cluster.ts +132 -0
  35. package/__tests__/core/config.ts +78 -0
  36. package/__tests__/core/errors.ts +112 -0
  37. package/__tests__/core/log.ts +23 -0
  38. package/__tests__/core/middleware.ts +427 -0
  39. package/__tests__/core/plugins/partialPlugin.ts +94 -0
  40. package/__tests__/core/plugins/withPlugin.ts +88 -0
  41. package/__tests__/core/plugins/withoutPlugin.ts +81 -0
  42. package/__tests__/core/process.ts +42 -0
  43. package/__tests__/core/specHelper.ts +330 -0
  44. package/__tests__/core/staticFile/compression.ts +99 -0
  45. package/__tests__/core/staticFile/staticFile.ts +180 -0
  46. package/__tests__/core/tasks/customQueueFunction.ts +67 -0
  47. package/__tests__/core/tasks/fullWorkerFlow.ts +199 -0
  48. package/__tests__/core/tasks/tasks.ts +605 -0
  49. package/__tests__/integration/browser.ts +133 -0
  50. package/__tests__/integration/ioredis-mock.ts +194 -0
  51. package/__tests__/integration/sendBuffer.ts +97 -0
  52. package/__tests__/integration/sendFile.ts +24 -0
  53. package/__tests__/integration/sharedFingerprint.ts +82 -0
  54. package/__tests__/integration/taskFlow.ts +110 -0
  55. package/__tests__/jest.ts +5 -0
  56. package/__tests__/modules/action.ts +103 -0
  57. package/__tests__/modules/config.ts +19 -0
  58. package/__tests__/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +24 -0
  59. package/__tests__/servers/web/allowedRequestHosts.ts +88 -0
  60. package/__tests__/servers/web/enableMultiples.ts +83 -0
  61. package/__tests__/servers/web/fileUpload.ts +79 -0
  62. package/__tests__/servers/web/jsonp.ts +57 -0
  63. package/__tests__/servers/web/nonMultiples.ts +83 -0
  64. package/__tests__/servers/web/rawBody.ts +208 -0
  65. package/__tests__/servers/web/returnErrorCodes.ts +55 -0
  66. package/__tests__/servers/web/routes/deepRoutes.ts +96 -0
  67. package/__tests__/servers/web/routes/routes.ts +579 -0
  68. package/__tests__/servers/web/routes/veryDeepRoutes.ts +92 -0
  69. package/__tests__/servers/web/web.ts +1031 -0
  70. package/__tests__/servers/websocket.ts +795 -0
  71. package/__tests__/tasks/runAction.ts +37 -0
  72. package/__tests__/template.ts.example +20 -0
  73. package/__tests__/testCliCommands/hello.ts +44 -0
  74. package/__tests__/testPlugin/public/plugin.html +1 -0
  75. package/__tests__/testPlugin/src/actions/pluginAction.ts +14 -0
  76. package/__tests__/testPlugin/src/bin/hello.ts +22 -0
  77. package/__tests__/testPlugin/src/initializers/pluginInitializer.ts +17 -0
  78. package/__tests__/testPlugin/src/tasks/pluginTask.ts +15 -0
  79. package/__tests__/testPlugin/tsconfig.json +10 -0
  80. package/__tests__/utils/utils.ts +492 -0
  81. package/app.json +23 -0
  82. package/bin/deploy-docs +39 -0
  83. package/client/ActionheroWebsocketClient.js +277 -0
  84. package/docker-compose.yml +73 -0
  85. package/package.json +24 -0
  86. package/public/chat.html +194 -0
  87. package/public/css/cosmo.css +12 -0
  88. package/public/favicon.ico +0 -0
  89. package/public/index.html +115 -0
  90. package/public/javascript/.gitkeep +0 -0
  91. package/public/linkedSession.html +80 -0
  92. package/public/logo/actionhero-small.png +0 -0
  93. package/public/logo/actionhero.png +0 -0
  94. package/public/pixel.gif +0 -0
  95. package/public/simple.html +2 -0
  96. package/public/swagger.html +32 -0
  97. package/public/websocketLoadTest.html +322 -0
  98. package/src/actions/cacheTest.ts +58 -0
  99. package/src/actions/createChatRoom.ts +20 -0
  100. package/src/actions/randomNumber.ts +17 -0
  101. package/src/actions/recursiveAction.ts +13 -0
  102. package/src/actions/sendFile.ts +12 -0
  103. package/src/actions/sleepTest.ts +40 -0
  104. package/src/actions/status.ts +73 -0
  105. package/src/actions/swagger.ts +155 -0
  106. package/src/actions/validationTest.ts +36 -0
  107. package/src/bin/actionhero.ts +225 -0
  108. package/src/bin/methods/actions/list.ts +30 -0
  109. package/src/bin/methods/console.ts +26 -0
  110. package/src/bin/methods/generate/action.ts +58 -0
  111. package/src/bin/methods/generate/cli.ts +51 -0
  112. package/src/bin/methods/generate/initializer.ts +54 -0
  113. package/src/bin/methods/generate/plugin.ts +57 -0
  114. package/src/bin/methods/generate/server.ts +38 -0
  115. package/src/bin/methods/generate/task.ts +68 -0
  116. package/src/bin/methods/generate.ts +176 -0
  117. package/src/bin/methods/task/enqueue.ts +35 -0
  118. package/src/classes/action.ts +98 -0
  119. package/src/classes/actionProcessor.ts +463 -0
  120. package/src/classes/api.ts +51 -0
  121. package/src/classes/cli.ts +67 -0
  122. package/src/classes/config.ts +15 -0
  123. package/src/classes/connection.ts +321 -0
  124. package/src/classes/exceptionReporter.ts +9 -0
  125. package/src/classes/initializer.ts +59 -0
  126. package/src/classes/initializers.ts +5 -0
  127. package/src/classes/input.ts +9 -0
  128. package/src/classes/inputs.ts +34 -0
  129. package/src/classes/process/actionheroVersion.ts +15 -0
  130. package/src/classes/process/env.ts +16 -0
  131. package/src/classes/process/id.ts +34 -0
  132. package/src/classes/process/pid.ts +32 -0
  133. package/src/classes/process/projectRoot.ts +16 -0
  134. package/src/classes/process/typescript.ts +47 -0
  135. package/src/classes/process.ts +479 -0
  136. package/src/classes/server.ts +251 -0
  137. package/src/classes/task.ts +87 -0
  138. package/src/config/api.ts +107 -0
  139. package/src/config/errors.ts +162 -0
  140. package/src/config/logger.ts +113 -0
  141. package/src/config/plugins.ts +37 -0
  142. package/src/config/redis.ts +78 -0
  143. package/src/config/routes.ts +44 -0
  144. package/src/config/tasks.ts +84 -0
  145. package/src/config/web.ts +136 -0
  146. package/src/config/websocket.ts +62 -0
  147. package/src/index.ts +46 -0
  148. package/src/initializers/actions.ts +125 -0
  149. package/src/initializers/chatRoom.ts +214 -0
  150. package/src/initializers/connections.ts +124 -0
  151. package/src/initializers/exceptions.ts +155 -0
  152. package/src/initializers/params.ts +52 -0
  153. package/src/initializers/redis.ts +191 -0
  154. package/src/initializers/resque.ts +248 -0
  155. package/src/initializers/routes.ts +229 -0
  156. package/src/initializers/servers.ts +134 -0
  157. package/src/initializers/specHelper.ts +195 -0
  158. package/src/initializers/staticFile.ts +253 -0
  159. package/src/initializers/tasks.ts +188 -0
  160. package/src/modules/action.ts +89 -0
  161. package/src/modules/cache.ts +326 -0
  162. package/src/modules/chatRoom.ts +321 -0
  163. package/src/modules/config.ts +246 -0
  164. package/src/modules/log.ts +62 -0
  165. package/src/modules/redis.ts +93 -0
  166. package/src/modules/route.ts +59 -0
  167. package/src/modules/specHelper.ts +182 -0
  168. package/src/modules/task.ts +527 -0
  169. package/src/modules/utils/argv.ts +3 -0
  170. package/src/modules/utils/arrayStartingMatch.ts +21 -0
  171. package/src/modules/utils/arrayUnique.ts +15 -0
  172. package/src/modules/utils/collapseObjectToArray.ts +33 -0
  173. package/src/modules/utils/deepCopy.ts +3 -0
  174. package/src/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +19 -0
  175. package/src/modules/utils/eventLoopDelay.ts +34 -0
  176. package/src/modules/utils/fileUtils.ts +119 -0
  177. package/src/modules/utils/filterObjectForLogging.ts +51 -0
  178. package/src/modules/utils/filterResponseForLogging.ts +53 -0
  179. package/src/modules/utils/getExternalIPAddress.ts +17 -0
  180. package/src/modules/utils/hashMerge.ts +63 -0
  181. package/src/modules/utils/isPlainObject.ts +45 -0
  182. package/src/modules/utils/isRunning.ts +7 -0
  183. package/src/modules/utils/parseCookies.ts +20 -0
  184. package/src/modules/utils/parseHeadersForClientAddress.ts +53 -0
  185. package/src/modules/utils/parseIPv6URI.ts +24 -0
  186. package/src/modules/utils/replaceDistWithSrc.ts +9 -0
  187. package/src/modules/utils/safeGlob.ts +6 -0
  188. package/src/modules/utils/sleep.ts +8 -0
  189. package/src/modules/utils/sortGlobalMiddleware.ts +17 -0
  190. package/src/modules/utils/sourceRelativeLinkPath.ts +29 -0
  191. package/src/modules/utils.ts +66 -0
  192. package/src/server.ts +20 -0
  193. package/src/servers/web.ts +894 -0
  194. package/src/servers/websocket.ts +304 -0
  195. package/src/tasks/runAction.ts +29 -0
  196. package/tea.yaml +9 -0
  197. package/templates/README.md.template +17 -0
  198. package/templates/action.ts.template +15 -0
  199. package/templates/boot.js.template +9 -0
  200. package/templates/cli.ts.template +15 -0
  201. package/templates/gitignore.template +23 -0
  202. package/templates/initializer.ts.template +17 -0
  203. package/templates/package-plugin.json.template +12 -0
  204. package/templates/package.json.template +45 -0
  205. package/templates/projectMap.txt +39 -0
  206. package/templates/projectServer.ts.template +20 -0
  207. package/templates/server.ts.template +37 -0
  208. package/templates/task.ts.template +16 -0
  209. package/templates/test/action.ts.template +13 -0
  210. package/templates/test/task.ts.template +20 -0
  211. package/tsconfig.json +11 -0
@@ -0,0 +1,427 @@
1
+ import {
2
+ api,
3
+ Process,
4
+ config,
5
+ action,
6
+ utils,
7
+ specHelper,
8
+ ActionProcessor,
9
+ Connection,
10
+ } from "./../../src";
11
+
12
+ const actionhero = new Process();
13
+ let defaultMiddlewarePriority: number;
14
+
15
+ describe("Core: Middleware", () => {
16
+ beforeAll(async () => await actionhero.start());
17
+ afterAll(async () => await actionhero.stop());
18
+
19
+ beforeAll(() => {
20
+ defaultMiddlewarePriority = config!.general!
21
+ .defaultMiddlewarePriority as number;
22
+ });
23
+
24
+ afterEach(() => {
25
+ api.actions.middleware = {};
26
+ api.actions.globalMiddleware = [];
27
+ });
28
+
29
+ describe("action preProcessors", () => {
30
+ test("can define a global preProcessor and it can append the connection", async () => {
31
+ action.addMiddleware({
32
+ name: "test middleware",
33
+ global: true,
34
+ preProcessor: (data: ActionProcessor<any>) => {
35
+ data.response._preProcessorNote = "note";
36
+ },
37
+ });
38
+
39
+ const { _preProcessorNote, error } =
40
+ await specHelper.runAction<any>("randomNumber");
41
+ expect(error).toBeUndefined();
42
+ expect(_preProcessorNote).toEqual("note");
43
+ });
44
+
45
+ test("can define an async global preProcessor and it can append the connection", async () => {
46
+ action.addMiddleware({
47
+ name: "test middleware",
48
+ global: true,
49
+ preProcessor: async (data: ActionProcessor<any>) => {
50
+ await new Promise((resolve) => {
51
+ setTimeout(resolve, 100);
52
+ });
53
+ data.response._preProcessorNote = "slept";
54
+ },
55
+ });
56
+
57
+ const { _preProcessorNote, error } =
58
+ await specHelper.runAction<any>("randomNumber");
59
+ expect(error).toBeUndefined();
60
+ expect(_preProcessorNote).toEqual("slept");
61
+ });
62
+
63
+ test("can define a local preProcessor and it will not append the connection when not applied to the action", async () => {
64
+ action.addMiddleware({
65
+ name: "test middleware",
66
+ global: false,
67
+ preProcessor: (data: ActionProcessor<any>) => {
68
+ data.response._preProcessorNote = "note";
69
+ },
70
+ });
71
+
72
+ const { _preProcessorNote, error } =
73
+ await specHelper.runAction<any>("randomNumber");
74
+ expect(error).toBeUndefined();
75
+ expect(_preProcessorNote).toBeUndefined();
76
+ });
77
+
78
+ describe("middleware can read properties of the action template", () => {
79
+ const sessions: any[] = [];
80
+
81
+ beforeAll(() => {
82
+ api.actions.versions.authAction = [1];
83
+ api.actions.actions.authAction = {
84
+ 1: {
85
+ name: "authAction",
86
+ description: "I am a test",
87
+ version: 1,
88
+ //@ts-ignore
89
+ authenticated: true,
90
+ run: async ({ response, session }) => {
91
+ sessions.push(session);
92
+ response!.thing = "stuff";
93
+ },
94
+ },
95
+ };
96
+ });
97
+
98
+ afterAll(() => {
99
+ delete api.actions.actions.authAction;
100
+ delete api.actions.versions.authAction;
101
+ });
102
+
103
+ test("can read action template properties", async () => {
104
+ action.addMiddleware({
105
+ name: "auth middleware",
106
+ global: true,
107
+ preProcessor: (data: ActionProcessor<any>) => {
108
+ if (data.actionTemplate.authenticated === true) {
109
+ data.response.authenticatedAction = true;
110
+ } else {
111
+ data.response.authenticatedAction = false;
112
+ }
113
+ },
114
+ });
115
+
116
+ const randomResponse = await specHelper.runAction<any>("randomNumber");
117
+ expect(randomResponse.authenticatedAction).toEqual(false);
118
+
119
+ const authResponse = await specHelper.runAction<any>("authAction");
120
+ expect(authResponse.authenticatedAction).toEqual(true);
121
+ });
122
+
123
+ test("middleware can add data to the session", async () => {
124
+ action.addMiddleware({
125
+ name: "session middleware",
126
+ global: true,
127
+ preProcessor: async (data: ActionProcessor<any>) => {
128
+ data.session = { id: "abc123" };
129
+ },
130
+ });
131
+
132
+ await specHelper.runAction("authAction");
133
+ const lastSession = sessions.pop();
134
+ expect(lastSession.id).toBe("abc123");
135
+ });
136
+ });
137
+
138
+ test("preProcessors with priorities run in the right order", async () => {
139
+ // first priority
140
+ action.addMiddleware({
141
+ name: "first test middleware",
142
+ global: true,
143
+ priority: 1,
144
+ preProcessor: (data: ActionProcessor<any>) => {
145
+ data.response._processorNoteFirst = "first";
146
+ data.response._processorNoteEarly = "first";
147
+ data.response._processorNoteLate = "first";
148
+ data.response._processorNoteDefault = "first";
149
+ },
150
+ });
151
+
152
+ // lower number priority (runs sooner)
153
+ action.addMiddleware({
154
+ name: "early test middleware",
155
+ global: true,
156
+ priority: defaultMiddlewarePriority - 1,
157
+ preProcessor: (data: ActionProcessor<any>) => {
158
+ data.response._processorNoteEarly = "early";
159
+ data.response._processorNoteLate = "early";
160
+ data.response._processorNoteDefault = "early";
161
+ },
162
+ });
163
+
164
+ // old style "default" priority
165
+ action.addMiddleware({
166
+ name: "default test middleware",
167
+ global: true,
168
+ preProcessor: (data: ActionProcessor<any>) => {
169
+ data.response._processorNoteLate = "default";
170
+ data.response._processorNoteDefault = "default";
171
+ },
172
+ });
173
+
174
+ // higher number priority (runs later)
175
+ action.addMiddleware({
176
+ name: "late test middleware",
177
+ global: true,
178
+ priority: defaultMiddlewarePriority + 1,
179
+ preProcessor: (data: ActionProcessor<any>) => {
180
+ data.response._processorNoteLate = "late";
181
+ },
182
+ });
183
+
184
+ const response = await specHelper.runAction<any>("randomNumber");
185
+ expect(response._processorNoteFirst).toEqual("first");
186
+ expect(response._processorNoteEarly).toEqual("early");
187
+ expect(response._processorNoteDefault).toEqual("default");
188
+ expect(response._processorNoteLate).toEqual("late");
189
+ });
190
+
191
+ test("multiple preProcessors with same priority are executed", async () => {
192
+ action.addMiddleware({
193
+ name: "first test middleware",
194
+ global: true,
195
+ priority: defaultMiddlewarePriority - 1,
196
+ preProcessor: (data: ActionProcessor<any>) => {
197
+ data.response._processorNoteFirst = "first";
198
+ },
199
+ });
200
+
201
+ action.addMiddleware({
202
+ name: "late test middleware",
203
+ global: true,
204
+ priority: defaultMiddlewarePriority - 1,
205
+ preProcessor: (data: ActionProcessor<any>) => {
206
+ data.response._processorNoteSecond = "second";
207
+ },
208
+ });
209
+
210
+ const response = await specHelper.runAction<any>("randomNumber");
211
+ expect(response._processorNoteFirst).toEqual("first");
212
+ expect(response._processorNoteSecond).toEqual("second");
213
+ });
214
+
215
+ test("postProcessors can append the connection", async () => {
216
+ action.addMiddleware({
217
+ name: "test middleware",
218
+ global: true,
219
+ postProcessor: (data: ActionProcessor<any>) => {
220
+ data.response._postProcessorNote = "note";
221
+ },
222
+ });
223
+
224
+ const response = await specHelper.runAction<any>("randomNumber");
225
+ expect(response._postProcessorNote).toEqual("note");
226
+ });
227
+
228
+ test("postProcessors with priorities run in the right order", async () => {
229
+ // first priority
230
+ action.addMiddleware({
231
+ name: "first test middleware",
232
+ global: true,
233
+ priority: 1,
234
+ postProcessor: (data: ActionProcessor<any>) => {
235
+ data.response._processorNoteFirst = "first";
236
+ data.response._processorNoteEarly = "first";
237
+ data.response._processorNoteLate = "first";
238
+ data.response._processorNoteDefault = "first";
239
+ },
240
+ });
241
+
242
+ // lower number priority (runs sooner)
243
+ action.addMiddleware({
244
+ name: "early test middleware",
245
+ global: true,
246
+ priority: defaultMiddlewarePriority - 1,
247
+ postProcessor: (data: ActionProcessor<any>) => {
248
+ data.response._processorNoteEarly = "early";
249
+ data.response._processorNoteLate = "early";
250
+ data.response._processorNoteDefault = "early";
251
+ },
252
+ });
253
+
254
+ // old style "default" priority
255
+ action.addMiddleware({
256
+ name: "default test middleware",
257
+ global: true,
258
+ postProcessor: (data: ActionProcessor<any>) => {
259
+ data.response._processorNoteLate = "default";
260
+ data.response._processorNoteDefault = "default";
261
+ },
262
+ });
263
+
264
+ // higher number priority (runs later)
265
+ action.addMiddleware({
266
+ name: "late test middleware",
267
+ global: true,
268
+ priority: defaultMiddlewarePriority + 1,
269
+ postProcessor: (data: ActionProcessor<any>) => {
270
+ data.response._processorNoteLate = "late";
271
+ },
272
+ });
273
+
274
+ const response = await specHelper.runAction<any>("randomNumber");
275
+ expect(response._processorNoteFirst).toEqual("first");
276
+ expect(response._processorNoteEarly).toEqual("early");
277
+ expect(response._processorNoteDefault).toEqual("default");
278
+ expect(response._processorNoteLate).toEqual("late");
279
+ });
280
+
281
+ test("multiple postProcessors with same priority are executed", async () => {
282
+ action.addMiddleware({
283
+ name: "first middleware",
284
+ global: true,
285
+ priority: defaultMiddlewarePriority - 1,
286
+ postProcessor: (data: ActionProcessor<any>) => {
287
+ data.response._processorNoteFirst = "first";
288
+ },
289
+ });
290
+
291
+ action.addMiddleware({
292
+ name: "second middleware",
293
+ global: true,
294
+ priority: defaultMiddlewarePriority - 1,
295
+ postProcessor: (data: ActionProcessor<any>) => {
296
+ data.response._processorNoteSecond = "second";
297
+ },
298
+ });
299
+
300
+ const response = await specHelper.runAction<any>("randomNumber");
301
+ expect(response._processorNoteFirst).toEqual("first");
302
+ expect(response._processorNoteSecond).toEqual("second");
303
+ });
304
+
305
+ test("preProcessors can block actions", async () => {
306
+ action.addMiddleware({
307
+ name: "test middleware",
308
+ global: true,
309
+ preProcessor: function () {
310
+ throw new Error("BLOCKED");
311
+ },
312
+ });
313
+
314
+ const { randomNumber, error } =
315
+ await specHelper.runAction<any>("randomNumber");
316
+ expect(error).toEqual("Error: BLOCKED");
317
+ expect(randomNumber).toBeUndefined();
318
+ });
319
+
320
+ test("postProcessors can modify toRender", async () => {
321
+ action.addMiddleware({
322
+ name: "test middleware",
323
+ global: true,
324
+ postProcessor: (data: ActionProcessor<any>) => {
325
+ data.toRender = false;
326
+ },
327
+ });
328
+
329
+ await new Promise((resolve, reject) => {
330
+ setTimeout(() => {
331
+ resolve(null);
332
+ }, 1000);
333
+ specHelper.runAction("randomNumber").then(() => {
334
+ throw new Error("should.not.get.here");
335
+ });
336
+ });
337
+ });
338
+ });
339
+
340
+ describe("connection sync create/destroy callbacks", () => {
341
+ let connection: Connection;
342
+ beforeEach(() => {
343
+ api.connections.middleware = {};
344
+ api.connections.globalMiddleware = [];
345
+ });
346
+
347
+ afterEach(() => {
348
+ api.connections.middleware = {};
349
+ api.connections.globalMiddleware = [];
350
+ });
351
+
352
+ test("can create callbacks on connection creation", async () => {
353
+ let middlewareRan = false;
354
+ api.connections.addMiddleware({
355
+ name: "connection middleware",
356
+ create: (_connection: Connection) => {
357
+ middlewareRan = true;
358
+ //@ts-ignore
359
+ _connection["touched"] = "connect";
360
+ },
361
+ });
362
+
363
+ connection = await specHelper.buildConnection();
364
+
365
+ expect(middlewareRan).toEqual(true);
366
+ //@ts-ignore
367
+ expect(connection["touched"]).toEqual("connect");
368
+ });
369
+
370
+ test("can create callbacks on connection destroy", async () => {
371
+ let middlewareRan = false;
372
+ api.connections.addMiddleware({
373
+ name: "connection middleware",
374
+ destroy: (_connection: Connection) => {
375
+ middlewareRan = true;
376
+ //@ts-ignore
377
+ expect(_connection["touched"]).toEqual("connect");
378
+ },
379
+ });
380
+
381
+ connection.destroy();
382
+ expect(middlewareRan).toEqual(true);
383
+ });
384
+ });
385
+
386
+ describe("connection async create/destroy callbacks", () => {
387
+ beforeEach(() => {
388
+ api.connections.middleware = {};
389
+ api.connections.globalMiddleware = [];
390
+ });
391
+
392
+ afterEach(() => {
393
+ api.connections.middleware = {};
394
+ api.connections.globalMiddleware = [];
395
+ });
396
+
397
+ test("can create async callbacks on connection create/destroy", async () => {
398
+ let middlewareRan = false;
399
+ let middlewareDestroyRan = false;
400
+
401
+ api.connections.addMiddleware({
402
+ name: "connection middleware",
403
+ create: async (_connection: Connection) => {
404
+ middlewareRan = true;
405
+ await utils.sleep(1);
406
+ //@ts-ignore
407
+ _connection["longProcessResult"] = true;
408
+ },
409
+ destroy: async (_connection: Connection) => {
410
+ await utils.sleep(1);
411
+ middlewareDestroyRan = true;
412
+ },
413
+ });
414
+
415
+ const connection = await specHelper.buildConnection();
416
+
417
+ // create
418
+ expect(middlewareRan).toEqual(true);
419
+ //@ts-ignore
420
+ expect(connection["longProcessResult"]).toEqual(true);
421
+
422
+ // destroy
423
+ await connection.destroy();
424
+ expect(middlewareDestroyRan).toEqual(true);
425
+ });
426
+ });
427
+ });
@@ -0,0 +1,94 @@
1
+ import * as path from "path";
2
+ import * as ChildProcess from "child_process";
3
+
4
+ process.env.ACTIONHERO_CONFIG_OVERRIDES = JSON.stringify({
5
+ plugins: {
6
+ testPlugin: {
7
+ path: path.join(__dirname, "..", "..", "testPlugin"),
8
+ actions: false,
9
+ tasks: false,
10
+ servers: false,
11
+ initializers: false,
12
+ public: false,
13
+ cli: false,
14
+ },
15
+ },
16
+ });
17
+
18
+ import { api, Process, specHelper } from "../../../src/index";
19
+
20
+ const actionhero = new Process();
21
+
22
+ async function exec(
23
+ command: string,
24
+ args: Record<string, any>,
25
+ ): Promise<{
26
+ error?: NodeJS.ErrnoException;
27
+ stdout?: string;
28
+ stderr?: string;
29
+ }> {
30
+ return new Promise((resolve, reject) => {
31
+ ChildProcess.exec(command, args, (error, stdout, stderr) => {
32
+ if (error) {
33
+ return reject(error);
34
+ }
35
+ return resolve({ stdout: stdout.toString(), stderr: stderr.toString() });
36
+ });
37
+ });
38
+ }
39
+
40
+ describe("Core: Plugins", () => {
41
+ describe("with plugin sections ignored", () => {
42
+ beforeAll(async () => {
43
+ await actionhero.start();
44
+ });
45
+
46
+ afterAll(async () => {
47
+ await actionhero.stop();
48
+ });
49
+
50
+ test("will not load an action from an un-loaded plugin", async () => {
51
+ const response = await specHelper.runAction("pluginAction");
52
+ expect(response.error).toMatch(/unknown action or invalid apiVersion/);
53
+ });
54
+
55
+ test("will not load a task from an un-loaded plugin", () => {
56
+ expect(api.tasks.tasks.pluginTask).not.toBeTruthy();
57
+ expect(api.tasks.jobs.pluginTask).not.toBeTruthy();
58
+ });
59
+
60
+ test("will not load an initializer from an un-loaded plugin", () => {
61
+ expect(api.pluginInitializer).not.toBeTruthy();
62
+ });
63
+
64
+ // test('will not load a server from an un-loaded plugin')
65
+
66
+ test("will not serve static files from an un-loaded plugin", async () => {
67
+ const file = await specHelper.getStaticFile("plugin.html");
68
+ expect(file.error).toMatch(/file is not found/);
69
+ });
70
+
71
+ test(
72
+ "will not load CLI command from an un-loaded plugin",
73
+ async () => {
74
+ const { stdout: helpResponse, stderr: error1 } = await exec(
75
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts help",
76
+ { env: process.env },
77
+ );
78
+ expect(error1).toEqual("");
79
+ expect(helpResponse).not.toContain("hello");
80
+
81
+ try {
82
+ await exec(
83
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts hello",
84
+ { env: process.env },
85
+ );
86
+ throw new Error("should not get here");
87
+ } catch (error) {
88
+ expect(error.toString()).toMatch(/unknown command 'hello'/);
89
+ }
90
+ },
91
+ 30 * 1000,
92
+ );
93
+ });
94
+ });
@@ -0,0 +1,88 @@
1
+ import * as path from "path";
2
+ import * as ChildProcess from "child_process";
3
+
4
+ process.env.ACTIONHERO_CONFIG_OVERRIDES = JSON.stringify({
5
+ plugins: {
6
+ testPlugin: { path: path.join(__dirname, "..", "..", "testPlugin") },
7
+ },
8
+ });
9
+
10
+ import { api, Process, specHelper } from "../../../src/index";
11
+
12
+ const actionhero = new Process();
13
+
14
+ async function exec(
15
+ command: string,
16
+ args: Record<string, any>,
17
+ ): Promise<{
18
+ error?: NodeJS.ErrnoException;
19
+ stdout?: string;
20
+ stderr?: string;
21
+ }> {
22
+ return new Promise((resolve, reject) => {
23
+ ChildProcess.exec(command, args, (error, stdout, stderr) => {
24
+ if (error) {
25
+ return reject(error);
26
+ }
27
+ return resolve({ stdout: stdout.toString(), stderr: stderr.toString() });
28
+ });
29
+ });
30
+ }
31
+
32
+ describe("Core: Plugins", () => {
33
+ describe("with plugin", () => {
34
+ beforeAll(async () => {
35
+ await actionhero.start();
36
+ });
37
+
38
+ afterAll(async () => {
39
+ delete process.env.ACTIONHERO_CONFIG_OVERRIDES;
40
+ await actionhero.stop();
41
+ });
42
+
43
+ test("can load an action from a plugin", async () => {
44
+ const response = await specHelper.runAction<any>("pluginAction");
45
+ expect(response.error).toBeUndefined();
46
+ expect(response.cool).toEqual(true);
47
+ });
48
+
49
+ test("can load a task from a plugin", () => {
50
+ expect(api.tasks.tasks.pluginTask).toBeTruthy();
51
+ expect(api.tasks.jobs.pluginTask).toBeTruthy();
52
+ });
53
+
54
+ test("can load an initializer from a plugin", () => {
55
+ expect(api.pluginInitializer.here).toEqual(true);
56
+ });
57
+
58
+ test.todo("can load a server from a plugin");
59
+
60
+ test("can serve static files from a plugin", async () => {
61
+ const file = await specHelper.getStaticFile("plugin.html");
62
+ expect(file.content).toEqual("<h1>PLUGIN!<h1>\n");
63
+ expect(file.mime).toEqual("text/html");
64
+ });
65
+
66
+ test(
67
+ "can load CLI command from a plugin",
68
+ async () => {
69
+ const env = process.env;
70
+
71
+ const { stdout: helpResponse, stderr: error1 } = await exec(
72
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts help",
73
+ { env },
74
+ );
75
+ expect(error1).toEqual("");
76
+ expect(helpResponse).toContain("hello");
77
+
78
+ const { stdout: helloResponse, stderr: error2 } = await exec(
79
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts hello",
80
+ { env },
81
+ );
82
+ expect(error2).toEqual("");
83
+ expect(helloResponse).toContain("Hello, Actionhero");
84
+ },
85
+ 30 * 1000,
86
+ );
87
+ });
88
+ });
@@ -0,0 +1,81 @@
1
+ import * as ChildProcess from "child_process";
2
+
3
+ process.env.ACTIONHERO_CONFIG_OVERRIDES = JSON.stringify({
4
+ plugins: {},
5
+ });
6
+
7
+ import { api, Process, specHelper } from "../../../src/index";
8
+
9
+ const actionhero = new Process();
10
+
11
+ async function exec(
12
+ command: string,
13
+ args: Record<string, any>,
14
+ ): Promise<{
15
+ error?: NodeJS.ErrnoException;
16
+ stdout?: string;
17
+ stderr?: string;
18
+ }> {
19
+ return new Promise((resolve, reject) => {
20
+ ChildProcess.exec(command, args, (error, stdout, stderr) => {
21
+ if (error) {
22
+ return reject(error);
23
+ }
24
+ return resolve({ stdout: stdout.toString(), stderr: stderr.toString() });
25
+ });
26
+ });
27
+ }
28
+
29
+ describe("Core: Plugins", () => {
30
+ describe("without plugin", () => {
31
+ beforeAll(async () => {
32
+ await actionhero.start();
33
+ });
34
+
35
+ afterAll(async () => {
36
+ await actionhero.stop();
37
+ });
38
+
39
+ test("will not load an action from an un-loaded plugin", async () => {
40
+ const response = await specHelper.runAction("pluginAction");
41
+ expect(response.error).toMatch(/unknown action or invalid apiVersion/);
42
+ });
43
+
44
+ test("will not load a task from an un-loaded plugin", () => {
45
+ expect(api.tasks.tasks.pluginTask).not.toBeTruthy();
46
+ expect(api.tasks.jobs.pluginTask).not.toBeTruthy();
47
+ });
48
+
49
+ test("will not load an initializer from an un-loaded plugin", () => {
50
+ expect(api.pluginInitializer).not.toBeTruthy();
51
+ });
52
+
53
+ // test('will not load a server from an un-loaded plugin')
54
+ test("will not serve static files from an un-loaded plugin", async () => {
55
+ const file = await specHelper.getStaticFile("plugin.html");
56
+ expect(file.error).toMatch(/file is not found/);
57
+ });
58
+
59
+ test(
60
+ "will not load CLI command from an un-loaded plugin",
61
+ async () => {
62
+ const { stdout: helpResponse, stderr: error1 } = await exec(
63
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts help",
64
+ { env: process.env },
65
+ );
66
+ expect(error1).toEqual("");
67
+ expect(helpResponse).not.toContain("hello");
68
+ try {
69
+ await exec(
70
+ "./node_modules/.bin/ts-node ./src/bin/actionhero.ts hello",
71
+ { env: process.env },
72
+ );
73
+ throw new Error("should not get here");
74
+ } catch (error) {
75
+ expect(error.toString()).toMatch(/unknown command 'hello'/);
76
+ }
77
+ },
78
+ 30 * 1000,
79
+ );
80
+ });
81
+ });