actionhero
Version:
The reusable, scalable, and quick node.js API server for stateless and stateful applications
124 lines (109 loc) • 3.46 kB
text/typescript
import * as glob from "glob";
import * as path from "path";
import { api, log, utils, Initializer, Action } from "../index";
import * as ActionModule from "./../modules/action";
export interface ActionsApi {
actions: {
[key: string]: {
[key: string]: Action;
};
};
versions: {
[key: string]: Array<string | number>;
};
middleware: {
[key: string]: ActionModule.action.ActionMiddleware;
};
globalMiddleware: Array<string>;
loadFile?: Function;
}
export class Actions extends Initializer {
constructor() {
super();
this.name = "actions";
this.loadPriority = 410;
}
async initialize(config) {
api.actions = {
actions: {},
versions: {},
middleware: {},
globalMiddleware: [],
};
api.actions.loadFile = async (
fullFilePath: string,
reload: boolean = false
) => {
const loadMessage = (action) => {
if (reload) {
log(
`action reloaded: ${action.name} @ v${action.version}, ${fullFilePath}`,
"info"
);
} else {
log(
`action loaded: ${action.name} @ v${action.version}, ${fullFilePath}`,
"debug"
);
}
};
let action;
try {
let collection = await import(fullFilePath);
if (typeof collection === "function") {
collection = [collection];
}
for (const i in collection) {
action = new collection[i]();
await action.validate(api);
if (!api.actions.actions[action.name]) {
api.actions.actions[action.name] = {};
}
if (!api.actions.versions[action.name]) {
api.actions.versions[action.name] = [];
}
if (api.actions.actions[action.name][action.version] && !reload) {
log(
`an existing action with the same name \`${action.name}\` will be overridden by the file ${fullFilePath}`,
"warning"
);
}
api.actions.actions[action.name][action.version] = action;
api.actions.versions[action.name].push(action.version);
api.actions.versions[action.name].sort();
loadMessage(action);
}
} catch (error) {
try {
api.exceptionHandlers.loader(fullFilePath, error);
delete api.actions.actions[action.name][action.version];
} catch (_error) {
throw error;
}
}
};
for (const i in config.general.paths.action) {
const p = config.general.paths.action[i];
let files = glob.sync(path.join(p, "**", "**/*(*.js|*.ts)"));
files = utils.ensureNoTsHeaderFiles(files);
for (const j in files) {
await api.actions.loadFile(files[j]);
}
}
for (const pluginName in config.plugins) {
if (config.plugins[pluginName].actions !== false) {
const pluginPath = config.plugins[pluginName].path;
// old style at the root of the project
let files = glob.sync(path.join(pluginPath, "actions", "**", "*.js"));
files = files.concat(
glob.sync(path.join(pluginPath, "dist", "actions", "**", "*.js"))
);
utils
.ensureNoTsHeaderFiles(files)
.forEach((f) => api.actions.loadFile(f));
}
}
// now that the actions are loaded, we can add all the inputs to api.params
api.params.buildPostVariables();
}
}