UNPKG

@loopeco/socketio

Version:

A enhanced LoopBack's WebSocket server based on socket.io

120 lines 5.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SocketIoControllerFactory = void 0; const core_1 = require("@loopback/core"); const decorators_1 = require("./decorators"); const keys_1 = require("./keys"); const types_1 = require("./types"); /** * A factory to instantiate socket.io controllers */ class SocketIoControllerFactory { constructor(parentCtx, controllerClass, socket) { var _a; this.controllerClass = controllerClass; this.connCtx = new types_1.SocketIoConnectionContext(socket, (_a = types_1.getConnectionContext(socket)) !== null && _a !== void 0 ? _a : parentCtx); this.connCtx.bind(core_1.CoreBindings.CONTROLLER_CLASS).to(this.controllerClass); this.connCtx.bind(core_1.CoreBindings.CONTROLLER_CURRENT).toClass(controllerClass).inScope(core_1.BindingScope.SINGLETON); } async create() { // Instantiate the controller instance this.controller = await this.connCtx.get(core_1.CoreBindings.CONTROLLER_CURRENT); await this.setup(); return this.controller; } /** * Set up the controller for the given socket */ async setup() { await this.connect(); this.registerSubscribeMethods(); } async connect() { const connectMethods = this.getDecoratedMethodsForConnect(); for (const methodName in connectMethods) { await core_1.invokeMethod(this.controller, methodName, this.connCtx, [this.connCtx.socket]); } } getDecoratedMethodsForConnect() { return this.getAllMethodMetadataForKey(decorators_1.SOCKET_IO_CONNECT_METADATA); } getDecorateSubscribeMethodsByEventName() { var _a; const eventMatchersInfo = new Map(); const subscribeMethods = this.getDecorateSubscribeMethods(); for (const methodName in subscribeMethods) { for (const matcher of subscribeMethods[methodName]) { const matcherString = matcher.toString(); const eventMatcherInfo = (_a = eventMatchersInfo.get(matcherString)) !== null && _a !== void 0 ? _a : { matcher: matcher, methodNames: [], }; eventMatcherInfo.methodNames.push(methodName); eventMatchersInfo.set(matcherString, eventMatcherInfo); } } return eventMatchersInfo; } getCallback(methodName) { return async (...args) => { let done = async (_response) => { }; if (typeof args[args.length - 1] === 'function') { done = args.pop(); } const eventCtx = new core_1.Context(this.connCtx); eventCtx.bind(keys_1.SocketIoBindings.MESSAGE).to(args); const sequence = await eventCtx.get(keys_1.SocketIoBindings.SEQUENCE); await sequence.handle(methodName, args, done); }; } registerSubscribeMethods() { const methodsByEventHandler = this.getDecorateSubscribeMethodsByEventName(); const regexMethodsHandlers = new Map(); const methodHandlers = new Map(); methodsByEventHandler.forEach(eventMatcherInfo => { const { matcher, methodNames } = eventMatcherInfo; methodNames.forEach(methodName => { var _a; let handler = methodHandlers.get(methodName); if (!handler) { handler = this.getCallback(methodName); methodHandlers.set(methodName, handler); } if (matcher instanceof RegExp) { const handlers = (_a = regexMethodsHandlers.get(matcher)) !== null && _a !== void 0 ? _a : []; handlers.push(handler); regexMethodsHandlers.set(matcher, handlers); } else { this.connCtx.socket.on(matcher, handler); } }); }); // Register event handlers with regexp if (regexMethodsHandlers.size) { // Use a socket middleware to match event names with regexp // eslint-disable-next-line @typescript-eslint/no-misused-promises this.connCtx.socket.use(async (packet, next) => { const [eventName, ...args] = packet; for (const iterator of regexMethodsHandlers.entries()) { const [regex, handlers] = iterator; if (eventName.match(regex)) { for (const handler of handlers) { await handler(...args); } } } next(); }); } } getDecorateSubscribeMethods() { return this.getAllMethodMetadataForKey(decorators_1.SOCKET_IO_SUBSCRIBE_METADATA); } getAllMethodMetadataForKey(metadataAccessor) { var _a; return ((_a = core_1.MetadataInspector.getAllMethodMetadata(metadataAccessor, this.controllerClass.prototype)) !== null && _a !== void 0 ? _a : {}); } } exports.SocketIoControllerFactory = SocketIoControllerFactory; //# sourceMappingURL=socketio-controller-factory.js.map