-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import typescript from "@rollup/plugin-typescript"; | ||
import { dts } from "rollup-plugin-dts"; | ||
import alias from '@rollup/plugin-alias'; | ||
import * as path from "path"; | ||
import resolve from '@rollup/plugin-node-resolve'; | ||
import commonjs from '@rollup/plugin-commonjs'; | ||
|
||
const config = [ | ||
{ | ||
input: 'src/index.ts', | ||
output: [ | ||
{ | ||
file: './dist/index.js', | ||
format: 'cjs', | ||
sourcemap: true, | ||
} | ||
], | ||
plugins: [ | ||
typescript({ | ||
tsconfig: './tsconfig.json' | ||
}), | ||
resolve(), | ||
commonjs(), | ||
alias({ | ||
entries: [ | ||
{ find: '@', replacement: path.join(path.resolve(), "src") } | ||
] | ||
}), | ||
] | ||
}, | ||
{ | ||
input: "src/index.ts", | ||
output: [{ file: "./dist/index.d.ts", format: "es" }], | ||
plugins: [ | ||
dts(), | ||
alias({ | ||
entries: [ | ||
{ find: '@', replacement: path.join(path.resolve(), "src") } | ||
] | ||
}), | ||
resolve(), | ||
commonjs() | ||
] | ||
} | ||
] | ||
export default config; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Writable, WritableOptions } from "stream"; | ||
|
||
export class JSONFrameStream extends Writable { | ||
public handler: (obj: object) => void; | ||
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 4 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, latest)
|
||
public frame: Frame | null; | ||
|
||
public constructor( | ||
handler: (obj: object) => void, | ||
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 8 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, latest)
|
||
options?: WritableOptions, | ||
) { | ||
super(options); | ||
this.handler = handler; | ||
this.frame = null; | ||
} | ||
|
||
public _write( | ||
chunk: Buffer, | ||
encoding: BufferEncoding, | ||
callback: (error?: Error | null) => void, | ||
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 19 in common/src/Rpc/JSONFrameStream.ts GitHub Actions / build (windows-latest, latest)
|
||
): void { | ||
this._parse(chunk); | ||
callback(); | ||
} | ||
|
||
public _parse(buffer: Buffer): unknown | undefined { | ||
if (!buffer.length) { | ||
return; | ||
} | ||
if (!this.frame) { | ||
this.frame = { | ||
data: Buffer.alloc(4), | ||
pointer: 0, | ||
}; | ||
} | ||
if (!this.frame.size) { | ||
const length = Math.min(buffer.length, 4 - this.frame.pointer); | ||
buffer.copy(this.frame.data, this.frame.pointer, 0, length); | ||
this.frame.pointer += length; | ||
if (this.frame.pointer === 4) { | ||
this.frame.size = this.frame.data.readUInt32BE(); | ||
this.frame.data = Buffer.alloc(this.frame.size); | ||
this.frame.pointer = 0; | ||
} | ||
return this._parse(buffer.slice(length)); | ||
} else { | ||
const length = Math.min( | ||
buffer.length, | ||
this.frame.size - this.frame.pointer, | ||
); | ||
buffer.copy(this.frame.data, this.frame.pointer, 0, length); | ||
this.frame.pointer += length; | ||
if (this.frame.pointer == this.frame.size) { | ||
this.handler(JSON.parse(this.frame.data.toString("utf8"))); | ||
this.frame = null; | ||
} | ||
return this._parse(buffer.slice(length)); | ||
} | ||
} | ||
|
||
public static makeFrame(obj: object): Buffer { | ||
const data = Buffer.from(JSON.stringify(obj), "utf8"); | ||
const length = Buffer.alloc(4); | ||
length.writeUInt32BE(data.length); | ||
return Buffer.concat([length, data]); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Socket } from "net"; | ||
import { EventEmitter } from "events"; | ||
import { JSONFrameStream } from "@/Rpc/JSONFrameStream"; | ||
|
||
export class RpcClient { | ||
public socket: Socket; | ||
public requestId: number; | ||
public defers: Map< | ||
string, | ||
{ | ||
defer: Promise<unknown>; | ||
reject: (reason?: Error | undefined) => void; | ||
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 12 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
resolve: (value?: object) => void; | ||
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 13 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
} | ||
>; | ||
public pubSub: EventEmitter; | ||
|
||
public constructor(socket: Socket) { | ||
this.socket = socket; | ||
this.socket.pipe( | ||
new JSONFrameStream( | ||
(this._processFrame as (obj: object) => void).bind(this), | ||
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 22 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
), | ||
); | ||
this.requestId = 0; | ||
this.defers = new Map(); | ||
this.pubSub = new EventEmitter(); | ||
} | ||
|
||
public _processFrame(obj: RpcClientFrameObj): void { | ||
if (obj.pubSub) { | ||
this.pubSub.emit(obj.pubSub.channel, obj.pubSub.channel, obj.pubSub.data); | ||
this.pubSub.emit("*", obj.pubSub.channel, obj.pubSub.data); | ||
return; | ||
} | ||
if (!this.defers.has(String(obj.id))) { | ||
console.error("invalid request id", obj.id); | ||
return; | ||
} | ||
if (obj.error) { | ||
this.defers.get(String(obj.id))!.reject(obj.error); | ||
} else { | ||
this.defers.get(String(obj.id))!.resolve(obj.result); | ||
} | ||
this.defers.delete(String(obj.id)); | ||
} | ||
|
||
public request( | ||
method: string, | ||
...args: unknown[] | ||
): { | ||
defer: Promise<unknown>; | ||
reject: (reason?: Error) => void; | ||
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 53 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
resolve: (value?: object) => void; | ||
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 54 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
} { | ||
this.requestId++; | ||
const request = { | ||
id: this.requestId, | ||
method, | ||
args, | ||
}; | ||
let resolve = ((): void => {}) as (value?: object) => void, | ||
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 62 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
reject = ((): void => {}) as (reason?: Error) => void; | ||
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 18.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 16.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, 20.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (ubuntu-latest, latest)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 16.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 16.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 20.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, 20.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, 18.x)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (macos-latest, latest)
Check warning on line 63 in common/src/Rpc/RpcClient.ts GitHub Actions / build (windows-latest, latest)
|
||
this.socket.write(JSONFrameStream.makeFrame(request)); | ||
const defer = new Promise((res, rej) => { | ||
[resolve, reject] = [res, rej]; | ||
}); | ||
this.defers.set(String(this.requestId), { defer, reject, resolve }); | ||
return { defer, reject, resolve }; | ||
} | ||
|
||
public subscribe( | ||
channelToSubscribe: string, | ||
callback: (...args: unknown[]) => void, | ||
): void { | ||
const request = { | ||
method: "subscribe", | ||
channel: channelToSubscribe, | ||
}; | ||
this.socket.write(JSONFrameStream.makeFrame(request)); | ||
this.pubSub.addListener( | ||
channelToSubscribe, | ||
(channel: string, ...args: unknown[]) => { | ||
callback.apply({ channel }, args); | ||
}, | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Socket } from "net"; | ||
import { JSONFrameStream } from "@/Rpc/JSONFrameStream"; | ||
|
||
export class RpcServer { | ||
public socket: Socket; | ||
public methods: RpcMethods; | ||
public channelUnsubscribe: Map<string, () => void>; | ||
public constructor(socket: Socket, methods: RpcMethods) { | ||
this.socket = socket; | ||
this.socket.pipe( | ||
new JSONFrameStream( | ||
(this._processFrame as (obj: object) => void).bind(this), | ||
), | ||
); | ||
this.methods = methods; | ||
this.channelUnsubscribe = new Map(); | ||
this.socket.on("close", () => { | ||
this.channelUnsubscribe.forEach((unsubscribe) => unsubscribe()); | ||
this.channelUnsubscribe.clear(); | ||
}); | ||
} | ||
|
||
public _processFrame(obj: RpcServerFrameObj): void { | ||
const args = obj.args || []; | ||
if (obj.method === "subscribe") { | ||
if (this.channelUnsubscribe.has("*")) { | ||
return; | ||
} | ||
if (obj.channel === "*") { | ||
this.channelUnsubscribe.forEach((unsubscribe) => unsubscribe()); | ||
this.channelUnsubscribe.clear(); | ||
} | ||
if (!this.channelUnsubscribe.has(obj.channel)) { | ||
const unsubscribe = this.methods.subscribe(obj.channel, (pubSub) => { | ||
this.socket.write(JSONFrameStream.makeFrame({ pubSub })); | ||
}); | ||
this.channelUnsubscribe.set(obj.channel, unsubscribe); | ||
} | ||
this.socket.write(""); | ||
return; | ||
} | ||
this.methods[obj.method].apply( | ||
null, | ||
args.concat([ | ||
(error: Error, result: object): void => { | ||
const response: RpcResponse = { id: obj.id }; | ||
if (error) { | ||
response.error = error; | ||
} else { | ||
response.result = result; | ||
} | ||
this.socket.write(JSONFrameStream.makeFrame(response)); | ||
}, | ||
]), | ||
); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
type Frame = { data: Buffer; pointer: number; size?: number }; | ||
|
||
type RpcServerFrameObj = { | ||
method: string; | ||
channel: string; | ||
id: string; | ||
args: unknown[]; | ||
}; | ||
|
||
type RpcClientFrameObj = { | ||
id: string; | ||
error?: Error; | ||
result?: object; | ||
pubSub: ChildProcess; | ||
}; | ||
|
||
type RpcMethods = { | ||
subscribe( | ||
channel: string, | ||
listener: (data: { channel: string; data: unknown }) => void, | ||
): () => void; | ||
publish: (channel: string, data: unknown, cb?: CallBack) => void; | ||
[name: string]: (cb?: CallBack, ...args) => void; | ||
}; | ||
|
||
type RpcResponse = { | ||
id: string; | ||
error?: Error; | ||
result?: object; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { JSONFrameStream } from "@/Rpc/JSONFrameStream"; | ||
|
||
test("JSONFrameStream", () => { | ||
const buffer = JSONFrameStream.makeFrame({ Loki: "god" }); | ||
console.log(buffer); | ||
expect(buffer.length).toBe(18); | ||
}); |