@grest-ts/ipc 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/src/client/IPCClient.d.ts +15 -0
- package/dist/src/client/IPCClient.d.ts.map +1 -0
- package/dist/src/client/IPCClient.js +75 -0
- package/dist/src/client/IPCClient.js.map +1 -0
- package/dist/src/common/IPCSocket.d.ts +42 -0
- package/dist/src/common/IPCSocket.d.ts.map +1 -0
- package/dist/src/common/IPCSocket.js +206 -0
- package/dist/src/common/IPCSocket.js.map +1 -0
- package/dist/src/common/IPCTypes.d.ts +17 -0
- package/dist/src/common/IPCTypes.d.ts.map +1 -0
- package/dist/src/common/IPCTypes.js +2 -0
- package/dist/src/common/IPCTypes.js.map +1 -0
- package/dist/src/index-node.d.ts +7 -0
- package/dist/src/index-node.d.ts.map +1 -0
- package/dist/src/index-node.js +6 -0
- package/dist/src/index-node.js.map +1 -0
- package/dist/src/server/HttpHandler.d.ts +19 -0
- package/dist/src/server/HttpHandler.d.ts.map +1 -0
- package/dist/src/server/HttpHandler.js +83 -0
- package/dist/src/server/HttpHandler.js.map +1 -0
- package/dist/src/server/IPCServer.d.ts +25 -0
- package/dist/src/server/IPCServer.d.ts.map +1 -0
- package/dist/src/server/IPCServer.js +122 -0
- package/dist/src/server/IPCServer.js.map +1 -0
- package/dist/src/server/SocketHandler.d.ts +28 -0
- package/dist/src/server/SocketHandler.d.ts.map +1 -0
- package/dist/src/server/SocketHandler.js +103 -0
- package/dist/src/server/SocketHandler.js.map +1 -0
- package/dist/src/tsconfig.json +16 -0
- package/dist/tsconfig.publish.tsbuildinfo +1 -0
- package/package.json +60 -0
- package/src/client/IPCClient.ts +99 -0
- package/src/common/IPCSocket.ts +251 -0
- package/src/common/IPCTypes.ts +17 -0
- package/src/index-node.ts +6 -0
- package/src/server/HttpHandler.ts +107 -0
- package/src/server/IPCServer.ts +159 -0
- package/src/server/SocketHandler.ts +146 -0
- package/src/tsconfig.json +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Grest Games OÜ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IPCClientRequest, IPCServerRequest } from "../common/IPCTypes";
|
|
2
|
+
export declare class IPCClient {
|
|
3
|
+
private readonly url;
|
|
4
|
+
private socket?;
|
|
5
|
+
constructor(port: number);
|
|
6
|
+
static defineRequest<Req, Res>(name: string): IPCClientRequest<Req, Res>;
|
|
7
|
+
onFrameworkRequest<Req, Res>(type: IPCClientRequest<Req, Res>, handler: (payload: Req) => Promise<Res>): void;
|
|
8
|
+
sendFrameworkRequest<Req, Res>(type: IPCServerRequest<Req, Res>, payload: Req, timeoutMs?: number): Promise<Res>;
|
|
9
|
+
connect(runtimeId?: string): Promise<void>;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
onClose(handler: () => void): void;
|
|
12
|
+
isConnected(): boolean;
|
|
13
|
+
private getSocket;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=IPCClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCClient.d.ts","sourceRoot":"","sources":["../../../src/client/IPCClient.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEtE,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAC,CAAY;gBAEf,IAAI,EAAE,MAAM;WAIV,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC;IAMxE,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAC9B,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAChC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GACxC,IAAI;IAIM,oBAAoB,CAAC,GAAG,EAAE,GAAG,EACtC,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAChC,OAAO,EAAE,GAAG,EACZ,SAAS,GAAE,MAAc,GAC1B,OAAO,CAAC,GAAG,CAAC;IAMF,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoChD,UAAU,IAAI,IAAI;IAOlB,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,WAAW,IAAI,OAAO;IAM7B,OAAO,CAAC,SAAS;CAMpB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { GGLog } from "@grest-ts/logger";
|
|
3
|
+
import { GGLocator } from "@grest-ts/locator";
|
|
4
|
+
import { INTERNAL_SOCKET_PATH } from "../server/SocketHandler.js";
|
|
5
|
+
import { IPCSocket } from "../common/IPCSocket.js";
|
|
6
|
+
export class IPCClient {
|
|
7
|
+
url;
|
|
8
|
+
socket;
|
|
9
|
+
constructor(port) {
|
|
10
|
+
this.url = "localhost:" + port;
|
|
11
|
+
}
|
|
12
|
+
static defineRequest(name) {
|
|
13
|
+
return name;
|
|
14
|
+
}
|
|
15
|
+
// -----------------------------------------------------
|
|
16
|
+
onFrameworkRequest(type, handler) {
|
|
17
|
+
this.getSocket().onRequest(type, async (data) => handler(data));
|
|
18
|
+
}
|
|
19
|
+
async sendFrameworkRequest(type, payload, timeoutMs = 10000) {
|
|
20
|
+
return this.getSocket().request(type, payload, timeoutMs);
|
|
21
|
+
}
|
|
22
|
+
// -----------------------------------------------------
|
|
23
|
+
async connect(runtimeId) {
|
|
24
|
+
if (this.socket?.isConnected())
|
|
25
|
+
return;
|
|
26
|
+
// Capture scope before async boundary - WebSocket events don't preserve AsyncLocalStorage context
|
|
27
|
+
const scope = GGLocator.getScope();
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const queryParam = runtimeId ? `?runtimeId=${encodeURIComponent(runtimeId)}` : '';
|
|
30
|
+
const url = `ws://${this.url}${INTERNAL_SOCKET_PATH}${queryParam}`;
|
|
31
|
+
const ws = new WebSocket(url);
|
|
32
|
+
const timeout = setTimeout(() => {
|
|
33
|
+
ws.terminate();
|
|
34
|
+
reject(new Error(`Connection timeout to ${this.url}`));
|
|
35
|
+
}, 5000);
|
|
36
|
+
ws.on('open', () => {
|
|
37
|
+
scope.ensureEntered();
|
|
38
|
+
clearTimeout(timeout);
|
|
39
|
+
this.socket = new IPCSocket(ws);
|
|
40
|
+
GGLog.debug(this, `Connected to IPC server at ${this.url}`);
|
|
41
|
+
resolve();
|
|
42
|
+
});
|
|
43
|
+
ws.on('error', (err) => {
|
|
44
|
+
scope.ensureEntered();
|
|
45
|
+
clearTimeout(timeout);
|
|
46
|
+
if (!this.socket) {
|
|
47
|
+
reject(err);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
GGLog.error(this, 'Socket error', err);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
disconnect() {
|
|
56
|
+
if (this.socket) {
|
|
57
|
+
this.socket.teardown();
|
|
58
|
+
this.socket = undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
onClose(handler) {
|
|
62
|
+
this.getSocket().onClose(handler);
|
|
63
|
+
}
|
|
64
|
+
isConnected() {
|
|
65
|
+
return this.socket?.isConnected() ?? false;
|
|
66
|
+
}
|
|
67
|
+
// -----------------------------------------------------
|
|
68
|
+
getSocket() {
|
|
69
|
+
if (!this.socket) {
|
|
70
|
+
throw new Error('Not connected to IPC server');
|
|
71
|
+
}
|
|
72
|
+
return this.socket;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=IPCClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCClient.js","sourceRoot":"","sources":["../../../src/client/IPCClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
export declare enum IPCMessageType {
|
|
3
|
+
MSG = "m",
|
|
4
|
+
REQ = "r",
|
|
5
|
+
RES = "s"
|
|
6
|
+
}
|
|
7
|
+
export interface IPCMessage {
|
|
8
|
+
type: IPCMessageType;
|
|
9
|
+
id: string;
|
|
10
|
+
path: string;
|
|
11
|
+
data?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export type IPCMessageHandler = (data: unknown) => void | Promise<void>;
|
|
14
|
+
export type IPCRequestHandler = (data: unknown) => Promise<unknown>;
|
|
15
|
+
export declare class IPCSocket {
|
|
16
|
+
private readonly ws;
|
|
17
|
+
private readonly messageHandlers;
|
|
18
|
+
private readonly requestHandlers;
|
|
19
|
+
private readonly pendingRequests;
|
|
20
|
+
private requestIdCounter;
|
|
21
|
+
private active;
|
|
22
|
+
private readonly closeCallbacks;
|
|
23
|
+
private readonly errorCallbacks;
|
|
24
|
+
constructor(ws: WebSocket);
|
|
25
|
+
private static DELIMITER;
|
|
26
|
+
private static serialize;
|
|
27
|
+
private static parse;
|
|
28
|
+
private handleRawMessage;
|
|
29
|
+
private handleIncomingMessage;
|
|
30
|
+
private handleIncomingRequest;
|
|
31
|
+
private handleIncomingResponse;
|
|
32
|
+
onMessage(path: string, handler: IPCMessageHandler): void;
|
|
33
|
+
onRequest(path: string, handler: IPCRequestHandler): void;
|
|
34
|
+
onClose(callback: () => void): void;
|
|
35
|
+
onError(callback: (error: Error) => void): void;
|
|
36
|
+
send(path: string, data?: unknown): void;
|
|
37
|
+
request<T = unknown>(path: string, data?: unknown, timeoutMs?: number): Promise<T>;
|
|
38
|
+
isConnected(): boolean;
|
|
39
|
+
close(): void;
|
|
40
|
+
teardown(): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=IPCSocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCSocket.d.ts","sourceRoot":"","sources":["../../../src/common/IPCSocket.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAC;AAI3B,oBAAY,cAAc;IACtB,GAAG,MAAM;IACT,GAAG,MAAM;IACT,GAAG,MAAM;CACZ;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAQpE,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6C;IAC7E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6C;IAC7E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;IAE1E,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,MAAM,CAAQ;IAEtB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqC;gBAExD,EAAE,EAAE,SAAS;IAoCzB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAO;IAE/B,OAAO,CAAC,MAAM,CAAC,SAAS;IAKxB,OAAO,CAAC,MAAM,CAAC,KAAK;YAqBN,gBAAgB;YAoBhB,qBAAqB;YAarB,qBAAqB;IA6BnC,OAAO,CAAC,sBAAsB;IAkBvB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAIzD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAIzD,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAInC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI/C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAQlC,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAwB/F,WAAW,IAAI,OAAO;IAItB,KAAK,IAAI,IAAI;IAOb,QAAQ,IAAI,IAAI;CAQ1B"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { GGLog } from "@grest-ts/logger";
|
|
3
|
+
import { GGLocator } from "@grest-ts/locator";
|
|
4
|
+
export var IPCMessageType;
|
|
5
|
+
(function (IPCMessageType) {
|
|
6
|
+
IPCMessageType["MSG"] = "m";
|
|
7
|
+
IPCMessageType["REQ"] = "r";
|
|
8
|
+
IPCMessageType["RES"] = "s";
|
|
9
|
+
})(IPCMessageType || (IPCMessageType = {}));
|
|
10
|
+
export class IPCSocket {
|
|
11
|
+
ws;
|
|
12
|
+
messageHandlers = new Map();
|
|
13
|
+
requestHandlers = new Map();
|
|
14
|
+
pendingRequests = new Map();
|
|
15
|
+
requestIdCounter = 0;
|
|
16
|
+
active = true;
|
|
17
|
+
closeCallbacks = [];
|
|
18
|
+
errorCallbacks = [];
|
|
19
|
+
constructor(ws) {
|
|
20
|
+
this.ws = ws;
|
|
21
|
+
const scope = GGLocator.getScope();
|
|
22
|
+
ws.on('message', async (data) => {
|
|
23
|
+
scope.ensureEntered();
|
|
24
|
+
await this.handleRawMessage(data.toString('utf8'));
|
|
25
|
+
});
|
|
26
|
+
ws.on('close', () => {
|
|
27
|
+
scope.ensureEntered();
|
|
28
|
+
this.active = false;
|
|
29
|
+
for (const pending of this.pendingRequests.values()) {
|
|
30
|
+
clearTimeout(pending.timeout);
|
|
31
|
+
pending.reject(new Error('Connection closed'));
|
|
32
|
+
}
|
|
33
|
+
this.pendingRequests.clear();
|
|
34
|
+
this.closeCallbacks.forEach(cb => {
|
|
35
|
+
try {
|
|
36
|
+
cb();
|
|
37
|
+
}
|
|
38
|
+
catch (e) { /* ignore */
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
ws.on('error', (error) => {
|
|
43
|
+
scope.ensureEntered();
|
|
44
|
+
this.errorCallbacks.forEach(cb => {
|
|
45
|
+
try {
|
|
46
|
+
cb(error);
|
|
47
|
+
}
|
|
48
|
+
catch (e) { /* ignore */
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
static DELIMITER = ':';
|
|
54
|
+
static serialize(msg) {
|
|
55
|
+
const dataStr = msg.data !== undefined ? JSON.stringify(msg.data) : '';
|
|
56
|
+
return `${msg.type}${this.DELIMITER}${msg.id}${this.DELIMITER}${msg.path}${this.DELIMITER}${dataStr}`;
|
|
57
|
+
}
|
|
58
|
+
static parse(raw) {
|
|
59
|
+
const parts = raw.split(this.DELIMITER);
|
|
60
|
+
if (parts.length < 3)
|
|
61
|
+
return undefined;
|
|
62
|
+
const type = parts[0];
|
|
63
|
+
const id = parts[1];
|
|
64
|
+
const path = parts[2];
|
|
65
|
+
const dataStr = parts.length > 3 ? parts.slice(3).join(this.DELIMITER) : '';
|
|
66
|
+
let data;
|
|
67
|
+
if (dataStr) {
|
|
68
|
+
try {
|
|
69
|
+
data = JSON.parse(dataStr);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Invalid JSON
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { type, id, path, data };
|
|
76
|
+
}
|
|
77
|
+
async handleRawMessage(raw) {
|
|
78
|
+
const msg = IPCSocket.parse(raw);
|
|
79
|
+
if (!msg) {
|
|
80
|
+
GGLog.warn(this, `Invalid IPC message: ${raw.substring(0, 100)}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
switch (msg.type) {
|
|
84
|
+
case IPCMessageType.MSG:
|
|
85
|
+
await this.handleIncomingMessage(msg);
|
|
86
|
+
break;
|
|
87
|
+
case IPCMessageType.REQ:
|
|
88
|
+
await this.handleIncomingRequest(msg);
|
|
89
|
+
break;
|
|
90
|
+
case IPCMessageType.RES:
|
|
91
|
+
this.handleIncomingResponse(msg);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async handleIncomingMessage(msg) {
|
|
96
|
+
const handler = this.messageHandlers.get(msg.path);
|
|
97
|
+
if (!handler) {
|
|
98
|
+
GGLog.debug(this, `No handler for message: ${msg.path}`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
await handler(msg.data);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
GGLog.error(this, `Message handler error for ${msg.path}`, error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async handleIncomingRequest(msg) {
|
|
109
|
+
const handler = this.requestHandlers.get(msg.path);
|
|
110
|
+
const sendResponse = (success, data, error) => {
|
|
111
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
112
|
+
const response = {
|
|
113
|
+
type: IPCMessageType.RES,
|
|
114
|
+
id: msg.id,
|
|
115
|
+
path: msg.path,
|
|
116
|
+
data: { success, data, error }
|
|
117
|
+
};
|
|
118
|
+
this.ws.send(IPCSocket.serialize(response));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
if (!handler) {
|
|
122
|
+
sendResponse(false, undefined, `No handler for: ${msg.path}`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const result = await handler(msg.data);
|
|
127
|
+
sendResponse(true, result);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
GGLog.error(this, `Request handler error for ${msg.path}`, error);
|
|
131
|
+
sendResponse(false, undefined, error.message || String(error));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
handleIncomingResponse(msg) {
|
|
135
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
136
|
+
if (!pending) {
|
|
137
|
+
GGLog.debug(this, `No pending request for response id: ${msg.id}`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
clearTimeout(pending.timeout);
|
|
141
|
+
this.pendingRequests.delete(msg.id);
|
|
142
|
+
const response = msg.data;
|
|
143
|
+
if (response.success) {
|
|
144
|
+
pending.resolve(response.data);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
pending.reject(new Error(response.error || 'Request failed'));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
onMessage(path, handler) {
|
|
151
|
+
this.messageHandlers.set(path, handler);
|
|
152
|
+
}
|
|
153
|
+
onRequest(path, handler) {
|
|
154
|
+
this.requestHandlers.set(path, handler);
|
|
155
|
+
}
|
|
156
|
+
onClose(callback) {
|
|
157
|
+
this.closeCallbacks.push(callback);
|
|
158
|
+
}
|
|
159
|
+
onError(callback) {
|
|
160
|
+
this.errorCallbacks.push(callback);
|
|
161
|
+
}
|
|
162
|
+
send(path, data) {
|
|
163
|
+
if (!this.active || this.ws.readyState !== WebSocket.OPEN) {
|
|
164
|
+
throw new Error('Socket not connected');
|
|
165
|
+
}
|
|
166
|
+
const msg = { type: IPCMessageType.MSG, id: '', path, data };
|
|
167
|
+
this.ws.send(IPCSocket.serialize(msg));
|
|
168
|
+
}
|
|
169
|
+
async request(path, data, timeoutMs = 10000) {
|
|
170
|
+
if (!this.active || this.ws.readyState !== WebSocket.OPEN) {
|
|
171
|
+
throw new Error('Socket not connected');
|
|
172
|
+
}
|
|
173
|
+
const id = `${++this.requestIdCounter}`;
|
|
174
|
+
const msg = { type: IPCMessageType.REQ, id, path, data };
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
const timeout = setTimeout(() => {
|
|
177
|
+
this.pendingRequests.delete(id);
|
|
178
|
+
reject(new Error(`Request '${path}' timed out after ${timeoutMs}ms`));
|
|
179
|
+
}, timeoutMs);
|
|
180
|
+
this.pendingRequests.set(id, {
|
|
181
|
+
resolve: resolve,
|
|
182
|
+
reject,
|
|
183
|
+
timeout
|
|
184
|
+
});
|
|
185
|
+
this.ws.send(IPCSocket.serialize(msg));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
isConnected() {
|
|
189
|
+
return this.active && this.ws.readyState === WebSocket.OPEN;
|
|
190
|
+
}
|
|
191
|
+
close() {
|
|
192
|
+
if (this.active) {
|
|
193
|
+
this.active = false;
|
|
194
|
+
this.ws.terminate();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
teardown() {
|
|
198
|
+
for (const pending of this.pendingRequests.values()) {
|
|
199
|
+
clearTimeout(pending.timeout);
|
|
200
|
+
pending.reject(new Error('Socket teardown'));
|
|
201
|
+
}
|
|
202
|
+
this.pendingRequests.clear();
|
|
203
|
+
this.close();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=IPCSocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCSocket.js","sourceRoot":"","sources":["../../../src/common/IPCSocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type for messages that the IPC server handles (sent by client, handled by server)
|
|
3
|
+
*/
|
|
4
|
+
export type IPCServerRequest<Request, Response> = string & {
|
|
5
|
+
__IPCServerRequest: never;
|
|
6
|
+
__request: Request;
|
|
7
|
+
__response: Response;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Type for messages that the IPC client handles (sent by server, handled by client)
|
|
11
|
+
*/
|
|
12
|
+
export type IPCClientRequest<Request, Response> = string & {
|
|
13
|
+
__IPCClientRequest: never;
|
|
14
|
+
__request: Request;
|
|
15
|
+
__response: Response;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=IPCTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCTypes.d.ts","sourceRoot":"","sources":["../../../src/common/IPCTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,IAAI,MAAM,GAAG;IACvD,kBAAkB,EAAE,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,QAAQ,CAAC;CACxB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,IAAI,MAAM,GAAG;IACvD,kBAAkB,EAAE,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,QAAQ,CAAC;CACxB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCTypes.js","sourceRoot":"","sources":["../../../src/common/IPCTypes.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './server/IPCServer';
|
|
2
|
+
export * from './client/IPCClient';
|
|
3
|
+
export * from './common/IPCSocket';
|
|
4
|
+
export * from './common/IPCTypes';
|
|
5
|
+
export { INTERNAL_SOCKET_PATH } from './server/SocketHandler';
|
|
6
|
+
export type { SocketMessage } from './server/SocketHandler';
|
|
7
|
+
//# sourceMappingURL=index-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAA;AAC3D,YAAY,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-node.js","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as http from 'http';
|
|
2
|
+
import { HttpMethod } from "@grest-ts/common";
|
|
3
|
+
/** HTTP route handler - receives body, path params, and headers. Returns response data (or void for empty 200) */
|
|
4
|
+
export type HttpRouteHandler = (body: any, pathParams?: Record<string, string>, headers?: Record<string, string>) => Promise<any>;
|
|
5
|
+
/** Default HTTP handler for unmatched routes (proxying) - gets raw req/res */
|
|
6
|
+
export type DefaultHttpHandler = (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
|
|
7
|
+
export declare class HttpHandler {
|
|
8
|
+
private router;
|
|
9
|
+
private routeResolver;
|
|
10
|
+
private readonly proxy;
|
|
11
|
+
constructor();
|
|
12
|
+
setRouteResolver(routeResolver: (path: string) => string): void;
|
|
13
|
+
addRoute(method: HttpMethod, path: string, handler: HttpRouteHandler): void;
|
|
14
|
+
removeRoute(method: HttpMethod, path: string): void;
|
|
15
|
+
handleRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void>;
|
|
16
|
+
private readJsonBody;
|
|
17
|
+
private sendResponse;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=HttpHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpHandler.d.ts","sourceRoot":"","sources":["../../../src/server/HttpHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAI5C,kHAAkH;AAClH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAElI,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAMxG,qBAAa,WAAW;IAEpB,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;;IAM3B,gBAAgB,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;IAIxD,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAM3E,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAI7C,aAAa,CACtB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC;YA0CF,YAAY;IAiB1B,OAAO,CAAC,YAAY;CAIvB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { GGLog } from "@grest-ts/logger";
|
|
2
|
+
import httpProxy from "http-proxy";
|
|
3
|
+
import findMyWay from "find-my-way";
|
|
4
|
+
export class HttpHandler {
|
|
5
|
+
router = findMyWay();
|
|
6
|
+
routeResolver;
|
|
7
|
+
proxy;
|
|
8
|
+
constructor() {
|
|
9
|
+
this.proxy = httpProxy.createProxyServer({});
|
|
10
|
+
}
|
|
11
|
+
setRouteResolver(routeResolver) {
|
|
12
|
+
this.routeResolver = routeResolver;
|
|
13
|
+
}
|
|
14
|
+
addRoute(method, path, handler) {
|
|
15
|
+
const store = { handler };
|
|
16
|
+
this.router.on(method, path, () => {
|
|
17
|
+
}, store);
|
|
18
|
+
}
|
|
19
|
+
removeRoute(method, path) {
|
|
20
|
+
this.router.off(method, path);
|
|
21
|
+
}
|
|
22
|
+
async handleRequest(req, res) {
|
|
23
|
+
const method = (req.method || 'GET');
|
|
24
|
+
const url = req.url || '/';
|
|
25
|
+
// Strip query string for route matching
|
|
26
|
+
const path = url.split('?')[0];
|
|
27
|
+
// Try to match a route
|
|
28
|
+
const result = this.router.find(method, path);
|
|
29
|
+
if (result?.store) {
|
|
30
|
+
const store = result.store;
|
|
31
|
+
const body = await this.readJsonBody(req);
|
|
32
|
+
// Normalize headers to Record<string, string>
|
|
33
|
+
const headers = {};
|
|
34
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
35
|
+
if (value !== undefined) {
|
|
36
|
+
headers[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const pathParams = result.params || {};
|
|
40
|
+
try {
|
|
41
|
+
const responseData = await store.handler(body, pathParams, headers);
|
|
42
|
+
this.sendResponse(res, 200, responseData);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
GGLog.error(this, `HTTP route error [${method} ${path}]: ${err.message}`, err);
|
|
46
|
+
this.sendResponse(res, 500, { error: err.message });
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const routeToUrl = this.routeResolver(path);
|
|
51
|
+
if (routeToUrl) {
|
|
52
|
+
GGLog.debug(this, `Proxying ${req.method} ${req.url} -> ${routeToUrl}`);
|
|
53
|
+
this.proxy.web(req, res, { target: routeToUrl }, (err) => {
|
|
54
|
+
GGLog.error(this, "Proxy error", err);
|
|
55
|
+
this.sendResponse(res, 502, { issue: "Proxy error: " + err.message + " (Did the service crash?)" });
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.sendResponse(res, 404, { error: `No route for ${method} ${path}! Did you forget to start a service that defines this path?` });
|
|
60
|
+
}
|
|
61
|
+
async readJsonBody(req) {
|
|
62
|
+
return new Promise((resolve) => {
|
|
63
|
+
let bodyStr = '';
|
|
64
|
+
req.on('data', (chunk) => {
|
|
65
|
+
bodyStr += chunk.toString();
|
|
66
|
+
});
|
|
67
|
+
req.on('end', () => {
|
|
68
|
+
try {
|
|
69
|
+
resolve(bodyStr ? JSON.parse(bodyStr) : undefined);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
resolve(undefined);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
req.on('error', () => resolve(undefined));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
sendResponse(res, status, data) {
|
|
79
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
80
|
+
res.end(data !== undefined ? JSON.stringify(data) : '');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=HttpHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpHandler.js","sourceRoot":"","sources":["../../../src/server/HttpHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HttpMethod } from "@grest-ts/common";
|
|
2
|
+
import { SocketMessage } from "./SocketHandler";
|
|
3
|
+
import { IPCClientRequest, IPCServerRequest } from "../common/IPCTypes";
|
|
4
|
+
export declare class IPCServer {
|
|
5
|
+
private readonly httpServer;
|
|
6
|
+
private readonly httpHandler;
|
|
7
|
+
private readonly socketHandler;
|
|
8
|
+
private readonly expectedPort;
|
|
9
|
+
private port;
|
|
10
|
+
private url;
|
|
11
|
+
private readonly connections;
|
|
12
|
+
private readonly scope;
|
|
13
|
+
constructor(port?: number);
|
|
14
|
+
static defineRequest<Req, Res>(name: string): IPCServerRequest<Req, Res>;
|
|
15
|
+
start(): Promise<boolean>;
|
|
16
|
+
teardown(): Promise<void>;
|
|
17
|
+
interceptHttp(method: HttpMethod, path: string, handler: (body: any, pathParams?: Record<string, string>, headers?: Record<string, string>) => Promise<any>): void;
|
|
18
|
+
removeInterceptHttp(method: HttpMethod, path: string): void;
|
|
19
|
+
setRouteProxyResolver(resolver: (path: string) => string): void;
|
|
20
|
+
onFrameworkMessage<Req, Res>(type: IPCServerRequest<Req, Res>, handler: (payload: Req, msg: SocketMessage) => Promise<Res>): void;
|
|
21
|
+
sendFrameworkMessage<Req, Res>(runtimeId: string, type: IPCClientRequest<Req, Res>, payload: Req, timeoutMs?: number): Promise<Res>;
|
|
22
|
+
getPort(): number;
|
|
23
|
+
getUrl(): string;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=IPCServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPCServer.d.ts","sourceRoot":"","sources":["../../../src/server/IPCServer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAgB,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAKtE,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAE9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,GAAG,CAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAE3B,IAAI,GAAE,MAAU;WAiCd,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC;IAQlE,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAuBzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB/B,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI;IAIlK,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3D,qBAAqB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;IASxD,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAC9B,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAChC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,GAAG,CAAC,GAC5D,IAAI;IAIM,oBAAoB,CAAC,GAAG,EAAE,GAAG,EACtC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAChC,OAAO,EAAE,GAAG,EACZ,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,GAAG,CAAC;IAQR,OAAO,IAAI,MAAM;IAIjB,MAAM,IAAI,MAAM;CAG1B"}
|