UNPKG

@minimaltech/node-infra

Version:

Minimal Technology NodeJS Infrastructure - Loopback 4 Framework

156 lines 6.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseNetworkTcpServer = void 0; const base_helper_1 = require("../../base/base.helper"); const utilities_1 = require("../../utilities"); const date_utility_1 = require("../../utilities/date.utility"); const parse_utility_1 = require("../../utilities/parse.utility"); const omit_1 = __importDefault(require("lodash/omit")); class BaseNetworkTcpServer extends base_helper_1.BaseHelper { constructor(opts) { var _a, _b, _c; super({ scope: (_b = (_a = opts.scope) !== null && _a !== void 0 ? _a : opts.identifier) !== null && _b !== void 0 ? _b : BaseNetworkTcpServer.name, identifier: opts.identifier, }); this.serverOptions = {}; this.listenOptions = {}; this.clients = Object.assign({}); this.serverOptions = opts.serverOptions; this.listenOptions = opts.listenOptions; this.authenticateOptions = opts.authenticateOptions; if (this.authenticateOptions.required && (!this.authenticateOptions.duration || this.authenticateOptions.duration < 0)) { throw (0, utilities_1.getError)({ message: 'TCP Server | Invalid authenticate duration | Required duration for authenticateOptions', }); } this.extraEvents = (_c = opts.extraEvents) !== null && _c !== void 0 ? _c : {}; this.createServerFn = opts.createServerFn; this.onServerReady = opts.onServerReady; this.onClientConnected = opts.onClientConnected; this.onClientData = opts.onClientData; this.onClientClose = opts.onClientClose; this.configure(); } configure() { this.server = this.createServerFn(this.serverOptions, socket => { this.onNewConnection({ socket }); }); this.server.listen(this.listenOptions, () => { var _a; this.logger.info('[configure] TCP Socket Server is now listening | Options: %j', this.listenOptions); (_a = this.onServerReady) === null || _a === void 0 ? void 0 : _a.call(this, { server: this.server }); }); } onNewConnection(opts) { var _a; const { socket } = opts; const id = (0, parse_utility_1.getUID)(); socket.on('data', (data) => { var _a; (_a = this.onClientData) === null || _a === void 0 ? void 0 : _a.call(this, { id, socket, data }); }); socket.on('error', (error) => { var _a; this.logger.error('[onClientConnect][error] ID: %s | Error: %s', id, error); (_a = this.onClientError) === null || _a === void 0 ? void 0 : _a.call(this, { id, socket, error }); socket.end(); }); socket.on('close', (hasError) => { var _a; this.logger.info('[onClientConnect][close] ID: %s | hasError: %s', id, hasError); (_a = this.onClientClose) === null || _a === void 0 ? void 0 : _a.call(this, { id, socket }); this.clients = (0, omit_1.default)(this.clients, [id]); }); for (const extraEvent in this.extraEvents) { socket.on(extraEvent, args => { this.extraEvents[extraEvent]({ id, socket, args }); }); } this.clients[id] = { id, socket, state: this.authenticateOptions.required ? 'unauthorized' : 'authenticated', subscriptions: new Set([]), storage: { connectedAt: (0, date_utility_1.dayjs)(), authenticatedAt: this.authenticateOptions.required ? null : (0, date_utility_1.dayjs)(), }, }; this.logger.info('[onClientConnect] New TCP SocketClient | Client: %s | authenticateOptions: %s %s', `${id} - ${socket.remoteAddress} - ${socket.remotePort} - ${socket.remoteFamily}`, this.authenticateOptions.required, this.authenticateOptions.duration); (_a = this.onClientConnected) === null || _a === void 0 ? void 0 : _a.call(this, { id, socket }); // Check client authentication if (this.authenticateOptions.required && this.authenticateOptions.duration && this.authenticateOptions.duration > 0) { setTimeout(() => { const client = this.getClient({ id }); if (!client) { return; } if (client.state === 'authenticated') { return; } this.emit({ clientId: id, payload: 'Unauthorized Client' }); client.socket.end(); }, this.authenticateOptions.duration); } } getClients() { return this.clients; } getClient(opts) { var _a; return (_a = this.clients) === null || _a === void 0 ? void 0 : _a[opts.id]; } getServer() { return this.server; } doAuthenticate(opts) { const { id, state } = opts; const client = this.getClient({ id }); if (!client) { this.logger.error('[authenticateClient][%s] Client %s NOT FOUND', id); return; } client.state = state; switch (state) { case 'unauthorized': case 'authenticating': { client.storage.authenticatedAt = null; break; } case 'authenticated': { client.storage.authenticatedAt = (0, date_utility_1.dayjs)(); break; } default: { break; } } } emit(opts) { const { clientId, payload } = opts; const client = this.getClient({ id: clientId }); if (!client) { this.logger.error('[emit][%s] Client %s NOT FOUND', clientId); return; } const { socket } = client; if (!socket.writable) { this.logger.error('[emit][%s] Client %s NOT WRITABLE', clientId); return; } if (!(payload === null || payload === void 0 ? void 0 : payload.length)) { this.logger.info('[emit][%s] Client %s | Invalid payload to write to TCP Socket!', this.identifier, clientId); return; } socket.write(payload); } } exports.BaseNetworkTcpServer = BaseNetworkTcpServer; //# sourceMappingURL=base-tcp-server.helper.js.map