helene
Version:
Real-time Web Apps for Node.js
201 lines • 7.57 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = void 0;
exports.createServer = createServer;
const utils_1 = require("../utils");
const assert = __importStar(require("assert"));
const defer_1 = __importDefault(require("lodash/defer"));
const isFunction_1 = __importDefault(require("lodash/isFunction"));
const isObject_1 = __importDefault(require("lodash/isObject"));
const isString_1 = __importDefault(require("lodash/isString"));
const client_node_1 = require("./client-node");
const create_method_proxy_1 = require("./create-method-proxy");
const default_methods_1 = require("./default-methods");
const method_1 = require("./method");
const server_channel_1 = require("./server-channel");
const transports_1 = require("./transports");
class Server extends server_channel_1.ServerChannel {
uuid;
httpTransport;
webSocketTransport;
redisTransport;
host = 'localhost';
port;
requestListener;
allowedContextKeys;
isAuthEnabled = false;
auth;
debug = false;
rateLimit;
methods = new Map();
allClients = new Map();
channels = new Map();
events = new Map();
m;
acceptConnections = true;
ready = false;
shouldAllowChannelSubscribe = async () => true;
static ERROR_EVENT = 'error';
handlers = {};
constructor({ host = 'localhost', port = 80, debug = false, origins, ws, redis, requestListener, globalInstance = true, allowedContextKeys = [], rateLimit = false, } = {}) {
super(utils_1.NO_CHANNEL);
this.m = (0, create_method_proxy_1.createMethodProxy)(this);
this.setServer(this);
this.createDefaultMethods();
if (globalInstance) {
if (global.Helene)
throw new Error('There can only be one instance of Helene.');
global.Helene = this;
}
assert.ok(host, 'Invalid Host');
assert.ok(port, 'Invalid Port');
this.host = host;
this.port = Number(port);
this.requestListener = requestListener;
this.debug = debug;
this.uuid = utils_1.Presentation.uuid();
this.rateLimit = rateLimit;
this.allowedContextKeys = allowedContextKeys;
this.httpTransport = new transports_1.HttpTransport(this, origins, this.rateLimit);
this.webSocketTransport = new transports_1.WebSocketTransport(this, origins, ws);
this.httpTransport.http.listen(this.port, this.host, () => {
(0, defer_1.default)(() => {
this.server.emit(utils_1.ServerEvents.HTTP_LISTENING);
});
});
this.redisTransport = redis ? new transports_1.RedisTransport(this, redis) : null;
this.addEvent(utils_1.HeleneEvents.METHOD_REFRESH);
this.channels.set(utils_1.NO_CHANNEL, this);
(0, utils_1.waitForAll)(this, [
utils_1.ServerEvents.HTTP_LISTENING,
this.redisTransport ? utils_1.ServerEvents.REDIS_CONNECT : null,
].filter(Boolean)).then(() => {
this.ready = true;
this.emit(utils_1.ServerEvents.READY, true);
});
}
isReady() {
return new Promise(resolve => {
if (this.ready)
resolve(true);
this.once(utils_1.ServerEvents.READY, resolve);
});
}
get express() {
return this.httpTransport.express;
}
setAuth({ auth, logIn }) {
this.isAuthEnabled = true;
this.auth = auth;
this.addMethod(utils_1.Methods.RPC_LOGIN, logIn);
}
setChannelAuthorization(checker) {
this.shouldAllowChannelSubscribe = checker;
}
async close() {
this.allClients.forEach(node => node.close());
this.allClients.clear();
this.methods.clear();
this.channels.forEach(channel => channel.clear());
this.channels.clear();
await this.redisTransport?.close();
await this.webSocketTransport?.close();
await this.httpTransport?.close();
delete global.Helene;
this.emit(utils_1.ServerEvents.CLOSED);
return true;
}
static(path, catchAll) {
return this.httpTransport.static(path, catchAll);
}
debugger(...args) {
if (this.debug)
console.debug(...args);
}
async call(method, params) {
this.debugger(`[server] Calling ${method}`, params);
const methodInstance = this.methods.get(method);
const node = new client_node_1.ClientNode(this);
node.isServer = true;
return await methodInstance.exec(params, node);
}
createDefaultMethods() {
Object.entries(default_methods_1.DefaultMethods).forEach(([key, value]) => this.methods.set(key, value(this, key)));
}
getMethod(method) {
return this.methods.get(method);
}
addClient(node) {
this.allClients.set(node.uuid, node);
}
deleteClient(node) {
this.allClients.delete(node.uuid);
this.channels.forEach(channel => {
channel.deleteClientNode(node);
if (channel.clients.size === 0) {
this.channels.delete(channel.channelName);
}
});
}
addMethod(method, fn, opts) {
this.methods.set(method, new method_1.Method(this, method, fn, opts));
}
channel(name = utils_1.NO_CHANNEL) {
if ((0, isObject_1.default)(name) &&
name.constructor.name === 'ObjectId' &&
(0, isFunction_1.default)(name.toString)) {
name = name.toString();
}
if (!name || !(0, isString_1.default)(name))
return this;
if (name === utils_1.NO_CHANNEL)
return this;
if (this.channels.has(name))
return this.channels.get(name);
const channel = new server_channel_1.ServerChannel(name);
channel.setServer(this.server);
this.channels.set(name, channel);
return channel;
}
}
exports.Server = Server;
function createServer(options) {
return new Server(options);
}
//# sourceMappingURL=server.js.map