stuff
This commit is contained in:
+24
-18
@@ -1,50 +1,56 @@
|
||||
'use strict'
|
||||
|
||||
var bsock = require('bsock')
|
||||
|
||||
import { ExtendedRpcInfo, UnhookFunction, CallbackFunction, AsyncFunction } from "./Types";
|
||||
import { Socket } from './interfaces/Socket'
|
||||
import * as I from './Interfaces';
|
||||
import * as T from './Types';
|
||||
|
||||
|
||||
//fix args with defaults like "force = true" -> "force"
|
||||
function stripAfterEquals(str:string){
|
||||
return str.split("=")[0]
|
||||
}
|
||||
|
||||
export class Client implements Socket{
|
||||
private socket: Socket
|
||||
export class Client implements I.Socket{
|
||||
|
||||
private socket: I.Socket
|
||||
constructor(public port:number, private server: string, private tls: boolean = false){
|
||||
}
|
||||
|
||||
hook(name, args){
|
||||
|
||||
|
||||
public hook(name: T.Name, args: T.Arg){
|
||||
return this.socket.hook(name, args)
|
||||
}
|
||||
|
||||
unhook(name){
|
||||
public unhook(name: T.Name){
|
||||
return this.socket.unhook(name)
|
||||
}
|
||||
|
||||
on(type: "error" | "close", f: (e?: any) => void){
|
||||
return this.socket.on(type, name)
|
||||
public on(type: "error" | "close", f: (e?: any) => void){
|
||||
return this.socket.on(type, f)
|
||||
}
|
||||
|
||||
destroy(){
|
||||
public destroy(){
|
||||
return this.socket.destroy()
|
||||
}
|
||||
|
||||
close(){
|
||||
public close(){
|
||||
return this.socket.close()
|
||||
}
|
||||
|
||||
async call (rpcname: string, ...args: any[]) : Promise<any>{
|
||||
public async call (rpcname: T.Name, ...args: T.Any[]) : Promise<T.Any>{
|
||||
return await this.socket.call.apply(this.socket, [rpcname, ...args])
|
||||
}
|
||||
|
||||
async fire(rpcname: string, ...args: any[]) : Promise<any>{
|
||||
public async fire(rpcname: T.Name, ...args: T.Any[]) : Promise<T.Any>{
|
||||
return await this.socket.fire.apply(this.socket, [rpcname, ...args])
|
||||
}
|
||||
|
||||
async connect(){
|
||||
public async connect(){
|
||||
this.socket = await bsock.connect(this.port, this.server, this.tls)
|
||||
|
||||
const info:ExtendedRpcInfo[] = await this.info()
|
||||
const info:T.ExtendedRpcInfo[] = await this.info()
|
||||
info.forEach(i => {
|
||||
let f: any
|
||||
switch (i.type) {
|
||||
@@ -65,17 +71,17 @@ export class Client implements Socket{
|
||||
})
|
||||
}
|
||||
|
||||
async info(){
|
||||
public async info(){
|
||||
return await this.socket.call('info')
|
||||
}
|
||||
|
||||
private callGenerator(fnName, fnArgs:string[]): AsyncFunction{
|
||||
private callGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.AsyncFunction{
|
||||
const headerArgs = fnArgs.join(",")
|
||||
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
||||
return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", '+argParams+')} )()' )
|
||||
}
|
||||
|
||||
private hookGenerator(fnName, fnArgs:string[]): CallbackFunction{
|
||||
private hookGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.CallbackFunction{
|
||||
const headerArgs = fnArgs.join(",")
|
||||
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
||||
return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
|
||||
@@ -87,7 +93,7 @@ export class Client implements Socket{
|
||||
} )()` )
|
||||
}
|
||||
|
||||
private unhookGenerator(fnName, fnArgs:string[]): UnhookFunction{
|
||||
private unhookGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.UnhookFunction{
|
||||
const headerArgs = fnArgs.join(",")
|
||||
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
||||
if(fnArgs.length != 1)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import * as T from "./Types";
|
||||
import * as I from "./Interfaces"
|
||||
|
||||
export interface Exporter{
|
||||
name: T.Name
|
||||
localRPCs() : T.RPC[]
|
||||
publicRPCs() : T.RPC[]
|
||||
}
|
||||
|
||||
export interface Socket {
|
||||
port: number
|
||||
hook: (rpcname: T.Name, ...args: T.Any[]) => I.Socket
|
||||
unhook: (rpcname:T.Name) => I.Socket
|
||||
call: (rpcname:T.Name, ...args: T.Any[]) => Promise<T.Any>
|
||||
fire: (rpcname:T.Name, ...args: T.Any[]) => Promise<T.Any>
|
||||
on: T.OnFunction
|
||||
destroy: ()=>void
|
||||
close: ()=>void
|
||||
}
|
||||
+26
-26
@@ -1,23 +1,23 @@
|
||||
'use strict'
|
||||
|
||||
import http = require('http');
|
||||
import bsock = require('bsock');
|
||||
|
||||
import { ExtendedRpcInfo, SocketConf, SocketioRPC } from './Types';
|
||||
import { rpcHooker } from './Util';
|
||||
import { Exporter } from './interfaces/Exporter';
|
||||
import { Socket } from "./interfaces/Socket";
|
||||
import * as T from './Types';
|
||||
import * as U from './Utils';
|
||||
import * as I from './Interfaces';
|
||||
|
||||
export class Server{
|
||||
|
||||
private ws = http.createServer()
|
||||
private io = bsock.createServer()
|
||||
private wsServer = http.createServer()
|
||||
|
||||
constructor(
|
||||
private port:number,
|
||||
private rpcExporters: Exporter[] = [],
|
||||
private conf: SocketConf = {
|
||||
errorHandler: (socket:Socket) => (error:any) => { socket.destroy(); console.error(error) },
|
||||
closeHandler: (socket:Socket) => () => { console.log("Socket closing") },
|
||||
connectionHandler: (socket:Socket) => { console.log("New websocket connection in port "+socket.port)},
|
||||
private exporters: I.Exporter[] = [],
|
||||
private conf: T.SocketConf = {
|
||||
errorHandler: (socket:I.Socket) => (error:any) => { socket.destroy(); console.error(error) },
|
||||
closeHandler: (socket:I.Socket) => () => { console.log("Socket closing") },
|
||||
connectionHandler: (socket:I.Socket) => { console.log("New websocket connection in port "+socket.port)},
|
||||
visibility: "127.0.0.1"
|
||||
}
|
||||
){
|
||||
@@ -26,8 +26,8 @@ export class Server{
|
||||
|
||||
private startWebsocket(){
|
||||
try{
|
||||
this.io.attach(this.wsServer)
|
||||
this.io.on('socket', (socket:Socket) => {
|
||||
this.io.attach(this.ws)
|
||||
this.io.on('socket', (socket:I.Socket) => {
|
||||
socket.on('error', this.conf.errorHandler(socket))
|
||||
socket.on('close', this.conf.closeHandler(socket))
|
||||
if(this.conf.visibility === "127.0.0.1")
|
||||
@@ -35,26 +35,26 @@ export class Server{
|
||||
else
|
||||
this.initPublicRPCs(socket)
|
||||
})
|
||||
this.wsServer.listen(this.port, this.conf.visibility)
|
||||
this.ws.listen(this.port, this.conf.visibility)
|
||||
}catch(e){
|
||||
//@ts-ignore
|
||||
this.errorHandler(undefined)("Unable to connect to socket")
|
||||
}
|
||||
}
|
||||
|
||||
protected initRPCs(socket:Socket){
|
||||
const infoRPC:SocketioRPC[] = [
|
||||
{
|
||||
name: 'info',
|
||||
type: 'Call',
|
||||
func: async () => rpcInfos
|
||||
}
|
||||
]
|
||||
const rpcInfos:ExtendedRpcInfo[] = [
|
||||
...rpcHooker(socket, "RPC", infoRPC, false),
|
||||
...this.rpcExporters.flatMap(exporter => rpcHooker(socket, exporter.name, [...exporter.exportPublicRPCs(), ...exporter.exportRPCs()]))
|
||||
protected initRPCs(socket:I.Socket){
|
||||
socket.hook('info', () => rpcInfos)
|
||||
|
||||
const rpcInfos:T.ExtendedRpcInfo[] = [
|
||||
...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
|
||||
protected initPublicRPCs(socket:Socket){}
|
||||
protected initPublicRPCs(socket:I.Socket){
|
||||
socket.hook('info', () => rpcInfos)
|
||||
|
||||
const rpcInfos:T.ExtendedRpcInfo[] = [
|
||||
...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
}
|
||||
+23
-20
@@ -1,44 +1,47 @@
|
||||
import { SuccessResponse, ErrorResponse, SubscriptionResponse } from "./Response";
|
||||
import { Socket } from "./interfaces/Socket";
|
||||
import * as R from "./Responses";
|
||||
import * as I from "./Interfaces";
|
||||
|
||||
export type Visibility = "127.0.0.1" | "0.0.0.0"
|
||||
export type Name = string
|
||||
export type Any = any
|
||||
export type Arg = string
|
||||
export type Name = Arg
|
||||
export type Owner = Name
|
||||
|
||||
export type SocketConf = {
|
||||
connectionHandler: (socket:Socket) => void
|
||||
errorHandler: (socket:Socket) => (error:any) => void
|
||||
closeHandler: (socket:Socket) => () => void
|
||||
connectionHandler: (socket:I.Socket) => void
|
||||
errorHandler: (socket:I.Socket) => (error:any) => void
|
||||
closeHandler: (socket:I.Socket) => () => void
|
||||
visibility: Visibility
|
||||
}
|
||||
|
||||
export type rpcType = 'Hook' | 'Unhook' | 'Call'
|
||||
export type RPCType = 'Hook' | 'Unhook' | 'Call'
|
||||
|
||||
export type BaseRPC = {
|
||||
type: rpcType
|
||||
name: string
|
||||
type: RPCType
|
||||
name: Name
|
||||
}
|
||||
|
||||
export type HookRPC = BaseRPC & {
|
||||
type: 'Hook'
|
||||
func: CallbackFunction
|
||||
clbk: CallbackFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
export type UnhookRPC = BaseRPC & {
|
||||
type: 'Unhook'
|
||||
func: UnhookFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
export type CallRPC = BaseRPC & {
|
||||
type: 'Call'
|
||||
func: (...args) => Promise<any>
|
||||
call: AsyncFunction
|
||||
}
|
||||
|
||||
export type SocketioRPC = CallRPC | UnhookRPC | HookRPC
|
||||
export type RPC = CallRPC | UnhookRPC | HookRPC
|
||||
|
||||
export type BaseInfo = {
|
||||
owner: string,
|
||||
argNames: string[],
|
||||
owner: Name,
|
||||
argNames: Name[],
|
||||
}
|
||||
|
||||
export type HookInfo = BaseRPC & BaseInfo & {
|
||||
@@ -49,18 +52,18 @@ export type HookInfo = BaseRPC & BaseInfo & {
|
||||
|
||||
export type UnhookInfo = BaseRPC & BaseInfo & {
|
||||
type: 'Unhook',
|
||||
func: UnhookFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
export type CallInfo = BaseRPC & BaseInfo & {
|
||||
type: 'Call',
|
||||
func: AsyncFunction
|
||||
call: AsyncFunction
|
||||
}
|
||||
|
||||
export type RpcInfo = HookInfo | UnhookInfo | CallInfo
|
||||
export type ExtendedRpcInfo = RpcInfo & { uniqueName: string }
|
||||
|
||||
export type OnFunction = (type: 'error' | 'close', f: (e?:any)=>void) => Socket
|
||||
export type UnhookFunction = (uid:string) => Promise<SuccessResponse | ErrorResponse>
|
||||
export type CallbackFunction = (...args) => Promise<SubscriptionResponse | ErrorResponse>
|
||||
export type OnFunction = (type: 'error' | 'close', f: (e?:any)=>void) => I.Socket
|
||||
export type UnhookFunction = (uid:string) => Promise<R.SuccessResponse | R.ErrorResponse>
|
||||
export type CallbackFunction = (...args) => Promise<R.SubscriptionResponse | R.ErrorResponse>
|
||||
export type AsyncFunction = (...args) => Promise<any>
|
||||
|
||||
+20
-15
@@ -1,25 +1,25 @@
|
||||
import * as uuid from "uuid/v4"
|
||||
|
||||
import { HookRPC, HookInfo, SocketioRPC, RpcInfo, ExtendedRpcInfo } from "./Types";
|
||||
import { Socket } from "./interfaces/Socket";
|
||||
import * as T from "./Types";
|
||||
import * as I from "./Interfaces";
|
||||
|
||||
export const rpcToRpcinfo = (rpc : SocketioRPC, owner: string):RpcInfo => {
|
||||
export const rpcToRpcinfo = (rpc : T.RPC, owner: T.Owner):T.RpcInfo => {
|
||||
switch(rpc.type){
|
||||
case "Call" :
|
||||
return {
|
||||
owner: owner,
|
||||
argNames: extractArgs(rpc.func),
|
||||
argNames: extractArgs(rpc.call),
|
||||
type: rpc.type,
|
||||
name: rpc.name,
|
||||
func: rpc.func,
|
||||
call: rpc.call,
|
||||
}
|
||||
case "Unhook" :
|
||||
return {
|
||||
owner: owner,
|
||||
argNames: extractArgs(rpc.func),
|
||||
argNames: extractArgs(rpc.unhook),
|
||||
type: rpc.type,
|
||||
name: rpc.name,
|
||||
func: rpc.func,
|
||||
unhook: rpc.unhook,
|
||||
}
|
||||
case "Hook" :
|
||||
const generator = hookGenerator(rpc)
|
||||
@@ -33,8 +33,9 @@ export const rpcToRpcinfo = (rpc : SocketioRPC, owner: string):RpcInfo => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const rpcHooker = (socket: Socket, owner:string, RPCs: SocketioRPC[], makeUnique = true):ExtendedRpcInfo[] => {
|
||||
export function rpcHooker(socket: I.Socket, exporter:I.Exporter, makeUnique = true):T.ExtendedRpcInfo[]{
|
||||
const owner = exporter.name
|
||||
const RPCs = [...exporter.publicRPCs(), ...exporter.localRPCs()]
|
||||
const suffix = makeUnique?"-"+uuid().substr(0,4):""
|
||||
return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
|
||||
.map(info => {
|
||||
@@ -45,21 +46,25 @@ export const rpcHooker = (socket: Socket, owner:string, RPCs: SocketioRPC[], mak
|
||||
case "Hook":
|
||||
socket.hook(ret.uniqueName, info.generator(socket))
|
||||
break;
|
||||
default:
|
||||
socket.hook(ret.uniqueName, info.func)
|
||||
case "Unhook":
|
||||
socket.hook(ret.uniqueName, info.unhook)
|
||||
break;
|
||||
case "Call":
|
||||
socket.hook(ret.uniqueName, info.call)
|
||||
break;
|
||||
}
|
||||
socket.on('close', () => socket.unhook(info.name))
|
||||
return ret
|
||||
})
|
||||
}
|
||||
|
||||
const hookGenerator = (rpc:HookRPC): HookInfo['generator'] => {
|
||||
const argsArr = extractArgs(rpc.func)
|
||||
const hookGenerator = (rpc:T.HookRPC): T.HookInfo['generator'] => {
|
||||
const argsArr = extractArgs(rpc.clbk)
|
||||
argsArr.pop()
|
||||
const args = argsArr.join(',')
|
||||
|
||||
return eval(`(socket) => async (`+args+`) => {
|
||||
const res = await rpc.func(`+args+(args.length!==0?',':'')+` (x) => {
|
||||
const res = await rpc.clbk(`+args+(args.length!==0?',':'')+` (x) => {
|
||||
socket.call(res.uid, x)
|
||||
})
|
||||
if(res.result == 'Success'){
|
||||
@@ -73,7 +78,7 @@ const hookGenerator = (rpc:HookRPC): HookInfo['generator'] => {
|
||||
}`)
|
||||
}
|
||||
|
||||
const extractArgs = (f:Function):string[] => {
|
||||
const extractArgs = (f:Function):T.Arg[] => {
|
||||
let fn = String(f)
|
||||
let args = fn.substr(0, fn.indexOf(")"))
|
||||
args = args.substr(fn.indexOf("(")+1)
|
||||
@@ -1,256 +0,0 @@
|
||||
import http = require('http');
|
||||
import bsock = require('bsock');
|
||||
|
||||
import * as uuid from "uuid/v4"
|
||||
import { Socket } from "./RPCSocketServer"
|
||||
|
||||
type rpcType = 'hook' | 'unhook' | 'call'
|
||||
export type Outcome = "Success" | "Error"
|
||||
export type Visibility = "127.0.0.1" | "0.0.0.0"
|
||||
|
||||
/* Responses */
|
||||
export class Response{
|
||||
constructor(
|
||||
public message?:string
|
||||
){}
|
||||
}
|
||||
|
||||
export class SuccessResponse extends Response{
|
||||
result:Outcome = "Success"
|
||||
|
||||
constructor(
|
||||
message?:string
|
||||
){
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorResponse extends Response{
|
||||
result:Outcome = "Error"
|
||||
|
||||
constructor(
|
||||
message: string = "Unknown error"
|
||||
){
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
|
||||
export class SubscriptionResponse extends SuccessResponse{
|
||||
constructor(
|
||||
public uid: string,
|
||||
message?:string
|
||||
){
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
export type UnhookFunction = (uid:string) => Promise<SuccessResponse | ErrorResponse>
|
||||
export type callbackFunction = (...args) => Promise<SubscriptionResponse | ErrorResponse>
|
||||
export type AsyncFunction = (...args) => Promise<any>
|
||||
|
||||
export interface RPCExporter{
|
||||
name: string
|
||||
exportRPCs() : socketioRPC[]
|
||||
exportPublicRPCs() : socketioRPC[]
|
||||
}
|
||||
|
||||
type baseRPC = {
|
||||
type: rpcType
|
||||
name: string
|
||||
}
|
||||
|
||||
type hookRPC = baseRPC & {
|
||||
type: 'hook'
|
||||
func: callbackFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
type unhookRPC = baseRPC & {
|
||||
type: 'unhook'
|
||||
func: UnhookFunction
|
||||
}
|
||||
|
||||
type callRPC = baseRPC & {
|
||||
type: 'call'
|
||||
func: (...args) => Promise<any>
|
||||
}
|
||||
|
||||
export type socketioRPC = callRPC | unhookRPC | hookRPC
|
||||
|
||||
export type baseInfo = {
|
||||
owner: string,
|
||||
argNames: string[],
|
||||
}
|
||||
|
||||
type HookInfo = baseRPC & baseInfo & {
|
||||
type: 'hook',
|
||||
generator: (socket) => callbackFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
type UnhookInfo = baseRPC & baseInfo & {
|
||||
type: 'unhook',
|
||||
func: UnhookFunction
|
||||
}
|
||||
|
||||
type CallInfo = baseRPC & baseInfo & {
|
||||
type: 'call',
|
||||
func: AsyncFunction
|
||||
}
|
||||
|
||||
type RpcInfo = HookInfo | UnhookInfo | CallInfo
|
||||
|
||||
export type ExtendedRpcInfo = RpcInfo & { uniqueName: string }
|
||||
|
||||
export const rpcToRpcinfo = (rpc : socketioRPC, owner: string):RpcInfo => {
|
||||
switch(rpc.type){
|
||||
case "call" :
|
||||
return {
|
||||
owner: owner,
|
||||
argNames: extractArgs(rpc.func),
|
||||
type: rpc.type,
|
||||
name: rpc.name,
|
||||
func: rpc.func,
|
||||
}
|
||||
case "unhook" :
|
||||
return {
|
||||
owner: owner,
|
||||
argNames: extractArgs(rpc.func),
|
||||
type: rpc.type,
|
||||
name: rpc.name,
|
||||
func: rpc.func,
|
||||
}
|
||||
case "hook" :
|
||||
const generator = hookGenerator(rpc)
|
||||
return {
|
||||
owner: owner,
|
||||
argNames: extractArgs(generator(undefined)),
|
||||
type: rpc.type,
|
||||
name: rpc.name,
|
||||
unhook: rpc.unhook,
|
||||
generator: generator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rpcHooker(socket: Socket, exporter:RPCExporter, makeUnique = true):ExtendedRpcInfo[]{
|
||||
const owner = exporter.name
|
||||
const RPCs = [...exporter.exportPublicRPCs(), ...exporter.exportRPCs()]
|
||||
const suffix = makeUnique?"-"+uuid().substr(0,4):""
|
||||
return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
|
||||
.map(info => {
|
||||
const ret:any = info
|
||||
ret.uniqueName = info.name+suffix
|
||||
|
||||
switch(info.type){
|
||||
case "hook":
|
||||
socket.hook(ret.uniqueName, info.generator(socket))
|
||||
break;
|
||||
default:
|
||||
socket.hook(ret.uniqueName, info.func)
|
||||
}
|
||||
socket.on('close', () => socket.unhook(info.name))
|
||||
return ret
|
||||
})
|
||||
}
|
||||
|
||||
const hookGenerator = (rpc:hookRPC): HookInfo['generator'] => {
|
||||
const argsArr = extractArgs(rpc.func)
|
||||
argsArr.pop()
|
||||
const args = argsArr.join(',')
|
||||
|
||||
return eval(`(socket) => async (`+args+`) => {
|
||||
const res = await rpc.func(`+args+(args.length!==0?',':'')+` (x) => {
|
||||
socket.call(res.uid, x)
|
||||
})
|
||||
if(res.result == 'Success'){
|
||||
socket.on('close', async () => {
|
||||
const unhookRes = await rpc.unhook(res.uid)
|
||||
console.log("Specific close handler for", rpc.name, res.uid, unhookRes)
|
||||
})
|
||||
|
||||
}
|
||||
return res
|
||||
}`)
|
||||
}
|
||||
|
||||
const extractArgs = (f:Function):string[] => {
|
||||
let fn = String(f)
|
||||
let args = fn.substr(0, fn.indexOf(")"))
|
||||
args = args.substr(fn.indexOf("(")+1)
|
||||
let ret = args.split(",")
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
type OnFunction = (type: 'error' | 'close', f: (e?:any)=>void) => Socket
|
||||
|
||||
export interface Socket {
|
||||
port: number
|
||||
hook: (rpcname: string, ...args: any[]) => Socket
|
||||
unhook: (rpcname:string) => Socket
|
||||
call: (rpcname:string, ...args: any[]) => Promise<any>
|
||||
fire: (rpcname:string, ...args: any[]) => Promise<any>
|
||||
on: OnFunction
|
||||
destroy: ()=>void
|
||||
close: ()=>void
|
||||
}
|
||||
|
||||
export type RPCSocketConf = {
|
||||
connectionHandler: (socket:Socket) => void
|
||||
errorHandler: (socket:Socket) => (error:any) => void
|
||||
closeHandler: (socket:Socket) => () => void
|
||||
}
|
||||
|
||||
export class RPCSocketServer{
|
||||
|
||||
private io = bsock.createServer()
|
||||
private wsServer = http.createServer()
|
||||
|
||||
constructor(
|
||||
private port:number,
|
||||
private rpcExporters: RPCExporter[] = [],
|
||||
private visibility: Visibility = "127.0.0.1",
|
||||
private conf: RPCSocketConf = {
|
||||
errorHandler: (socket:Socket) => (error:any) => { socket.destroy(); console.error(error) },
|
||||
closeHandler: (socket:Socket) => () => { console.log("Socket closing") },
|
||||
connectionHandler: (socket:Socket) => { console.log("New websocket connection in port "+socket.port) }
|
||||
}
|
||||
){
|
||||
this.startWebsocket()
|
||||
}
|
||||
|
||||
private startWebsocket(){
|
||||
try{
|
||||
this.io.attach(this.wsServer)
|
||||
this.io.on('socket', (socket:Socket) => {
|
||||
socket.on('error', this.conf.errorHandler(socket))
|
||||
socket.on('close', this.conf.closeHandler(socket))
|
||||
if(this.visibility === "127.0.0.1")
|
||||
this.initRPCs(socket)
|
||||
else
|
||||
this.initPublicRPCs(socket)
|
||||
})
|
||||
this.wsServer.listen(this.port, this.visibility)
|
||||
}catch(e){
|
||||
//@ts-ignore
|
||||
this.errorHandler(undefined)("Unable to connect to socket")
|
||||
}
|
||||
}
|
||||
|
||||
protected initRPCs(socket:Socket){
|
||||
socket.hook('info', () => rpcInfos)
|
||||
|
||||
const rpcInfos:ExtendedRpcInfo[] = [
|
||||
...this.rpcExporters.flatMap(exporter => rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
|
||||
protected initPublicRPCs(socket:Socket){
|
||||
socket.hook('info', () => rpcInfos)
|
||||
|
||||
const rpcInfos:ExtendedRpcInfo[] = [
|
||||
...this.rpcExporters.flatMap(exporter => rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { SocketioRPC, Name } from "../Types";
|
||||
|
||||
export interface Exporter{
|
||||
name: Name
|
||||
exportRPCs() : SocketioRPC[]
|
||||
exportPublicRPCs() : SocketioRPC[]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { OnFunction } from "../Types";
|
||||
|
||||
export interface Socket {
|
||||
port: number
|
||||
hook: (rpcname: string, ...args: any[]) => Socket
|
||||
unhook: (rpcname:string) => Socket
|
||||
call: (rpcname:string, ...args: any[]) => Promise<any>
|
||||
fire: (rpcname:string, ...args: any[]) => Promise<any>
|
||||
on: OnFunction
|
||||
destroy: ()=>void
|
||||
close: ()=>void
|
||||
}
|
||||
+43
-11
@@ -1,27 +1,59 @@
|
||||
const path = require('path');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
const frontendConf = {
|
||||
mode: 'production',
|
||||
target: "web",
|
||||
entry: path.resolve(__dirname, 'Client.ts'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../lib'),
|
||||
filename: 'Frontend.js',
|
||||
libraryTarget: 'commonjs',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.ts?$/, loader: "ts-loader" }
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"]
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
exclude: [
|
||||
/\.\/(.*)\/.ts/,
|
||||
/\.\/(.*).ts/,
|
||||
],
|
||||
}),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const backendConf = {
|
||||
mode: 'production',
|
||||
target: "web",
|
||||
entry: path.resolve(__dirname, 'Client.ts'),
|
||||
target: "node",
|
||||
entry: path.resolve(__dirname, 'Server.ts'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../../lib'),
|
||||
filename: 'Frontend.min.js',
|
||||
path: path.resolve(__dirname, '../lib'),
|
||||
filename: 'Backend.js',
|
||||
libraryTarget: 'commonjs',
|
||||
},
|
||||
resolve: {
|
||||
// Add `.ts` and `.tsx` as a resolvable extension.
|
||||
extensions: [".ts", ".tsx", ".js"]
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.ts?$/, loader: "ts-loader" }
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"]
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
exclude: [
|
||||
/\.\/(.*)\/.ts/,
|
||||
/\.\/(.*).ts/,
|
||||
@@ -29,6 +61,6 @@ module.exports = {
|
||||
}),
|
||||
],
|
||||
},
|
||||
externals: {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = [frontendConf, backendConf]
|
||||
|
||||
Reference in New Issue
Block a user