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,113 @@
|
|
1
|
+
import * as winston from "winston";
|
2
|
+
import { ActionheroConfigInterface } from "..";
|
3
|
+
|
4
|
+
const namespace = "logger";
|
5
|
+
|
6
|
+
declare module ".." {
|
7
|
+
export interface ActionheroConfigInterface {
|
8
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
/*
|
13
|
+
The loggers defined here will eventually be available via `import { loggers } from "actionhero"`
|
14
|
+
|
15
|
+
You may want to customize how Actionhero sets the log level. By default, you can use `process.env.LOG_LEVEL` to change each logger's level (default: 'info')
|
16
|
+
|
17
|
+
learn more about winston v3 loggers @
|
18
|
+
- https://github.com/winstonjs/winston
|
19
|
+
- https://github.com/winstonjs/winston/blob/master/docs/transports.md
|
20
|
+
*/
|
21
|
+
|
22
|
+
type ActionheroConfigLoggerBuilderArray = Array<
|
23
|
+
(config: ActionheroConfigInterface) => winston.Logger
|
24
|
+
>;
|
25
|
+
|
26
|
+
export const DEFAULT = {
|
27
|
+
[namespace]: (config: ActionheroConfigInterface) => {
|
28
|
+
const loggers: ActionheroConfigLoggerBuilderArray = [];
|
29
|
+
loggers.push(buildConsoleLogger(process.env.LOG_LEVEL));
|
30
|
+
config.general.paths.log.forEach((p: string) => {
|
31
|
+
loggers.push(buildFileLogger(p, process.env.LOG_LEVEL));
|
32
|
+
});
|
33
|
+
|
34
|
+
return {
|
35
|
+
loggers,
|
36
|
+
maxLogStringLength: 100, // the maximum length of param to log (we will truncate)
|
37
|
+
maxLogArrayLength: 10, // the maximum number of items in an array to log before collapsing into one message
|
38
|
+
};
|
39
|
+
},
|
40
|
+
};
|
41
|
+
|
42
|
+
export const test = {
|
43
|
+
[namespace]: (config: ActionheroConfigInterface) => {
|
44
|
+
const loggers: ActionheroConfigLoggerBuilderArray = [];
|
45
|
+
loggers.push(buildConsoleLogger(process.env.LOG_LEVEL ?? "crit"));
|
46
|
+
config.general.paths.log.forEach((path: string) => {
|
47
|
+
loggers.push(buildFileLogger(path, "debug", 1));
|
48
|
+
});
|
49
|
+
|
50
|
+
return { loggers };
|
51
|
+
},
|
52
|
+
};
|
53
|
+
|
54
|
+
// helpers for building the winston loggers
|
55
|
+
|
56
|
+
function buildConsoleLogger(level = "info") {
|
57
|
+
return function () {
|
58
|
+
return winston.createLogger({
|
59
|
+
format: winston.format.combine(
|
60
|
+
winston.format.timestamp(),
|
61
|
+
winston.format.colorize(),
|
62
|
+
winston.format.printf((info) => {
|
63
|
+
return `${info.timestamp} - ${info.level}: ${
|
64
|
+
info.message
|
65
|
+
} ${stringifyExtraMessagePropertiesForConsole(info)}`;
|
66
|
+
}),
|
67
|
+
),
|
68
|
+
level,
|
69
|
+
levels: winston.config.syslog.levels,
|
70
|
+
transports: [new winston.transports.Console()],
|
71
|
+
});
|
72
|
+
};
|
73
|
+
}
|
74
|
+
|
75
|
+
function buildFileLogger(path: string, level = "info", maxFiles?: number) {
|
76
|
+
return function (config: ActionheroConfigInterface) {
|
77
|
+
const filename = `${path}/${config.process.id}-${config.process.env}.log`;
|
78
|
+
return winston.createLogger({
|
79
|
+
format: winston.format.combine(
|
80
|
+
winston.format.timestamp(),
|
81
|
+
winston.format.json(),
|
82
|
+
),
|
83
|
+
level,
|
84
|
+
levels: winston.config.syslog.levels,
|
85
|
+
transports: [
|
86
|
+
new winston.transports.File({
|
87
|
+
filename,
|
88
|
+
maxFiles,
|
89
|
+
}),
|
90
|
+
],
|
91
|
+
});
|
92
|
+
};
|
93
|
+
}
|
94
|
+
|
95
|
+
function stringifyExtraMessagePropertiesForConsole(
|
96
|
+
info: winston.Logform.TransformableInfo,
|
97
|
+
) {
|
98
|
+
const skippedProperties = ["message", "timestamp", "level"];
|
99
|
+
let response = "";
|
100
|
+
|
101
|
+
for (const key in info) {
|
102
|
+
const value = info[key];
|
103
|
+
if (skippedProperties.includes(key)) {
|
104
|
+
continue;
|
105
|
+
}
|
106
|
+
if (value === undefined || value === null || value === "") {
|
107
|
+
continue;
|
108
|
+
}
|
109
|
+
response += `${key}=${value} `;
|
110
|
+
}
|
111
|
+
|
112
|
+
return response;
|
113
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { PluginConfig } from "..";
|
2
|
+
|
3
|
+
const namespace = "plugins";
|
4
|
+
|
5
|
+
declare module ".." {
|
6
|
+
export interface ActionheroConfigInterface {
|
7
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
export const DEFAULT: { [namespace]: () => PluginConfig } = {
|
12
|
+
[namespace]: () => {
|
13
|
+
/*
|
14
|
+
If you want to use plugins in your application, include them here:
|
15
|
+
|
16
|
+
return {
|
17
|
+
'myPlugin': { path: __dirname + '/../node_modules/myPlugin' }
|
18
|
+
}
|
19
|
+
|
20
|
+
You can also toggle on or off sections of a plugin to include (default true for all sections):
|
21
|
+
|
22
|
+
return {
|
23
|
+
'myPlugin': {
|
24
|
+
path: __dirname + '/../node_modules/myPlugin',
|
25
|
+
actions: true,
|
26
|
+
tasks: true,
|
27
|
+
initializers: true,
|
28
|
+
servers: true,
|
29
|
+
public: true,
|
30
|
+
cli: true
|
31
|
+
}
|
32
|
+
}
|
33
|
+
*/
|
34
|
+
|
35
|
+
return {};
|
36
|
+
},
|
37
|
+
};
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { URL } from "url";
|
2
|
+
|
3
|
+
const namespace = "redis";
|
4
|
+
|
5
|
+
declare module ".." {
|
6
|
+
export interface ActionheroConfigInterface {
|
7
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
/**
|
12
|
+
* This is the standard redis config for Actionhero.
|
13
|
+
* This will use a redis server to persist cache, share chat message between processes, etc.
|
14
|
+
*/
|
15
|
+
|
16
|
+
export const DEFAULT = {
|
17
|
+
[namespace]: () => {
|
18
|
+
const konstructor = require("ioredis"); // or konstructor = require("ioredis-mock") if you don't need real redis;
|
19
|
+
let protocol = process.env.REDIS_SSL ? "rediss" : "redis";
|
20
|
+
let host = process.env.REDIS_HOST || "127.0.0.1";
|
21
|
+
let port = process.env.REDIS_PORT || 6379;
|
22
|
+
let db = process.env.REDIS_DB || process.env.JEST_WORKER_ID || "0";
|
23
|
+
let password = process.env.REDIS_PASSWORD || null;
|
24
|
+
|
25
|
+
if (process.env.REDIS_URL) {
|
26
|
+
const parsed = new URL(process.env.REDIS_URL);
|
27
|
+
if (parsed.protocol) protocol = parsed.protocol.split(":")[0];
|
28
|
+
if (parsed.password) password = parsed.password;
|
29
|
+
if (parsed.hostname) host = parsed.hostname;
|
30
|
+
if (parsed.port) port = parsed.port;
|
31
|
+
if (parsed.pathname) db = parsed.pathname.substring(1);
|
32
|
+
}
|
33
|
+
|
34
|
+
const maxBackoff = 1000;
|
35
|
+
const commonArgs = {
|
36
|
+
port,
|
37
|
+
host,
|
38
|
+
password,
|
39
|
+
db: parseInt(db),
|
40
|
+
// ssl options
|
41
|
+
tls: protocol === "rediss" ? { rejectUnauthorized: false } : undefined,
|
42
|
+
// you can learn more about retryStrategy @ https://github.com/luin/ioredis#auto-reconnect
|
43
|
+
retryStrategy: (times: number) => {
|
44
|
+
if (times === 1) {
|
45
|
+
console.error(
|
46
|
+
"Unable to connect to Redis - please check your Redis config!",
|
47
|
+
);
|
48
|
+
return 5000;
|
49
|
+
}
|
50
|
+
return Math.min(times * 50, maxBackoff);
|
51
|
+
},
|
52
|
+
};
|
53
|
+
|
54
|
+
return {
|
55
|
+
// how many items should be fetched in a batch at once?
|
56
|
+
scanCount: 1000,
|
57
|
+
// how many ms should we wait when disconnecting after sending server-side disconnect message to the cluster
|
58
|
+
stopTimeout: 100,
|
59
|
+
|
60
|
+
_toExpand: false,
|
61
|
+
client: {
|
62
|
+
konstructor,
|
63
|
+
args: [commonArgs],
|
64
|
+
buildNew: true,
|
65
|
+
},
|
66
|
+
subscriber: {
|
67
|
+
konstructor,
|
68
|
+
args: [commonArgs],
|
69
|
+
buildNew: true,
|
70
|
+
},
|
71
|
+
tasks: {
|
72
|
+
konstructor,
|
73
|
+
args: [commonArgs],
|
74
|
+
buildNew: true,
|
75
|
+
},
|
76
|
+
};
|
77
|
+
},
|
78
|
+
};
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { RoutesConfig } from "..";
|
2
|
+
|
3
|
+
const namespace = "routes";
|
4
|
+
|
5
|
+
declare module ".." {
|
6
|
+
export interface ActionheroConfigInterface {
|
7
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
export const DEFAULT: { [namespace]: () => RoutesConfig } = {
|
12
|
+
[namespace]: () => {
|
13
|
+
return {
|
14
|
+
get: [
|
15
|
+
{ path: "/status", action: "status" },
|
16
|
+
{ path: "/swagger", action: "swagger" },
|
17
|
+
{ path: "/createChatRoom", action: "createChatRoom" },
|
18
|
+
],
|
19
|
+
|
20
|
+
/* ---------------------
|
21
|
+
For web clients (http and https) you can define an optional RESTful mapping to help route requests to actions.
|
22
|
+
If the client doesn't specify and action in a param, and the base route isn't a named action, the action will attempt to be discerned from this routes.js file.
|
23
|
+
|
24
|
+
Learn more here: https://www.actionherojs.com/tutorials/web-server#Routes
|
25
|
+
|
26
|
+
examples:
|
27
|
+
|
28
|
+
get: [
|
29
|
+
{ path: '/users', action: 'usersList' }, // (GET) /api/users
|
30
|
+
{ path: '/search/:term/limit/:limit/offset/:offset', action: 'search' }, // (GET) /api/search/car/limit/10/offset/100
|
31
|
+
],
|
32
|
+
|
33
|
+
post: [
|
34
|
+
{ path: '/login/:userID(^\\d{3}$)', action: 'login' } // (POST) /api/login/123
|
35
|
+
],
|
36
|
+
|
37
|
+
all: [
|
38
|
+
{ path: '/user/:userID', action: 'user', matchTrailingPathParts: true } // (*) /api/user/123, api/user/123/stuff
|
39
|
+
]
|
40
|
+
|
41
|
+
---------------------- */
|
42
|
+
};
|
43
|
+
},
|
44
|
+
};
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import { ActionheroLogLevel } from "..";
|
2
|
+
import { MultiWorker, Queue, Scheduler } from "node-resque";
|
3
|
+
|
4
|
+
const namespace = "tasks";
|
5
|
+
|
6
|
+
declare module ".." {
|
7
|
+
export interface ActionheroConfigInterface {
|
8
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
export const DEFAULT = {
|
13
|
+
[namespace]: () => {
|
14
|
+
return {
|
15
|
+
_toExpand: false,
|
16
|
+
|
17
|
+
// Should this node run a scheduler to promote delayed tasks?
|
18
|
+
scheduler: false,
|
19
|
+
|
20
|
+
// what queues should the taskProcessors work?
|
21
|
+
queues: ["*"] as string[] | (() => Promise<string[]>),
|
22
|
+
// Or, rather than providing a static list of `queues`, you can define a method that returns the list of queues.
|
23
|
+
// queues: async () => { return ["queueA", "queueB"]; } as string[] | (() => Promise<string[]>)>,
|
24
|
+
|
25
|
+
// Logging levels of task workers
|
26
|
+
workerLogging: {
|
27
|
+
failure: "error" as ActionheroLogLevel, // task failure
|
28
|
+
success: "info" as ActionheroLogLevel, // task success
|
29
|
+
start: "info" as ActionheroLogLevel,
|
30
|
+
end: "info" as ActionheroLogLevel,
|
31
|
+
cleaning_worker: "info" as ActionheroLogLevel,
|
32
|
+
poll: "debug" as ActionheroLogLevel,
|
33
|
+
job: "debug" as ActionheroLogLevel,
|
34
|
+
pause: "debug" as ActionheroLogLevel,
|
35
|
+
reEnqueue: "debug" as ActionheroLogLevel,
|
36
|
+
internalError: "error" as ActionheroLogLevel,
|
37
|
+
multiWorkerAction: "debug" as ActionheroLogLevel,
|
38
|
+
},
|
39
|
+
// Logging levels of the task scheduler
|
40
|
+
schedulerLogging: {
|
41
|
+
start: "info" as ActionheroLogLevel,
|
42
|
+
end: "info" as ActionheroLogLevel,
|
43
|
+
poll: "debug" as ActionheroLogLevel,
|
44
|
+
enqueue: "debug" as ActionheroLogLevel,
|
45
|
+
working_timestamp: "debug" as ActionheroLogLevel,
|
46
|
+
reEnqueue: "debug" as ActionheroLogLevel,
|
47
|
+
transferred_job: "debug" as ActionheroLogLevel,
|
48
|
+
},
|
49
|
+
// how long to sleep between jobs / scheduler checks
|
50
|
+
timeout: 5000,
|
51
|
+
// at minimum, how many parallel taskProcessors should this node spawn?
|
52
|
+
// (have number > 0 to enable, and < 1 to disable)
|
53
|
+
minTaskProcessors: 0,
|
54
|
+
// at maximum, how many parallel taskProcessors should this node spawn?
|
55
|
+
maxTaskProcessors: 0,
|
56
|
+
// how often should we check the event loop to spawn more taskProcessors?
|
57
|
+
checkTimeout: 500,
|
58
|
+
// how many ms would constitute an event loop delay to halt taskProcessors spawning?
|
59
|
+
maxEventLoopDelay: 5,
|
60
|
+
// how long before we mark a resque worker / task processor as stuck/dead?
|
61
|
+
stuckWorkerTimeout: 1000 * 60 * 60,
|
62
|
+
// should the scheduler automatically try to retry failed tasks which were failed due to being 'stuck'?
|
63
|
+
retryStuckJobs: false,
|
64
|
+
// Customize Resque primitives, replace null with required replacement.
|
65
|
+
resque_overrides: {
|
66
|
+
queue: null as Queue,
|
67
|
+
multiWorker: null as MultiWorker,
|
68
|
+
scheduler: null as Scheduler,
|
69
|
+
},
|
70
|
+
connectionOptions: {
|
71
|
+
tasks: {},
|
72
|
+
},
|
73
|
+
};
|
74
|
+
},
|
75
|
+
};
|
76
|
+
|
77
|
+
export const test = {
|
78
|
+
[namespace]: () => {
|
79
|
+
return {
|
80
|
+
timeout: 100,
|
81
|
+
checkTimeout: 50,
|
82
|
+
};
|
83
|
+
},
|
84
|
+
};
|
@@ -0,0 +1,136 @@
|
|
1
|
+
import * as os from "os";
|
2
|
+
import { ActionheroConfigInterface } from "..";
|
3
|
+
|
4
|
+
import type { Options as FormParserOptions } from "formidable";
|
5
|
+
|
6
|
+
const namespace = "web";
|
7
|
+
|
8
|
+
declare module ".." {
|
9
|
+
export interface ActionheroConfigInterface {
|
10
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
export const DEFAULT = {
|
15
|
+
[namespace]: (config: ActionheroConfigInterface) => {
|
16
|
+
return {
|
17
|
+
enabled: true,
|
18
|
+
// HTTP or HTTPS? This setting is to enable SSL termination directly in the actionhero app, not set redirection host headers
|
19
|
+
secure: false,
|
20
|
+
// Passed to https.createServer if secure=true. Should contain SSL certificates
|
21
|
+
serverOptions: {},
|
22
|
+
// Should we redirect all traffic to the first host in this array if hte request header doesn't match?
|
23
|
+
// i.e.: [ 'https://www.site.com' ]
|
24
|
+
allowedRequestHosts: process.env.ALLOWED_HOSTS
|
25
|
+
? process.env.ALLOWED_HOSTS.split(",")
|
26
|
+
: [],
|
27
|
+
// Port or Socket Path
|
28
|
+
port: process.env.PORT || 8080,
|
29
|
+
// Which IP to listen on (use '0.0.0.0' for the default ip stack; '::' for all on ipv4 and ipv6)
|
30
|
+
// Set to `null` when listening to socket
|
31
|
+
bindIP: "::",
|
32
|
+
// Any additional headers you want actionhero to respond with
|
33
|
+
httpHeaders: {
|
34
|
+
"X-Powered-By": config.general.serverName,
|
35
|
+
"Access-Control-Allow-Origin": "*",
|
36
|
+
"Access-Control-Allow-Methods":
|
37
|
+
"HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS, TRACE",
|
38
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
39
|
+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
|
40
|
+
},
|
41
|
+
// Route that actions will be served from; secondary route against this route will be treated as actions,
|
42
|
+
// IE: /api/?action=test == /api/test/
|
43
|
+
urlPathForActions: "api",
|
44
|
+
// Route that static files will be served from;
|
45
|
+
// path (relative to your project root) to serve static content from
|
46
|
+
// set to `null` to disable the file server entirely
|
47
|
+
urlPathForFiles: "public",
|
48
|
+
// When visiting the root URL, should visitors see 'api' or 'file'?
|
49
|
+
// Visitors can always visit /api and /public as normal
|
50
|
+
rootEndpointType: "file",
|
51
|
+
// In addition to what's defined in config/routes.ts, should we make a route for every action? Useful for debugging or simple APIs.
|
52
|
+
// automaticRoutes should an array of strings - HTTP verbs, ie: [] (default), ['get'], ['post'], ['get','put'], ['get','post','put'], etc.
|
53
|
+
automaticRoutes: process.env.AUTOMATIC_ROUTES
|
54
|
+
? process.env.AUTOMATIC_ROUTES.split(",")
|
55
|
+
.map((v) => v.trim())
|
56
|
+
.map((v) => v.toLowerCase())
|
57
|
+
: [],
|
58
|
+
// Default HTTP status code for errors thrown in an action
|
59
|
+
defaultErrorStatusCode: 500,
|
60
|
+
// The cache or (if etags are enabled) next-revalidation time to be returned for all flat files served from /public; defined in seconds
|
61
|
+
flatFileCacheDuration: 60,
|
62
|
+
// Add an etag header to requested flat files which acts as fingerprint that changes when the file is updated;
|
63
|
+
// Client will revalidate the fingerprint at latest after flatFileCacheDuration and reload it if the etag (and therefore the file) changed
|
64
|
+
// or continue to use the cached file if it's still valid
|
65
|
+
enableEtag: true,
|
66
|
+
// should we save the un-parsed HTTP POST/PUT payload to connection.rawConnection.params.rawBody?
|
67
|
+
saveRawBody: false,
|
68
|
+
// How many times should we try to boot the server?
|
69
|
+
// This might happen if the port is in use by another process or the socket file is claimed
|
70
|
+
bootAttempts: 1,
|
71
|
+
// Settings for determining the id of an http(s) request (browser-fingerprint)
|
72
|
+
fingerprintOptions: {
|
73
|
+
cookieKey: "sessionID",
|
74
|
+
toSetCookie: true,
|
75
|
+
onlyStaticElements: false,
|
76
|
+
settings: {
|
77
|
+
path: "/",
|
78
|
+
expires: 3600000,
|
79
|
+
},
|
80
|
+
},
|
81
|
+
// Options to be applied to incoming file uploads.
|
82
|
+
// More options and details at https://github.com/felixge/node-formidable
|
83
|
+
formOptions: {
|
84
|
+
uploadDir: os.tmpdir(),
|
85
|
+
keepExtensions: false,
|
86
|
+
maxFieldsSize: 1024 * 1024 * 20,
|
87
|
+
maxFileSize: 1024 * 1024 * 200,
|
88
|
+
} as FormParserOptions,
|
89
|
+
// Should we pad JSON responses with whitespace to make them more human-readable?
|
90
|
+
// set to null to disable
|
91
|
+
padding: 2,
|
92
|
+
// Options to configure metadata in responses
|
93
|
+
metadataOptions: {
|
94
|
+
serverInformation: true,
|
95
|
+
requesterInformation: true,
|
96
|
+
},
|
97
|
+
// When true, returnErrorCodes will modify the response header for http(s) clients if connection.error is not null.
|
98
|
+
// You can also set connection.rawConnection.responseHttpCode to specify a code per request.
|
99
|
+
returnErrorCodes: true,
|
100
|
+
// should this node server attempt to gzip responses if the client can accept them?
|
101
|
+
// this will slow down the performance of actionhero, and if you need this functionality, it is recommended that you do this upstream with nginx or your load balancer
|
102
|
+
compress: false,
|
103
|
+
// options to pass to the query parser
|
104
|
+
// learn more about the options @ https://github.com/hapijs/qs
|
105
|
+
queryParseOptions: {},
|
106
|
+
};
|
107
|
+
},
|
108
|
+
};
|
109
|
+
|
110
|
+
export const production = {
|
111
|
+
[namespace]: () => {
|
112
|
+
return {
|
113
|
+
padding: null as number,
|
114
|
+
metadataOptions: {
|
115
|
+
serverInformation: false,
|
116
|
+
requesterInformation: false,
|
117
|
+
},
|
118
|
+
};
|
119
|
+
},
|
120
|
+
};
|
121
|
+
|
122
|
+
export const test = {
|
123
|
+
[namespace]: () => {
|
124
|
+
return {
|
125
|
+
secure: false,
|
126
|
+
port: process.env.PORT
|
127
|
+
? process.env.PORT
|
128
|
+
: 18080 + parseInt(process.env.JEST_WORKER_ID || "0"),
|
129
|
+
matchExtensionMime: true,
|
130
|
+
metadataOptions: {
|
131
|
+
serverInformation: true,
|
132
|
+
requesterInformation: true,
|
133
|
+
},
|
134
|
+
};
|
135
|
+
},
|
136
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// Note that to use the websocket server, you also need the web server enabled
|
2
|
+
|
3
|
+
import { ActionheroConfigInterface } from "..";
|
4
|
+
|
5
|
+
const namespace = "websocket";
|
6
|
+
|
7
|
+
declare module ".." {
|
8
|
+
export interface ActionheroConfigInterface {
|
9
|
+
[namespace]: ReturnType<(typeof DEFAULT)[typeof namespace]>;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
export const DEFAULT = {
|
14
|
+
[namespace]: (config: ActionheroConfigInterface) => {
|
15
|
+
return {
|
16
|
+
enabled: true,
|
17
|
+
// you can pass a FQDN (like https://company.com) here or 'window.location.origin'
|
18
|
+
clientUrl: "window.location.origin",
|
19
|
+
// Directory to render client-side JS.
|
20
|
+
// Path should start with "/" and will be built starting from api.config..general.paths.public
|
21
|
+
clientJsPath: "javascript/",
|
22
|
+
// the name of the client-side JS file to render. Both `.js` and `.min.js` versions will be created
|
23
|
+
// do not include the file extension
|
24
|
+
// set to `undefined` to not render the client-side JS on boot
|
25
|
+
clientJsName: "ActionheroWebsocketClient",
|
26
|
+
// should the server signal clients to not reconnect when the server is shutdown/reboot
|
27
|
+
destroyClientsOnShutdown: false,
|
28
|
+
|
29
|
+
// websocket Server Options:
|
30
|
+
server: {
|
31
|
+
// authorization: null,
|
32
|
+
// pathname: '/primus',
|
33
|
+
// parser: 'JSON',
|
34
|
+
// transformer: 'websockets',
|
35
|
+
// plugin: {},
|
36
|
+
// timeout: 35000,
|
37
|
+
// origins: '*',
|
38
|
+
// methods: ['GET','HEAD','PUT','POST','DELETE','OPTIONS'],
|
39
|
+
// credentials: true,
|
40
|
+
// maxAge: '30 days',
|
41
|
+
// exposed: false,
|
42
|
+
},
|
43
|
+
|
44
|
+
// websocket Client Options:
|
45
|
+
client: {
|
46
|
+
apiPath: "/api", // the api base endpoint on your actionhero server
|
47
|
+
// the cookie name we should use for shared authentication between WS and web connections
|
48
|
+
cookieKey: config.web.fingerprintOptions.cookieKey,
|
49
|
+
// reconnect: {},
|
50
|
+
// timeout: 10000,
|
51
|
+
// ping: 25000,
|
52
|
+
// pong: 10000,
|
53
|
+
// strategy: "online",
|
54
|
+
// manual: false,
|
55
|
+
// websockets: true,
|
56
|
+
// network: true,
|
57
|
+
// transport: {},
|
58
|
+
// queueSize: Infinity,
|
59
|
+
},
|
60
|
+
};
|
61
|
+
},
|
62
|
+
};
|
package/src/index.ts
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
// export classes (capitalized)
|
2
|
+
export { Api } from "./classes/api";
|
3
|
+
export { Process } from "./classes/process";
|
4
|
+
export { ActionheroConfigInterface } from "./classes/config";
|
5
|
+
export { Initializer } from "./classes/initializer";
|
6
|
+
export { Connection } from "./classes/connection";
|
7
|
+
export { ExceptionReporter } from "./classes/exceptionReporter";
|
8
|
+
export { Action } from "./classes/action";
|
9
|
+
export { Task } from "./classes/task";
|
10
|
+
export { Server } from "./classes/server";
|
11
|
+
export { CLI } from "./classes/cli";
|
12
|
+
export { ActionProcessor } from "./classes/actionProcessor";
|
13
|
+
export { PluginConfig } from "./classes/config";
|
14
|
+
export { Inputs, ParamsFrom } from "./classes/inputs";
|
15
|
+
export { Input } from "./classes/input";
|
16
|
+
|
17
|
+
// export modules (lower case)
|
18
|
+
export { utils } from "./modules/utils";
|
19
|
+
export { config, rebuildConfig } from "./modules/config";
|
20
|
+
export { log, loggers, ActionheroLogLevel } from "./modules/log";
|
21
|
+
export { action } from "./modules/action";
|
22
|
+
export { task } from "./modules/task";
|
23
|
+
export { cache } from "./modules/cache";
|
24
|
+
export { chatRoom } from "./modules/chatRoom";
|
25
|
+
export { redis } from "./modules/redis";
|
26
|
+
export { route, RouteMethod, RouteType, RoutesConfig } from "./modules/route";
|
27
|
+
export { specHelper } from "./modules/specHelper";
|
28
|
+
|
29
|
+
// export static members of this process (lower case)
|
30
|
+
export { env } from "./classes/process/env";
|
31
|
+
export { actionheroVersion } from "./classes/process/actionheroVersion";
|
32
|
+
export { projectRoot } from "./classes/process/projectRoot";
|
33
|
+
export { typescript } from "./classes/process/typescript";
|
34
|
+
export { id } from "./classes/process/id";
|
35
|
+
|
36
|
+
// API object to hold connections, actions, tasks, initializers, and servers
|
37
|
+
import { Api } from "./classes/api";
|
38
|
+
|
39
|
+
// export a global API instance
|
40
|
+
|
41
|
+
declare module globalThis {
|
42
|
+
let api: Api;
|
43
|
+
}
|
44
|
+
|
45
|
+
if (!globalThis.api) globalThis.api = new Api();
|
46
|
+
export const api = globalThis.api;
|