actionhero
Version:
The reusable, scalable, and quick node.js API server for stateless and stateful applications
136 lines (116 loc) • 3.85 kB
text/typescript
import * as path from "path";
import * as glob from "glob";
import { api, log, utils, Initializer, Server } from "../index";
export interface ServersApi {
servers: {
[key: string]: Server;
};
}
/**
* Manages the servers in this Actionhero instance.
*/
export class Servers extends Initializer {
constructor() {
super();
this.name = "servers";
this.loadPriority = 599;
this.startPriority = 900;
this.stopPriority = 100;
}
async initialize(config) {
api.servers = {
servers: {},
};
const serverFolders = [path.resolve(path.join(__dirname, "..", "servers"))];
config.general.paths.server.forEach((p) => {
p = path.resolve(p);
if (serverFolders.indexOf(p) < 0) {
serverFolders.push(p);
}
});
let files = [];
for (const i in serverFolders) {
const p = serverFolders[i];
files = files.concat(glob.sync(path.join(p, "**", "**/*(*.js|*.ts)")));
}
for (const pluginName in config.plugins) {
if (config.plugins[pluginName].servers !== false) {
const pluginPath = config.plugins[pluginName].path;
// old style at the root of the project
files = files.concat(
glob.sync(path.join(pluginPath, "servers", "**", "*.js"))
);
files = files.concat(
glob.sync(path.join(pluginPath, "dist", "servers", "**", "*.js"))
);
}
}
files = utils.ensureNoTsHeaderFiles(files);
let server: Server;
for (const j in files) {
const filename = files[j];
const ExportedClasses = await import(filename);
const exportLen = Object.keys(ExportedClasses).length;
// we have named exports
if (exportLen) {
if (exportLen > 1) {
throw new Error(
`server file ${filename} exports more than one server`
);
}
server = new ExportedClasses[Object.keys(ExportedClasses)[0]]();
} else {
// there is one default export
server = new ExportedClasses();
}
server.config = config.servers[server.type]; // for shorthand access
if (server.config && server.config.enabled === true) {
await server.initialize();
if (api.servers.servers[server.type]) {
log(
`an existing server with the same type \`${server.type}\` will be overridden by the file ${filename}`,
"crit"
);
}
api.servers.servers[server.type] = server;
log(`Initialized server: ${server.type}`, "debug");
}
}
}
async start(config) {
const serverNames = Object.keys(api.servers.servers);
for (const i in serverNames) {
const serverName = serverNames[i];
const server = api.servers.servers[serverName];
if (server && server.config.enabled === true) {
const message = `Starting server: \`${serverName}\` ${
config.servers[serverName].bindIP
? `@ ${serverName === "web" ? "http://" : ""}${
config.servers[serverName].bindIP
}${
config.servers[serverName].port
? `:${config.servers[serverName].port}`
: ""
}`
: ""
}`;
log(message, "notice");
await server.start();
log(`Server started: ${serverName}`, "debug");
}
}
}
async stop() {
const serverNames = Object.keys(api.servers.servers);
for (const i in serverNames) {
const serverName = serverNames[i];
const server = api.servers.servers[serverName];
if ((server && server.config.enabled === true) || !server) {
log(`Stopping server: ${serverName}`, "notice");
await server.stop();
server.removeAllListeners();
log(`Server stopped: ${serverName}`, "debug");
}
}
}
}