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,304 @@
|
|
1
|
+
import * as Primus from "primus";
|
2
|
+
import * as fs from "fs";
|
3
|
+
import * as path from "path";
|
4
|
+
import * as util from "util";
|
5
|
+
import * as uuid from "uuid";
|
6
|
+
import { api, config, utils, log, Server, Connection } from "../index";
|
7
|
+
|
8
|
+
export class WebSocketServer extends Server {
|
9
|
+
server: Primus;
|
10
|
+
|
11
|
+
constructor() {
|
12
|
+
super();
|
13
|
+
this.type = "websocket";
|
14
|
+
|
15
|
+
this.attributes = {
|
16
|
+
canChat: true,
|
17
|
+
logConnections: true,
|
18
|
+
logExits: true,
|
19
|
+
sendWelcomeMessage: true,
|
20
|
+
verbs: [
|
21
|
+
"quit",
|
22
|
+
"exit",
|
23
|
+
"documentation",
|
24
|
+
"roomAdd",
|
25
|
+
"roomLeave",
|
26
|
+
"roomView",
|
27
|
+
"detailsView",
|
28
|
+
"say",
|
29
|
+
],
|
30
|
+
};
|
31
|
+
}
|
32
|
+
|
33
|
+
async initialize() {
|
34
|
+
// we rely on the web server :D
|
35
|
+
}
|
36
|
+
|
37
|
+
async start() {
|
38
|
+
const webserver = api.servers.servers.web;
|
39
|
+
if (!webserver) {
|
40
|
+
throw new Error(`websocket server requires web server to be enabled`);
|
41
|
+
}
|
42
|
+
|
43
|
+
this.server = new Primus(webserver.server, this.config.server);
|
44
|
+
|
45
|
+
this.writeClientJS();
|
46
|
+
|
47
|
+
this.server.on("connection", (rawConnection) => {
|
48
|
+
this.handleConnection(rawConnection);
|
49
|
+
});
|
50
|
+
|
51
|
+
this.server.on("disconnection", (rawConnection) => {
|
52
|
+
this.handleDisconnection(rawConnection);
|
53
|
+
});
|
54
|
+
|
55
|
+
this.log(
|
56
|
+
`webSockets bound to ${webserver.config.bindIP}:${webserver.config.port}`,
|
57
|
+
"debug",
|
58
|
+
);
|
59
|
+
|
60
|
+
this.on("connection", (connection: Connection) => {
|
61
|
+
connection.rawConnection.on("data", (data: Record<string, any>) => {
|
62
|
+
this.handleData(connection, data);
|
63
|
+
});
|
64
|
+
});
|
65
|
+
|
66
|
+
this.on("actionComplete", (data) => {
|
67
|
+
if (data.toRender !== false) {
|
68
|
+
data.connection.response.messageId = data.messageId;
|
69
|
+
this.sendMessage(data.connection, data.response, data.messageId);
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
|
74
|
+
async stop() {
|
75
|
+
if (!this.server) return;
|
76
|
+
|
77
|
+
if (this.config.destroyClientsOnShutdown === true) {
|
78
|
+
this.connections().forEach((connection: Connection) => {
|
79
|
+
connection.destroy();
|
80
|
+
});
|
81
|
+
}
|
82
|
+
|
83
|
+
//@ts-ignore
|
84
|
+
this.server.destroy();
|
85
|
+
}
|
86
|
+
|
87
|
+
async sendMessage(
|
88
|
+
connection: Connection,
|
89
|
+
message: Record<string, any>,
|
90
|
+
messageId: string,
|
91
|
+
) {
|
92
|
+
if (message.error) {
|
93
|
+
message.error = config.errors.serializers.servers.websocket(
|
94
|
+
message.error,
|
95
|
+
);
|
96
|
+
}
|
97
|
+
|
98
|
+
if (!message.context) {
|
99
|
+
message.context = "response";
|
100
|
+
}
|
101
|
+
if (!messageId) {
|
102
|
+
messageId = connection.messageId;
|
103
|
+
}
|
104
|
+
if (message.context === "response" && !message.messageId) {
|
105
|
+
message.messageId = messageId;
|
106
|
+
}
|
107
|
+
|
108
|
+
connection.rawConnection.write(message);
|
109
|
+
}
|
110
|
+
|
111
|
+
async sendFile(
|
112
|
+
connection: Connection,
|
113
|
+
error: NodeJS.ErrnoException,
|
114
|
+
fileStream: any,
|
115
|
+
mime: string,
|
116
|
+
length: number,
|
117
|
+
lastModified: Date,
|
118
|
+
) {
|
119
|
+
const messageId = connection.messageId;
|
120
|
+
let content = "";
|
121
|
+
const response = {
|
122
|
+
error: error,
|
123
|
+
content: null as string,
|
124
|
+
mime: mime,
|
125
|
+
length: length,
|
126
|
+
lastModified: lastModified,
|
127
|
+
};
|
128
|
+
|
129
|
+
try {
|
130
|
+
if (!error) {
|
131
|
+
fileStream.on("data", (d: string) => {
|
132
|
+
content += d;
|
133
|
+
});
|
134
|
+
fileStream.on("end", () => {
|
135
|
+
response.content = content;
|
136
|
+
this.sendMessage(connection, response, messageId);
|
137
|
+
});
|
138
|
+
} else {
|
139
|
+
this.sendMessage(connection, response, messageId);
|
140
|
+
}
|
141
|
+
} catch (e) {
|
142
|
+
this.log(e, "warning");
|
143
|
+
this.sendMessage(connection, response, messageId);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
//@ts-ignore
|
148
|
+
goodbye(connection: Connection) {
|
149
|
+
connection.rawConnection.end();
|
150
|
+
}
|
151
|
+
|
152
|
+
compileActionheroWebsocketClientJS() {
|
153
|
+
let ahClientSource = fs
|
154
|
+
.readFileSync(
|
155
|
+
path.join(__dirname, "/../../client/ActionheroWebsocketClient.js"),
|
156
|
+
)
|
157
|
+
.toString();
|
158
|
+
const url = this.config.clientUrl;
|
159
|
+
ahClientSource = ahClientSource.replace(/%%URL%%/g, url);
|
160
|
+
const defaults: {
|
161
|
+
[key: string]: any;
|
162
|
+
} = {};
|
163
|
+
|
164
|
+
for (const i in this.config.client) {
|
165
|
+
defaults[i] = this.config.client[i];
|
166
|
+
}
|
167
|
+
|
168
|
+
defaults.url = url;
|
169
|
+
let defaultsString = util.inspect(defaults);
|
170
|
+
defaultsString = defaultsString.replace(
|
171
|
+
"'window.location.origin'",
|
172
|
+
"window.location.origin",
|
173
|
+
);
|
174
|
+
ahClientSource = ahClientSource.replace(
|
175
|
+
"%%DEFAULTS%%",
|
176
|
+
"return " + defaultsString,
|
177
|
+
);
|
178
|
+
|
179
|
+
return ahClientSource;
|
180
|
+
}
|
181
|
+
|
182
|
+
renderClientJS() {
|
183
|
+
const libSource = api.servers.servers.websocket.server.library();
|
184
|
+
let ahClientSource = this.compileActionheroWebsocketClientJS();
|
185
|
+
ahClientSource =
|
186
|
+
";;;\r\n" +
|
187
|
+
"(function(exports){ \r\n" +
|
188
|
+
ahClientSource +
|
189
|
+
"\r\n" +
|
190
|
+
"exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n" +
|
191
|
+
"exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n" +
|
192
|
+
"})(typeof exports === 'undefined' ? window : exports);";
|
193
|
+
|
194
|
+
return libSource + "\r\n\r\n\r\n" + ahClientSource;
|
195
|
+
}
|
196
|
+
|
197
|
+
writeClientJS() {
|
198
|
+
if (
|
199
|
+
!config.general.paths.public ||
|
200
|
+
config.general.paths.public.length === 0
|
201
|
+
) {
|
202
|
+
return;
|
203
|
+
}
|
204
|
+
|
205
|
+
if (this.config.clientJsPath && this.config.clientJsName) {
|
206
|
+
const clientJSPath = path.normalize(
|
207
|
+
config.general.paths.public[0] +
|
208
|
+
path.sep +
|
209
|
+
this.config.clientJsPath +
|
210
|
+
path.sep,
|
211
|
+
);
|
212
|
+
const clientJSName = this.config.clientJsName;
|
213
|
+
const clientJSFullPath = clientJSPath + clientJSName;
|
214
|
+
try {
|
215
|
+
if (!fs.existsSync(clientJSPath)) {
|
216
|
+
fs.mkdirSync(clientJSPath, { recursive: true });
|
217
|
+
}
|
218
|
+
fs.writeFileSync(clientJSFullPath + ".js", this.renderClientJS());
|
219
|
+
log(`wrote ${clientJSFullPath}.js`, "debug");
|
220
|
+
} catch (e) {
|
221
|
+
log("Cannot write client-side JS for websocket server:", "alert", e);
|
222
|
+
throw e;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
handleConnection(rawConnection: Primus.Spark) {
|
228
|
+
const fingerprint =
|
229
|
+
rawConnection.query[config.web.fingerprintOptions.cookieKey];
|
230
|
+
const { ip, port } = utils.parseHeadersForClientAddress(
|
231
|
+
rawConnection.headers,
|
232
|
+
);
|
233
|
+
|
234
|
+
this.buildConnection({
|
235
|
+
rawConnection: rawConnection,
|
236
|
+
remoteAddress: ip || rawConnection.address.ip,
|
237
|
+
remotePort: port || rawConnection.address.port,
|
238
|
+
fingerprint: fingerprint,
|
239
|
+
});
|
240
|
+
}
|
241
|
+
|
242
|
+
handleDisconnection(rawConnection: Primus.Spark) {
|
243
|
+
const connections = this.connections();
|
244
|
+
for (const i in connections) {
|
245
|
+
if (
|
246
|
+
connections[i] &&
|
247
|
+
rawConnection.id === connections[i].rawConnection.id
|
248
|
+
) {
|
249
|
+
connections[i].destroy();
|
250
|
+
break;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
async handleData(connection: Connection, data: Record<string, any>) {
|
256
|
+
const verb = data.event;
|
257
|
+
delete data.event;
|
258
|
+
|
259
|
+
connection.messageId = data.messageId || uuid.v4();
|
260
|
+
delete data.messageId;
|
261
|
+
connection.params = {};
|
262
|
+
|
263
|
+
if (verb === "action") {
|
264
|
+
for (const v in data.params) {
|
265
|
+
connection.params[v] = data.params[v];
|
266
|
+
}
|
267
|
+
connection.error = null;
|
268
|
+
connection.response = {};
|
269
|
+
return this.processAction(connection);
|
270
|
+
}
|
271
|
+
|
272
|
+
if (verb === "file") {
|
273
|
+
connection.params = {
|
274
|
+
file: data.file,
|
275
|
+
};
|
276
|
+
return this.processFile(connection);
|
277
|
+
}
|
278
|
+
|
279
|
+
const words = [];
|
280
|
+
let message;
|
281
|
+
if (data.room) {
|
282
|
+
words.push(data.room);
|
283
|
+
delete data.room;
|
284
|
+
}
|
285
|
+
for (const i in data) {
|
286
|
+
words.push(data[i]);
|
287
|
+
}
|
288
|
+
const messageId = connection.messageId;
|
289
|
+
try {
|
290
|
+
const data = await connection.verbs(verb, words);
|
291
|
+
message = { status: "OK", context: "response", data: data };
|
292
|
+
return this.sendMessage(connection, message, messageId);
|
293
|
+
} catch (error) {
|
294
|
+
const formattedError = error.toString();
|
295
|
+
message = {
|
296
|
+
status: formattedError,
|
297
|
+
error: formattedError,
|
298
|
+
context: "response",
|
299
|
+
data: data,
|
300
|
+
};
|
301
|
+
return this.sendMessage(connection, message, messageId);
|
302
|
+
}
|
303
|
+
}
|
304
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { log, Task, action, ParamsFrom } from "./../index";
|
2
|
+
|
3
|
+
export class RunAction extends Task {
|
4
|
+
name = "runAction";
|
5
|
+
description = "I will run an action and return the connection object";
|
6
|
+
frequency = 0;
|
7
|
+
queue = "default";
|
8
|
+
|
9
|
+
async run(params: ParamsFrom<RunAction>) {
|
10
|
+
if (!params) params = {};
|
11
|
+
|
12
|
+
const response = await action.run(
|
13
|
+
params.action,
|
14
|
+
params.version,
|
15
|
+
// @ts-ignore
|
16
|
+
params.params,
|
17
|
+
);
|
18
|
+
|
19
|
+
if (response.error) {
|
20
|
+
log("task error: " + response.error, "error", {
|
21
|
+
params: JSON.stringify(params),
|
22
|
+
});
|
23
|
+
} else {
|
24
|
+
log("[ action @ task ]", "debug", { params: JSON.stringify(params) });
|
25
|
+
}
|
26
|
+
|
27
|
+
return response;
|
28
|
+
}
|
29
|
+
}
|
package/tea.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# https://tea.xyz/what-is-this-file
|
2
|
+
---
|
3
|
+
version: 1.0.0
|
4
|
+
codeOwners:
|
5
|
+
- '0xa98810E2e6651F5bD3B6228a798e26C4e3C08862'
|
6
|
+
- '0x6EA07435C33111F3A2e8526da031391b209D2637'
|
7
|
+
- '0x3287b8E6A699fDdB844fD7bb5BB1B77bB4673c42'
|
8
|
+
- '0x18Ad36Faa96CadC9553675C8F67077FFa3f266c1'
|
9
|
+
quorum: 1
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# My actionhero Project
|
2
|
+
|
3
|
+
_visit www.actionherojs.com for more information_
|
4
|
+
|
5
|
+
## To install:
|
6
|
+
|
7
|
+
(assuming you have [node](http://nodejs.org/), [TypeScript](https://www.typescriptlang.org/), and NPM installed)
|
8
|
+
|
9
|
+
`npm install`
|
10
|
+
|
11
|
+
## To Run:
|
12
|
+
|
13
|
+
`npm start`
|
14
|
+
|
15
|
+
## To Test:
|
16
|
+
|
17
|
+
`npm test`
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { Action } from "actionhero";
|
2
|
+
|
3
|
+
export class MyAction extends Action {
|
4
|
+
constructor() {
|
5
|
+
super();
|
6
|
+
this.name = "%%name%%";
|
7
|
+
this.description = "%%description%%";
|
8
|
+
this.outputExample = {};
|
9
|
+
}
|
10
|
+
|
11
|
+
async run(data) {
|
12
|
+
// your logic here
|
13
|
+
data.response.ok = true;
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/* This file will load, be required, first in the actionhero binary.
|
2
|
+
Anything that needed loaded or run BEFORE actionhero starts can be done here.
|
3
|
+
|
4
|
+
This file returns a single method that is run immediately after loading.
|
5
|
+
*/
|
6
|
+
|
7
|
+
// include high-level requires here.
|
8
|
+
|
9
|
+
exports.default = async function BOOT() {}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { CLI } from "actionhero";
|
2
|
+
|
3
|
+
export class MyCLICommand extends CLI {
|
4
|
+
constructor() {
|
5
|
+
super();
|
6
|
+
this.name = "%%name%%";
|
7
|
+
this.description = "%%description%%";
|
8
|
+
this.example = "%%example%%";
|
9
|
+
this.inputs = {};
|
10
|
+
}
|
11
|
+
|
12
|
+
async run(data) {
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Actionhero files
|
2
|
+
pids/*
|
3
|
+
tmp/*
|
4
|
+
log/*
|
5
|
+
cache/*
|
6
|
+
coverage/*
|
7
|
+
node_modules/*
|
8
|
+
public/javascript/ActionheroWebsocketClient.js
|
9
|
+
dist
|
10
|
+
|
11
|
+
# Node / NPM
|
12
|
+
npm-debug.log
|
13
|
+
|
14
|
+
# OS-specific weirdness
|
15
|
+
.DS_Store
|
16
|
+
|
17
|
+
# Redis
|
18
|
+
dump.rdb
|
19
|
+
cache.dump
|
20
|
+
|
21
|
+
# Editor-specific
|
22
|
+
/nbproject/*
|
23
|
+
/.idea/*
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Initializer } from "actionhero";
|
2
|
+
|
3
|
+
export class MyInitializer extends Initializer {
|
4
|
+
constructor() {
|
5
|
+
super();
|
6
|
+
this.name = "%%name%%";
|
7
|
+
this.loadPriority = %%loadPriority%%;
|
8
|
+
this.startPriority = %%startPriority%%;
|
9
|
+
this.stopPriority = %%stopPriority%%;
|
10
|
+
}
|
11
|
+
|
12
|
+
async initialize() {}
|
13
|
+
|
14
|
+
async start() {}
|
15
|
+
|
16
|
+
async stop() {}
|
17
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
{
|
2
|
+
"author": "YOU <YOU@example.com>",
|
3
|
+
"name": "my_actionhero_project",
|
4
|
+
"description": "my actionhero project",
|
5
|
+
"version": "0.1.0",
|
6
|
+
"engines": {
|
7
|
+
"node": ">=8.0.0"
|
8
|
+
},
|
9
|
+
"dependencies": {
|
10
|
+
"actionhero": "%%versionNumber%%",
|
11
|
+
"ws": "latest",
|
12
|
+
"ioredis": "latest",
|
13
|
+
"ioredis-mock": "latest",
|
14
|
+
"winston": "latest"
|
15
|
+
},
|
16
|
+
"devDependencies": {
|
17
|
+
"@types/node": "latest",
|
18
|
+
"@types/glob": "latest",
|
19
|
+
"@types/jest": "latest",
|
20
|
+
"jest": "latest",
|
21
|
+
"prettier": "latest",
|
22
|
+
"ts-jest": "latest",
|
23
|
+
"ts-node-dev": "latest",
|
24
|
+
"type-fest": "latest",
|
25
|
+
"typescript": "latest"
|
26
|
+
},
|
27
|
+
"scripts": {
|
28
|
+
"postinstall": "npm run build",
|
29
|
+
"dev": "ts-node-dev --no-deps --transpile-only ./src/server",
|
30
|
+
"debug": "tsc && ts-node-dev --transpile-only --no-deps --inspect -- ./src/server ",
|
31
|
+
"start": "node ./dist/server.js",
|
32
|
+
"actionhero": "actionhero",
|
33
|
+
"test": "jest",
|
34
|
+
"pretest": "npm run build && npm run lint",
|
35
|
+
"build": "tsc --sourceMap false --declaration",
|
36
|
+
"lint": "prettier --check src/*/** __tests__/*/**",
|
37
|
+
"pretty": "prettier --write src/*/** __tests__/*/**"
|
38
|
+
},
|
39
|
+
"jest": {
|
40
|
+
"testEnvironment": "node",
|
41
|
+
"transform": {
|
42
|
+
"^.+\\.ts?$": "ts-jest"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
|
2
|
+
|- src
|
3
|
+
| - server.ts
|
4
|
+
|
|
5
|
+
| - config
|
6
|
+
| - (project settings)
|
7
|
+
|
|
8
|
+
| - actions
|
9
|
+
| -- (your actions)
|
10
|
+
|
|
11
|
+
| - initializers
|
12
|
+
| -- (any additional initializers you want)
|
13
|
+
|
|
14
|
+
| - servers
|
15
|
+
| -- (custom servers you may make)
|
16
|
+
|
|
17
|
+
| - tasks
|
18
|
+
| -- (your tasks)
|
19
|
+
|
|
20
|
+
| - bin
|
21
|
+
| -- (your custom CLI commands)
|
22
|
+
|
|
23
|
+
|- __tests__
|
24
|
+
|-- (tests for your API)
|
25
|
+
|
|
26
|
+
| - log
|
27
|
+
|-- (default location for logs)
|
28
|
+
|
|
29
|
+
|- node_modules
|
30
|
+
|-- (your modules, actionhero should be npm installed in here)
|
31
|
+
|
|
32
|
+
|- pids
|
33
|
+
|-- (pidfiles for your running servers)
|
34
|
+
|
|
35
|
+
|- public
|
36
|
+
|-- (your static assets to be served by /file)
|
37
|
+
|
|
38
|
+
readme.md
|
39
|
+
package.json
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
// load any custom code, configure the env, as needed
|
4
|
+
|
5
|
+
async function main() {
|
6
|
+
// create a new actionhero process
|
7
|
+
const { Process } = await import("actionhero");
|
8
|
+
const app = new Process();
|
9
|
+
|
10
|
+
// handle unix signals and uncaught exceptions & rejections
|
11
|
+
app.registerProcessSignals((exitCode) => {
|
12
|
+
process.exit(exitCode);
|
13
|
+
});
|
14
|
+
|
15
|
+
// start the app!
|
16
|
+
// you can pass custom configuration to the process as needed
|
17
|
+
await app.start();
|
18
|
+
}
|
19
|
+
|
20
|
+
main();
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { Server } from "actionhero";
|
2
|
+
|
3
|
+
export class MyServer extends Server {
|
4
|
+
constructor() {
|
5
|
+
super();
|
6
|
+
this.type = "%%name%%";
|
7
|
+
|
8
|
+
this.attributes = {
|
9
|
+
canChat: false,
|
10
|
+
logConnections: true,
|
11
|
+
logExits: true,
|
12
|
+
sendWelcomeMessage: false,
|
13
|
+
verbs: []
|
14
|
+
};
|
15
|
+
// this.config will be set to equal config[this.type]
|
16
|
+
}
|
17
|
+
|
18
|
+
async initialize() {
|
19
|
+
this.on("connection", connection => {});
|
20
|
+
|
21
|
+
this.on("actionComplete", data => {});
|
22
|
+
}
|
23
|
+
|
24
|
+
async start() {
|
25
|
+
// this.buildConnection (data)
|
26
|
+
// this.processAction (connection)
|
27
|
+
// this.processFile (connection)
|
28
|
+
}
|
29
|
+
|
30
|
+
async stop() {}
|
31
|
+
|
32
|
+
async sendMessage(connection, message, messageId) {}
|
33
|
+
|
34
|
+
async sendFile(connection, error, fileStream, mime, length, lastModified) {}
|
35
|
+
|
36
|
+
goodbye(connection) {}
|
37
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { Task } from "actionhero";
|
2
|
+
|
3
|
+
export class MyTask extends Task {
|
4
|
+
constructor() {
|
5
|
+
super();
|
6
|
+
this.name = "%%name%%";
|
7
|
+
this.description = "%%description%%";
|
8
|
+
this.frequency = %%frequency%%;
|
9
|
+
this.queue = "%%queue%%";
|
10
|
+
this.middleware = [];
|
11
|
+
}
|
12
|
+
|
13
|
+
async run(data) {
|
14
|
+
// your logic here
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Process, specHelper } from "actionhero";
|
2
|
+
|
3
|
+
describe("Action: %%name%%", () => {
|
4
|
+
const actionhero = new Process();
|
5
|
+
|
6
|
+
beforeAll(async () => await actionhero.start());
|
7
|
+
afterAll(async () => await actionhero.stop());
|
8
|
+
|
9
|
+
test("returns OK", async () => {
|
10
|
+
const { ok } = await specHelper.runAction("%%name%%");
|
11
|
+
expect(ok).toEqual(true);
|
12
|
+
});
|
13
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Process, task, api, specHelper } from "actionhero";
|
2
|
+
|
3
|
+
describe("Task: %%name%%", () => {
|
4
|
+
const actionhero = new Process();
|
5
|
+
|
6
|
+
beforeAll(async () => await actionhero.start());
|
7
|
+
afterAll(async () => await actionhero.stop());
|
8
|
+
|
9
|
+
beforeEach(async () => {
|
10
|
+
await api.resque.queue.connection.redis.flushdb();
|
11
|
+
});
|
12
|
+
|
13
|
+
test("can be enqueued", async () => {
|
14
|
+
await task.enqueue("%%name%%", {});
|
15
|
+
const found = await specHelper.findEnqueuedTasks("%%name%%");
|
16
|
+
expect(found.length).toEqual(1);
|
17
|
+
expect(found[0].timestamp).toBeNull();
|
18
|
+
});
|
19
|
+
});
|
20
|
+
|