actionhero
Version:
actionhero.js is a multi-transport API Server with integrated cluster capabilities and delayed tasks
162 lines (161 loc) • 5.73 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = void 0;
const events_1 = require("events");
const connection_1 = require("./connection");
const actionProcessor_1 = require("./actionProcessor");
const index_1 = require("../index");
const log_1 = require("../modules/log");
/**
* Create a new Actionhero Server. The required properties of an server. These can be defined statically (this.name) or as methods which return a value.
*/
class Server extends events_1.EventEmitter {
constructor() {
super();
this.options = {};
this.attributes = {};
this.config = {}; // will be applied by the initializer
this.connectionCustomMethods = {};
const defaultAttributes = this.defaultAttributes();
for (const key in defaultAttributes) {
if (!this.attributes[key]) {
this.attributes[key] = defaultAttributes[key];
}
if (typeof this.attributes[key] === "function") {
this.attributes[key] = this[key]();
}
}
}
defaultAttributes() {
return {
type: null,
canChat: true,
logConnections: true,
logExits: true,
sendWelcomeMessage: true,
verbs: [],
};
}
validate() {
if (!this.type) {
throw new Error("type is required for this server");
}
[
"start",
"stop",
"sendFile",
"sendMessage",
"goodbye",
].forEach((method) => {
if (!this[method] || typeof this[method] !== "function") {
throw new Error(`${method} is a required method for the server \`${this.type}\``);
}
});
}
/**
* * Build a the Actionhero.Connection from the raw parts provided by the server.
* ```js
*this.buildConnection({
* rawConnection: {
* req: req,
* res: res,
* params: {},
* method: method,
* cookies: cookies,
* responseHeaders: responseHeaders,
* responseHttpCode: responseHttpCode,
* parsedURL: parsedURL
* },
* id: fingerprint + '-' + uuid.v4(),
* fingerprint: fingerprint,
* remoteAddress: remoteIP,
* remotePort: remotePort
*})
* ```
*/
async buildConnection(data) {
const details = {
type: this.type,
id: data.id,
remotePort: data.remotePort,
remoteIP: data.remoteAddress,
rawConnection: data.rawConnection,
messageId: data.messageId,
canChat: null,
fingerprint: null,
};
if (this.attributes.canChat === true) {
details.canChat = true;
}
if (data.fingerprint) {
details.fingerprint = data.fingerprint;
}
const connection = await connection_1.Connection.createAsync(details);
connection.sendMessage = async (message) => {
this.sendMessage(connection, message);
};
connection.sendFile = async (path) => {
connection.params.file = path;
this.processFile(connection);
};
this.emit("connection", connection);
if (this.attributes.logConnections === true) {
this.log("new connection", "info", { to: connection.remoteIP });
}
if (this.attributes.sendWelcomeMessage === true) {
connection.sendMessage({
welcome: connection.localize("actionhero.welcomeMessage"),
context: "api",
});
}
if (typeof this.attributes.sendWelcomeMessage === "number") {
setTimeout(() => {
try {
connection.sendMessage({
welcome: connection.localize("actionhero.welcomeMessage"),
context: "api",
});
}
catch (e) {
this.log(e, "error");
}
}, this.attributes.sendWelcomeMessage);
}
}
/**
* When a connection has called an Action command, and all properties are set. Connection should have `params.action` set at least.
* on(event: 'actionComplete', cb: (data: object) => void): this;
*/
async processAction(connection) {
const actionProcessor = new actionProcessor_1.ActionProcessor(connection);
const data = await actionProcessor.processAction();
this.emit("actionComplete", data);
}
/**
* When a connection has called an File command, and all properties are set. Connection should have `params.file` set at least. Will eventually call Actionhero.Server#sendFile.
*/
async processFile(connection) {
const results = await index_1.api.staticFile.get(connection);
this.sendFile(results.connection, results.error, results.fileStream, results.mime, results.length, results.lastModified);
}
/**
* Enumerate the connections for this server type on this server.
*/
connections() {
const connections = [];
for (const i in index_1.api.connections.connections) {
const connection = index_1.api.connections.connections[i];
if (connection.type === this.type) {
connections.push(connection);
}
}
return connections;
}
/**
* Log a message from this server type. A wrapper around log() with a server prefix.
*/
log(message, severity, data) {
log_1.log(`[server: ${this.type}] ${message}`, severity, data);
}
}
exports.Server = Server;