import * as plugins from './typedsocket.plugins'; import type * as smartexpress from '@pushrocks/smartexpress'; const publicRoleName = 'publicRoleName'; const publicRolePass = 'publicRolePass'; export class TypedSocket { // STATIC /** * creates a typedsocket server * note: this will fail in browser environments as server libs are not bundled. */ public static async createServer( typedrouterArg: plugins.typedrequest.TypedRouter, smartexpressServerArg?: smartexpress.Server ): Promise { const smartsocketServer = new plugins.smartsocket.Smartsocket({ port: 3000, }); if (smartexpressServerArg) { smartsocketServer.setExternalServer('smartexpress', smartexpressServerArg); } const publicRole = new plugins.smartsocket.SocketRole({ name: publicRoleName, passwordHash: await plugins.isohash.sha256FromString(publicRolePass), }); smartsocketServer.addSocketRoles([publicRole]); smartsocketServer.socketFunctions.add( new plugins.smartsocket.SocketFunction({ funcName: 'processMessage', allowedRoles: [publicRole], funcDef: async (dataArg, socketConnectionArg) => { return typedrouterArg.routeAndAddResponse(dataArg); }, }) ); const typedsocket = new TypedSocket( typedrouterArg, async ( dataArg: T, targetConnectionArg?: plugins.smartsocket.SocketConnection ): Promise => { if (!targetConnectionArg) { if ((smartsocketServer.socketConnections.getArray().length = 1)) { console.log( 'Since no targetConnection was supplied and there is only one active one present, choosing that one automatically' ); targetConnectionArg = smartsocketServer.socketConnections.getArray()[0]; } else { throw new Error('you need to specify the wanted targetConnection'); } } const response: T = await smartsocketServer.clientCall( 'processMessage', dataArg, targetConnectionArg ) as any; return response; }, smartsocketServer ); if (smartexpressServerArg && smartexpressServerArg.serverStatus !== 'running') { await smartexpressServerArg.start() } await smartsocketServer.start(); return typedsocket; } public static async createClient( typedrouterArg: plugins.typedrequest.TypedRouter, serverUrlArg: string, aliasArg = 'clientArg' ): Promise { const domain = new plugins.smartstring.Domain(serverUrlArg); const smartsocketClient = new plugins.smartsocket.SmartsocketClient({ alias: aliasArg, role: publicRoleName, password: publicRolePass, port: domain.port || 3000, url: `${domain.nodeParsedUrl.protocol}//${domain.nodeParsedUrl.host}`, autoReconnect: true, }); smartsocketClient.addSocketFunction( new plugins.smartsocket.SocketFunction({ funcName: 'processMessage', allowedRoles: [], funcDef: async (dataArg, socketConnectionArg) => { return typedrouterArg.routeAndAddResponse(dataArg); }, }) ); const typedsocket = new TypedSocket( typedrouterArg, async (dataArg: T): Promise => { const response: T = (smartsocketClient.serverCall('processMessage', dataArg) as any) as T; return response; }, smartsocketClient ); await smartsocketClient.connect(); return typedsocket; } // INSTANCE public typedrouter: plugins.typedrequest.TypedRouter; private postMethod: plugins.typedrequest.IPostMethod & (( typedRequestPostObject: plugins.typedrequestInterfaces.ITypedRequest, socketConnectionArg?: plugins.smartsocket.SocketConnection ) => Promise); private socketServerOrClient: plugins.smartsocket.Smartsocket | plugins.smartsocket.SmartsocketClient; constructor( typedrouterArg: plugins.typedrequest.TypedRouter, postMethodArg: plugins.typedrequest.IPostMethod, socketServerOrClientArg: plugins.smartsocket.Smartsocket | plugins.smartsocket.SmartsocketClient ) { this.typedrouter = typedrouterArg; this.postMethod = postMethodArg; this.socketServerOrClient = socketServerOrClientArg; } public createTypedRequest( methodName: T['method'], targetConnection?: plugins.smartsocket.SocketConnection ): plugins.typedrequest.TypedRequest { const typedrequest = new plugins.typedrequest.TypedRequest( new plugins.typedrequest.TypedTarget({ postMethod: async (requestDataArg) => { const result = await this.postMethod(requestDataArg, targetConnection); return result; }, }), methodName ); return typedrequest; } public async findTargetConnection( findFuncArg: (connectionArg: plugins.smartsocket.SocketConnection) => boolean ) { if (this.socketServerOrClient instanceof plugins.smartsocket.Smartsocket) { for (const socketConnection of this.socketServerOrClient.socketConnections.getArray()) { if (findFuncArg(socketConnection)) { return socketConnection; } } } else { console.warn('this method >>findTargetConnection<< is only available from the server'); } } public async stop() { await this.socketServerOrClient.stop() } }