actionhero
Version:
The reusable, scalable, and quick node.js API server for stateless and stateful applications
144 lines (143 loc) • 5.63 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = void 0;
const events_1 = require("events");
const index_1 = require("../index");
const log_1 = require("../modules/log");
const actionProcessor_1 = require("./actionProcessor");
const connection_1 = require("./connection");
/**
* 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() {
var _a, _b, _c, _d, _e;
super();
this.options = {};
this.attributes = {};
this.config = {}; // will be applied by the initializer
this.connectionCustomMethods = {};
this.canChat = (_a = this.canChat) !== null && _a !== void 0 ? _a : true;
this.logExits = (_b = this.logExits) !== null && _b !== void 0 ? _b : true;
this.sendWelcomeMessage = (_c = this.sendWelcomeMessage) !== null && _c !== void 0 ? _c : true;
this.logConnections = (_d = this.logConnections) !== null && _d !== void 0 ? _d : true;
this.verbs = (_e = this.verbs) !== null && _e !== void 0 ? _e : [];
}
validate() {
if (!this.type) {
throw new Error("type is required for this server");
}
[
"start",
"stop",
"sendFile", // connection, error, fileStream, mime, length, lastModified
"sendMessage", // connection, message
"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) {
var _a, _b;
const details = {
type: this.type,
id: data.id,
remotePort: data.remotePort,
remoteIP: data.remoteAddress,
rawConnection: data.rawConnection,
messageId: data.messageId,
canChat: (_a = this.attributes.canChat) !== null && _a !== void 0 ? _a : null,
fingerprint: (_b = data.fingerprint) !== null && _b !== void 0 ? _b : null,
};
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: index_1.config.general.welcomeMessage,
context: "api",
});
}
if (typeof this.attributes.sendWelcomeMessage === "number") {
setTimeout(() => {
try {
connection.sendMessage({
welcome: index_1.config.general.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) {
(0, log_1.log)(`[server: ${this.type}] ${message}`, severity, data);
}
}
exports.Server = Server;