typedsocket/ts/typedsocket.classes.typedsocket.ts
2022-01-19 19:17:22 +01:00

206 lines
7.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as plugins from './typedsocket.plugins';
const publicRoleName = 'publicRoleName';
const publicRolePass = 'publicRolePass';
export type TTypedSocketSide = 'server' | 'client';
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?: any
): Promise<TypedSocket> {
const smartsocketServer = new plugins.smartsocket.Smartsocket({
alias: 'typedsocketServer',
port: 3000,
});
if (smartexpressServerArg) {
smartsocketServer.setExternalServer('smartexpress', smartexpressServerArg);
}
smartsocketServer.socketFunctions.add(
new plugins.smartsocket.SocketFunction({
funcName: 'processMessage',
funcDef: async (dataArg, socketConnectionArg) => {
return typedrouterArg.routeAndAddResponse(dataArg);
},
})
);
const typedsocket = new TypedSocket(
'server',
typedrouterArg,
async <T extends plugins.typedrequestInterfaces.ITypedRequest>(
dataArg: T,
targetConnectionArg?: plugins.smartsocket.SocketConnection
): Promise<T> => {
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. Currently no target is selectable automatically.');
}
}
const response: T = await smartsocketServer.clientCall(
'processMessage',
dataArg,
targetConnectionArg
) as any;
return response;
},
smartsocketServer
);
await smartsocketServer.start();
return typedsocket;
}
public static async createClient(
typedrouterArg: plugins.typedrequest.TypedRouter,
serverUrlArg: string,
aliasArg = 'clientArg'
): Promise<TypedSocket> {
const domain = new plugins.smartstring.Domain(serverUrlArg);
const socketOptions: plugins.smartsocket.ISmartsocketClientOptions = {
alias: aliasArg,
port: domain.port || 3000,
url: `${domain.nodeParsedUrl.protocol}//${domain.nodeParsedUrl.hostname}`,
autoReconnect: true,
}
console.log(`starting typedsocket with the following settings:`)
console.log(socketOptions);
const smartsocketClient = new plugins.smartsocket.SmartsocketClient(socketOptions);
smartsocketClient.addSocketFunction(
new plugins.smartsocket.SocketFunction({
funcName: 'processMessage',
funcDef: async (dataArg, socketConnectionArg) => {
return typedrouterArg.routeAndAddResponse(dataArg);
},
})
);
const typedsocket = new TypedSocket(
'client',
typedrouterArg,
async <T extends plugins.typedrequestInterfaces.ITypedRequest>(dataArg: T): Promise<T> => {
const response: T = (smartsocketClient.serverCall('processMessage', dataArg) as any) as T;
return response;
},
smartsocketClient
);
await smartsocketClient.connect();
return typedsocket;
}
// INSTANCE
public side: TTypedSocketSide;
public typedrouter: plugins.typedrequest.TypedRouter;
private postMethod: plugins.typedrequest.IPostMethod &
((
typedRequestPostObject: plugins.typedrequestInterfaces.ITypedRequest,
socketConnectionArg?: plugins.smartsocket.SocketConnection
) => Promise<plugins.typedrequestInterfaces.ITypedRequest>);
private socketServerOrClient: plugins.smartsocket.Smartsocket | plugins.smartsocket.SmartsocketClient;
constructor(
sideArg: TTypedSocketSide,
typedrouterArg: plugins.typedrequest.TypedRouter,
postMethodArg: plugins.typedrequest.IPostMethod,
socketServerOrClientArg: plugins.smartsocket.Smartsocket | plugins.smartsocket.SmartsocketClient
) {
this.side = sideArg;
this.typedrouter = typedrouterArg;
this.postMethod = postMethodArg;
this.socketServerOrClient = socketServerOrClientArg;
}
public addTag(keyArg: string, payloadArg: any) {
if (this.side === 'client' && this.socketServerOrClient instanceof plugins.smartsocket.SmartsocketClient) {
this.socketServerOrClient.socketConnection.addTag({
id: keyArg,
payload: payloadArg
})
} else {
throw new Error('tagging is only supported on clients');
}
}
public createTypedRequest<T extends plugins.typedrequestInterfaces.ITypedRequest>(
methodName: T['method'],
targetConnection?: plugins.smartsocket.SocketConnection
): plugins.typedrequest.TypedRequest<T> {
const typedrequest = new plugins.typedrequest.TypedRequest<T>(
new plugins.typedrequest.TypedTarget({
postMethod: async (requestDataArg) => {
const result = await this.postMethod(requestDataArg, targetConnection);
return result;
},
}),
methodName
);
return typedrequest;
}
/**
* returns all matching target connection
* @param asyncFindFuncArg
* @returns
*/
public async findAllTargetConnections(
asyncFindFuncArg: (connectionArg: plugins.smartsocket.SocketConnection) => Promise<boolean>
) {
if (this.socketServerOrClient instanceof plugins.smartsocket.Smartsocket) {
const matchingSockets: plugins.smartsocket.SocketConnection[] = [];
for (const socketConnection of this.socketServerOrClient.socketConnections.getArray()) {
if (await asyncFindFuncArg(socketConnection)) {
matchingSockets.push(socketConnection);
}
}
return matchingSockets;
} else {
throw new Error('this method >>findTargetConnection<< is only available from the server');
}
}
/**
* returns a single target connection by returning the first one of all matching ones
* @param asyncFindFuncArg
* @returns
*/
public async findTargetConnection(
asyncFindFuncArg: (connectionArg: plugins.smartsocket.SocketConnection) => Promise<boolean>
) {
const allMatching = await this.findAllTargetConnections(asyncFindFuncArg);
return allMatching[0];
}
public async findAllTargetConnectionsByTag(keyArg: string, payloadArg?: any) {
return this.findAllTargetConnections(async socketConnectionArg => {
let result: boolean;
if (!payloadArg) {
result = !!socketConnectionArg.getTagById(keyArg);
} else {
result = !!socketConnectionArg.getTagById(keyArg) === payloadArg;
}
return result;
})
}
public async findTargetConnectionByTag(keyArg: string, payloadArg?: any) {
const allResults = await this.findAllTargetConnectionsByTag(keyArg, payloadArg)
return allResults[0];
}
public async stop() {
await this.socketServerOrClient.stop()
}
}