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,32 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
4
+ <meta http-equiv="content-language" content="en" />
5
+ <meta name="description" content="Actionhero.js" />
6
+ <link rel="icon" href="/public/favicon.ico" />
7
+ <title>Actionhero.js Swagger Documentation</title>
8
+
9
+ <link
10
+ rel="stylesheet"
11
+ type="text/css"
12
+ href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css"
13
+ />
14
+ <script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js"></script>
15
+ <script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
16
+ </head>
17
+
18
+ <body>
19
+ <div class="container">
20
+ <div id="swagger-ui" />
21
+ </div>
22
+
23
+ <script type="text/javascript">
24
+ const SwaggerUI = SwaggerUIBundle({
25
+ url: "/api/swagger",
26
+ dom_id: "#swagger-ui",
27
+ presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
28
+ plugins: [SwaggerUIBundle.plugins.DownloadUrl],
29
+ });
30
+ </script>
31
+ </body>
32
+ </html>
@@ -0,0 +1,322 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
4
+ <meta http-equiv="content-language" content="en" />
5
+ <meta name="description" content="actionhero.js" />
6
+ <title>actionhero.js WebSocket Load Test</title>
7
+ <script type="text/javascript" src="/public/javascript/ActionheroWebsocketClient.js"></script>
8
+
9
+ <style>
10
+ body {
11
+ margin: 0px;
12
+ padding: 0px;
13
+ font-family:"Trebuchet MS", Helvetica, sans-serif;
14
+ font-size: 14px;
15
+ }
16
+
17
+ #mainContainer {
18
+ height: 100%;
19
+ width: 100%;
20
+ }
21
+
22
+ #resultsContainer {
23
+ color: white;
24
+ background-color: gray;
25
+ height: 100%;
26
+ width: 300px;
27
+ text-align: left;
28
+ overflow: scroll;
29
+ float: left;
30
+ }
31
+
32
+ #optionsContainer {
33
+ background-color: orange;
34
+ height: 100%;
35
+ width: 200px;
36
+ text-align: left;
37
+ overflow: scroll;
38
+ float: left;
39
+ }
40
+
41
+ #testContainer {
42
+ background-color: lightblue;
43
+ margin-left: 500px;
44
+ height: 100%;
45
+ overflow: scroll;
46
+ }
47
+
48
+ form {
49
+ padding: 4px;
50
+ }
51
+
52
+ h1 {
53
+ color: lightgreen;
54
+ padding: 10px;
55
+ }
56
+
57
+ h2 {
58
+ color: darkgreen;
59
+ padding: 5px;
60
+ }
61
+
62
+ .smallWords {
63
+ font-style: italic;
64
+ padding: 5px;
65
+ }
66
+
67
+ .green {background-color: green;}
68
+ .red {background-color: red;}
69
+ .yellow {background-color: yellow;}
70
+ .gray {background-color: gray;}
71
+
72
+ .connection{
73
+ margin: 5px;
74
+ border: 2px solid black;
75
+ float: left;
76
+ }
77
+ </style>
78
+
79
+ <script type="text/javascript">
80
+
81
+ /////////
82
+ // APP //
83
+ /////////
84
+
85
+ var app = {};
86
+
87
+ app.defaults = function(){
88
+ return {
89
+ state: 'stopped',
90
+ clients: {},
91
+ config: {},
92
+ renderTimer: null,
93
+ stats: {
94
+ totalGood: 0,
95
+ totalBad: 0,
96
+ totalRequests: 0,
97
+ startTime: 0,
98
+ endTime: 0,
99
+ }
100
+ }
101
+ }
102
+
103
+ app.loadConfig = function(){
104
+ app.config.numClients = parseInt( document.getElementById('numClients').value );
105
+ app.config.numRequests = parseInt( document.getElementById('numRequests').value );
106
+ app.config.sleep = parseInt( document.getElementById('sleep').value );
107
+ app.config.action = document.getElementById('action').value;
108
+ app.config.params = JSON.parse(document.getElementById('params').value);
109
+ }
110
+
111
+ app.render = function(){
112
+ if(app.state === 'running'){
113
+ delta = (new Date().getTime() - app.stats.startTime) / 1000;
114
+ }else{
115
+ delta = (app.stats.endTime - app.stats.startTime) / 1000;
116
+ }
117
+
118
+ var totalTime = delta;
119
+ var reqPerSec = app.stats.totalRequests / delta;
120
+ var secPerReq = (delta / app.stats.totalRequests) * app.config.numClients;
121
+
122
+ document.getElementById('report.state').innerHTML = app.state;
123
+ document.getElementById('report.numClients').innerHTML = app.config.numClients;
124
+ document.getElementById('report.totalRequests').innerHTML = app.stats.totalRequests;
125
+ document.getElementById('report.totalTime').innerHTML = totalTime;
126
+ document.getElementById('report.totalGood').innerHTML = app.stats.totalGood;
127
+ document.getElementById('report.totalBad').innerHTML = app.stats.totalBad;
128
+ document.getElementById('report.reqPerSec').innerHTML = reqPerSec
129
+ document.getElementById('report.secPerReq').innerHTML = secPerReq
130
+ document.getElementById('report.percentGood').innerHTML = Math.round(app.stats.totalGood / (app.stats.totalGood + app.stats.totalBad) * 100)
131
+ }
132
+
133
+ app.renderLoop = function(){
134
+ app.render();
135
+ app.checkComplete();
136
+ if(app.state === 'running' || app.sate === 'stopped'){
137
+ setTimeout(function(){
138
+ app.renderLoop();
139
+ },100)
140
+ }else{
141
+ app.render();
142
+ }
143
+ }
144
+
145
+ app.checkComplete = function(){
146
+ var complete = true;
147
+ for(var i in app.clients){
148
+ var connection = app.clients[i];
149
+ if(connection.running != false){
150
+ complete = false;
151
+ break;
152
+ }
153
+ }
154
+ if(complete === true){
155
+ app.stats.endTime = new Date().getTime();
156
+ app.state = 'complete';
157
+ }
158
+ }
159
+
160
+ app.boot = function(){
161
+ app.clients = {};
162
+ for(var i in app.defaults()){
163
+ app[i] = app.defaults()[i];
164
+ }
165
+ app.loadConfig();
166
+
167
+ var rows = '';
168
+ var i = 0;
169
+ while(i < app.config.numClients){
170
+ rows += '<div class="connection" id="connection_'+i+'">';
171
+ rows += '<div id="id_'+i+'" class="gray">#'+i+'</div>';
172
+ rows += '<span id="good_'+i+'" style="color: green;">0</span>';
173
+ rows += " | "
174
+ rows += '<span id="bad_'+i+'" style="color: red;">0</span>';
175
+ rows += '</div>';
176
+ i++;
177
+ }
178
+
179
+ document.getElementById('boxes').innerHTML = rows;
180
+
181
+ var i = 0;
182
+ app.stats.startTime = new Date().getTime();
183
+ app.state = 'running';
184
+ while(i < app.config.numClients){
185
+ var c = new client(i);
186
+ c.connect();
187
+ app.clients[i] = c;
188
+ i++;
189
+ }
190
+
191
+ app.renderLoop();
192
+
193
+ return false;
194
+ }
195
+
196
+ ////////////
197
+ // CLIENT //
198
+ ////////////
199
+
200
+ var client = function(id){
201
+ var self = this;
202
+ self.running = null;
203
+ self.id = id;
204
+ self.goodCount = 0;
205
+ self.badCount = 0;
206
+ self.numRequests = 0;
207
+ }
208
+
209
+ client.prototype.connect = function(){
210
+ var self = this;
211
+ self.client = new ActionheroWebsocketClient();
212
+ self.client.on('connected', function(){ console.log('['+self.id+'] ' + 'connected!') })
213
+ self.client.on('disconnected', function(){ console.log('['+self.id+'] ' + 'disconnected :(') })
214
+ self.client.on('alert', function(message){ alert('['+self.id+'] ' + JSON.stringify(message) ) })
215
+ self.client.on('api', function(message){ alert('['+self.id+'] ' + JSON.stringify(message) ) })
216
+ self.client.on('welcome', function(message){ console.log('['+self.id+'] ' + JSON.stringify(message) ); })
217
+ self.client.on('say', function(message){ console.log('['+self.id+'] ' + JSON.stringify(message) ); })
218
+ self.client.connect(function(error, details){
219
+ if(error != null){
220
+ self.running = true;
221
+ console.log(error);
222
+ }else{
223
+ self.work();
224
+ }
225
+ });
226
+ }
227
+
228
+ client.prototype.work = function(){
229
+ var self = this;
230
+ document.getElementById('id_'+self.id).className = 'yellow'
231
+ self.client.action(app.config.action, app.config.params, function(data){
232
+ self.numRequests++;
233
+ app.stats.totalRequests++;
234
+ console.log('['+self.id+'] ' + JSON.stringify(data));
235
+ if(data.error == null){
236
+ self.goodCount++;
237
+ app.stats.totalGood++
238
+ }else{
239
+ self.badCount++;
240
+ app.stats.totalBad++;
241
+ }
242
+ document.getElementById('good_'+self.id).innerHTML = self.goodCount;
243
+ document.getElementById('bad_'+self.id).innerHTML = self.badCount;
244
+ if(self.numRequests >= app.config.numRequests){
245
+ // done!
246
+ if(self.badCount == 0){
247
+ document.getElementById('id_'+self.id).className = 'green';
248
+ }else{
249
+ document.getElementById('id_'+self.id).className = 'red';
250
+ }
251
+ self.running = false;
252
+ self.client.disconnect();
253
+ setTimeout(function(){
254
+ self.client.removeAllListeners('connected');
255
+ self.client.removeAllListeners('disconnected');
256
+ self.client.removeAllListeners('alert');
257
+ self.client.removeAllListeners('api');
258
+ self.client.removeAllListeners('welcome');
259
+ self.client.removeAllListeners('say');
260
+ },100);
261
+ }else{
262
+ setTimeout(function(){
263
+ self.work();
264
+ }, sleep)
265
+ }
266
+ });
267
+ }
268
+
269
+ </script>
270
+
271
+ </head>
272
+
273
+ <body>
274
+ <div id="mainContainer">
275
+
276
+ <div id="resultsContainer">
277
+ <h1>actionhero websocket load test</h1>
278
+ <p class="smallWords">Check the console for logs.<br />Be sure to update your ulimts!</p>
279
+ <ul id="results">
280
+ <li><strong>Test State</strong>: <span id="report.state"></span></li>
281
+ <li><strong>Connections</strong>: <span id="report.numClients"></span></li>
282
+ <li><strong>Total Requests</strong>: <span id="report.totalRequests"></span></li>
283
+ <li><strong>Total Time</strong>: <span id="report.totalTime"></span></li>
284
+ <li><strong>Total Good</strong>: <span id="report.totalGood"></span></li>
285
+ <li><strong>Total Bad</strong>: <span id="report.totalBad"></span></li>
286
+ <li><strong>Req/Sec</strong>: <span id="report.reqPerSec"></span></li>
287
+ <li><strong>Sec/Rec</strong>: <span id="report.secPerReq"></span></li>
288
+ <li><strong>% Good</strong>: <span id="report.percentGood"></span></li>
289
+ </ul>
290
+ </div>
291
+
292
+ <div id='optionsContainer'>
293
+ <h2>Options</h2>
294
+
295
+ <form id="form" action="#">
296
+ <label>Number of Clients:</label><br>
297
+ <input type="text" name="numClients" id="numClients" value="100"><br><br>
298
+
299
+ <label>Number of Requests:</label><br>
300
+ <input type="text" name="numRequests" id="numRequests" value="10"><br><br>
301
+
302
+ <label>Action:</label><br>
303
+ <input type="text" name="action" id="action" value="randomNumber"><br><br>
304
+
305
+ <label>Params (json):</label><br>
306
+ <input type="text" name="params" id="params" value='{"key": "key", "value": "value"}'><br><br>
307
+
308
+ <label>Sleep (ms):</label><br>
309
+ <input type="text" name="sleep" id="sleep" value="10"><br><br>
310
+
311
+ <button onclick="return app.boot()">Go!</button>
312
+ </form>
313
+ </div>
314
+
315
+ <div id='testContainer'>
316
+ <h2>Results</h2>
317
+ <div id='boxes'></div>
318
+ </div>
319
+
320
+ </div>
321
+ </body>
322
+ </html>
@@ -0,0 +1,58 @@
1
+ import { cache, Action, ParamsFrom } from "./../index";
2
+
3
+ export class CacheTest extends Action {
4
+ name = "cacheTest";
5
+ description = "I will test the internal cache functions of the API";
6
+ inputs = {
7
+ key: {
8
+ required: true as true,
9
+ formatter: this.stringFormatter,
10
+ validator: this.stringValidator,
11
+ },
12
+
13
+ value: {
14
+ required: true as true,
15
+ formatter: this.stringFormatter,
16
+ validator: this.stringValidator,
17
+ },
18
+ };
19
+
20
+ outputExample = {
21
+ cacheTestResults: {
22
+ saveResp: true,
23
+ sizeResp: 1,
24
+ loadResp: {
25
+ key: "cacheTest_key",
26
+ value: "value",
27
+ createdAt: 1420953269716,
28
+ },
29
+ deleteResp: true,
30
+ },
31
+ };
32
+
33
+ stringFormatter(s: unknown) {
34
+ return String(s);
35
+ }
36
+
37
+ stringValidator(s: string) {
38
+ if (s.length < 3) {
39
+ return "inputs should be at least 3 letters long";
40
+ } else {
41
+ return true;
42
+ }
43
+ }
44
+
45
+ async run({ params }: { params: ParamsFrom<CacheTest> }) {
46
+ const key = `cacheTest_${params.key}`;
47
+ const value = params.value;
48
+
49
+ return {
50
+ cacheTestResults: {
51
+ saveResp: await cache.save(key, value, 5000),
52
+ sizeResp: await cache.size(),
53
+ loadResp: await cache.load(key),
54
+ deleteResp: await cache.destroy(key),
55
+ },
56
+ };
57
+ }
58
+ }
@@ -0,0 +1,20 @@
1
+ import { chatRoom, Action, ParamsFrom } from "./../index";
2
+
3
+ export class CreateChatRoom extends Action {
4
+ name = "createChatRoom";
5
+ description = "I will create a chatroom with the given name";
6
+ inputs = {
7
+ name: { required: true as true },
8
+ };
9
+
10
+ async run({ params }: { params: ParamsFrom<CreateChatRoom> }) {
11
+ let didCreate = false;
12
+
13
+ if (!(await chatRoom.exists(params.name))) {
14
+ await chatRoom.add(params.name);
15
+ didCreate = true;
16
+ }
17
+
18
+ return { name: params.name, didCreate };
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { Action } from "./../index";
2
+
3
+ export class RandomNumber extends Action {
4
+ name = "randomNumber";
5
+ description = "I am an API method which will generate a random number";
6
+ outputExample = {
7
+ randomNumber: 0.123,
8
+ stringRandomNumber: "Your random number is 0.123",
9
+ };
10
+
11
+ async run() {
12
+ const randomNumber = Math.random();
13
+ const stringRandomNumber = `Your random number is ${randomNumber}`;
14
+
15
+ return { randomNumber, stringRandomNumber };
16
+ }
17
+ }
@@ -0,0 +1,13 @@
1
+ import { Action, action } from "./../index";
2
+
3
+ export class RecursiveAction extends Action {
4
+ name = "recursiveAction";
5
+ description = "I am an action that runs another action";
6
+ outputExample = {};
7
+
8
+ async run() {
9
+ const localResponse = { local: true };
10
+ const actionResponse = await action.run("randomNumber");
11
+ return Object.assign(actionResponse, localResponse);
12
+ }
13
+ }
@@ -0,0 +1,12 @@
1
+ import { Action, Connection } from "../index";
2
+
3
+ export class SendFile extends Action {
4
+ name = "sendFile";
5
+ description = "I send a file though an action";
6
+ outputExample = {};
7
+
8
+ async run(data: { connection: Connection; toRender: boolean }) {
9
+ await data.connection.sendFile("logo/actionhero.png");
10
+ data.toRender = false;
11
+ }
12
+ }
@@ -0,0 +1,40 @@
1
+ import { Action } from "./../index";
2
+
3
+ function sleep(time: number): Promise<void> {
4
+ return new Promise((resolve) => {
5
+ setTimeout(resolve, time);
6
+ });
7
+ }
8
+
9
+ export class SleepTest extends Action {
10
+ name = "sleepTest";
11
+ description = "I will sleep and then return";
12
+ inputs = {
13
+ sleepDuration: {
14
+ required: true as true,
15
+ formatter: (n: string) => {
16
+ return parseInt(n);
17
+ },
18
+ default: () => {
19
+ return 1000;
20
+ },
21
+ },
22
+ };
23
+ outputExample = {
24
+ sleepStarted: 1420953571322,
25
+ sleepEnded: 1420953572327,
26
+ sleepDelta: 1005,
27
+ sleepDuration: 1000,
28
+ };
29
+
30
+ async run({ params }: { params: { sleepDuration: number } }) {
31
+ const sleepDuration = params.sleepDuration;
32
+ const sleepStarted = new Date().getTime();
33
+
34
+ await sleep(sleepDuration);
35
+ const sleepEnded = new Date().getTime();
36
+ const sleepDelta = sleepEnded - sleepStarted;
37
+
38
+ return { sleepStarted, sleepEnded, sleepDelta, sleepDuration };
39
+ }
40
+ }
@@ -0,0 +1,73 @@
1
+ import { api, id, task, Action, actionheroVersion } from "./../index";
2
+ import { PackageJson } from "type-fest";
3
+ import * as path from "path";
4
+ import * as fs from "fs";
5
+
6
+ // These values are probably good starting points, but you should expect to tweak them for your application
7
+ const maxMemoryAlloted = process.env.maxMemoryAlloted
8
+ ? parseInt(process.env.maxMemoryAlloted)
9
+ : 500;
10
+ const maxResqueQueueLength = process.env.maxResqueQueueLength
11
+ ? parseInt(process.env.maxResqueQueueLength)
12
+ : 1000;
13
+
14
+ enum StatusMessages {
15
+ healthy = "Node Healthy",
16
+ unhealthy = "Node Unhealthy",
17
+ }
18
+
19
+ const packageJSON: PackageJson = JSON.parse(
20
+ fs
21
+ .readFileSync(
22
+ path.normalize(path.join(__dirname, "..", "..", "package.json")),
23
+ )
24
+ .toString(),
25
+ );
26
+
27
+ export class Status extends Action {
28
+ name = "status";
29
+ description = "I will return some basic information about the API";
30
+ outputExample = {
31
+ id: "192.168.2.11",
32
+ actionheroVersion: "9.4.1",
33
+ uptime: 10469,
34
+ };
35
+
36
+ async run() {
37
+ let nodeStatus = StatusMessages.healthy;
38
+ const problems: string[] = [];
39
+
40
+ const consumedMemoryMB =
41
+ Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100;
42
+ if (consumedMemoryMB > maxMemoryAlloted) {
43
+ nodeStatus = StatusMessages.unhealthy;
44
+ problems.push(`Using more than ${maxMemoryAlloted} MB of RAM/HEAP`);
45
+ }
46
+
47
+ let resqueTotalQueueLength = 0;
48
+ const details = await task.details();
49
+ let length = 0;
50
+ Object.keys(details.queues).forEach((q) => {
51
+ length += details.queues[q].length;
52
+ });
53
+ resqueTotalQueueLength = length;
54
+
55
+ if (length > maxResqueQueueLength) {
56
+ nodeStatus = StatusMessages.unhealthy;
57
+ problems.push(`Resque Queues over ${maxResqueQueueLength} jobs`);
58
+ }
59
+
60
+ return {
61
+ id: id,
62
+ actionheroVersion: actionheroVersion,
63
+ name: packageJSON.name as string,
64
+ description: packageJSON.description as string,
65
+ version: packageJSON.version as string,
66
+ uptime: new Date().getTime() - api.bootTime,
67
+ consumedMemoryMB,
68
+ resqueTotalQueueLength,
69
+ nodeStatus,
70
+ problems,
71
+ };
72
+ }
73
+ }