oox 0.3.3 → 0.3.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/README.md +13 -0
- package/app.js +1 -1
- package/bin/cli.js +75 -15
- package/bin/configurer.js +6 -9
- package/bin/register.js +48 -15
- package/bin/starter.js +8 -0
- package/config.js +116 -0
- package/index.js +70 -44
- package/{rpc-keepalive-connection.js → keepalive-connection.js} +36 -16
- package/modules/http/index.js +52 -63
- package/modules/http/router.js +9 -4
- package/modules/index.js +78 -74
- package/modules/module.js +0 -9
- package/modules/socketio/adapter.js +30 -139
- package/modules/socketio/server.js +37 -38
- package/modules/socketio/utils.js +5 -2
- package/package.json +10 -4
- package/registry.js +145 -0
- package/samples/index.js +1 -0
- package/samples/keepalive-connection-sample.js +147 -0
- package/types/app.d.ts +20 -20
- package/types/bin/configurer.d.ts +3 -1
- package/types/bin/register.d.ts +2 -1
- package/types/bin/starter.d.ts +1 -2
- package/types/config.d.ts +54 -0
- package/types/index.d.ts +37 -31
- package/types/keepalive-connection.d.ts +104 -0
- package/types/modules/http/index.d.ts +4 -7
- package/types/modules/index.d.ts +36 -21
- package/types/modules/module.d.ts +9 -9
- package/types/modules/socketio/adapter.d.ts +10 -24
- package/types/modules/socketio/server.d.ts +6 -10
- package/types/modules/socketio/utils.d.ts +5 -2
- package/types/registry.d.ts +41 -0
- package/types/samples/index.d.ts +1 -0
- package/types/samples/keepalive-connection-sample.d.ts +55 -0
- package/utils.js +1 -1
- package/types/rpc-keepalive-connection.d.ts +0 -57
|
@@ -2,10 +2,11 @@ import * as http from 'node:http';
|
|
|
2
2
|
import * as https from 'node:https';
|
|
3
3
|
import { Server } from 'socket.io';
|
|
4
4
|
import * as oox from '../../index.js';
|
|
5
|
-
import { Module
|
|
5
|
+
import { Module } from '../../index.js';
|
|
6
6
|
import SocketIOAdapter from './adapter.js';
|
|
7
|
-
import {
|
|
8
|
-
export class SocketIOConfig
|
|
7
|
+
import { OOXEvent } from './utils.js';
|
|
8
|
+
export class SocketIOConfig {
|
|
9
|
+
enabled = true;
|
|
9
10
|
// listen port
|
|
10
11
|
port = 0;
|
|
11
12
|
// service path
|
|
@@ -34,6 +35,10 @@ export default class SocketIOServer extends Module {
|
|
|
34
35
|
server = null;
|
|
35
36
|
socketServer = null;
|
|
36
37
|
adapter = new SocketIOAdapter();
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
oox.keepAliveConnectionAdapters.set(this.name, this.adapter);
|
|
41
|
+
}
|
|
37
42
|
getURL() {
|
|
38
43
|
const { host } = oox.config;
|
|
39
44
|
const { port, path } = this.config;
|
|
@@ -53,21 +58,22 @@ export default class SocketIOServer extends Module {
|
|
|
53
58
|
return this.config;
|
|
54
59
|
}
|
|
55
60
|
async serve() {
|
|
56
|
-
oox.rpcKeepAliveConnectionAdapters.set(this.name, this.adapter);
|
|
57
61
|
await this.stop();
|
|
58
62
|
const { port, ssl } = this.config;
|
|
59
63
|
const isSelfServer = this.#isSelfServer = this.server ? true : false;
|
|
60
|
-
let server;
|
|
64
|
+
let server = null;
|
|
61
65
|
if (isSelfServer) {
|
|
66
|
+
if (!this.server)
|
|
67
|
+
throw new Error('HTTP Server is not created');
|
|
62
68
|
server = this.server;
|
|
63
69
|
}
|
|
64
70
|
else {
|
|
65
71
|
if (ssl.enabled) {
|
|
66
72
|
const fs = await import('node:fs');
|
|
67
73
|
const options = {
|
|
68
|
-
key: ssl.key ? fs.readFileSync(ssl.key) :
|
|
69
|
-
cert: ssl.cert ? fs.readFileSync(ssl.cert) :
|
|
70
|
-
ca: ssl.ca ? fs.readFileSync(ssl.ca) :
|
|
74
|
+
key: ssl.key ? fs.readFileSync(ssl.key) : undefined,
|
|
75
|
+
cert: ssl.cert ? fs.readFileSync(ssl.cert) : undefined,
|
|
76
|
+
ca: ssl.ca ? fs.readFileSync(ssl.ca) : undefined
|
|
71
77
|
};
|
|
72
78
|
if (!options.key || !options.cert) {
|
|
73
79
|
throw new Error('HTTPS enabled but missing key or cert');
|
|
@@ -88,10 +94,11 @@ export default class SocketIOServer extends Module {
|
|
|
88
94
|
this.createSocketIOServer();
|
|
89
95
|
}
|
|
90
96
|
async stop() {
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const { server, socketServer } = this;
|
|
98
|
+
if (socketServer)
|
|
99
|
+
await new Promise((resolve, reject) => socketServer.close(error => error ? reject(error) : resolve()));
|
|
93
100
|
if (this.#isSelfServer)
|
|
94
|
-
await new Promise((resolve, reject) =>
|
|
101
|
+
await new Promise((resolve, reject) => server?.close(error => error ? reject(error) : resolve()));
|
|
95
102
|
}
|
|
96
103
|
genSocketIOServerOptions() {
|
|
97
104
|
const options = {
|
|
@@ -127,7 +134,10 @@ export default class SocketIOServer extends Module {
|
|
|
127
134
|
return options;
|
|
128
135
|
}
|
|
129
136
|
createSocketIOServer() {
|
|
130
|
-
const
|
|
137
|
+
const { server } = this;
|
|
138
|
+
if (!server)
|
|
139
|
+
throw new Error('HTTP Server is not created');
|
|
140
|
+
const socketServer = this.socketServer = new Server(server, this.genSocketIOServerOptions());
|
|
131
141
|
socketServer.on('connection', async (socket) => {
|
|
132
142
|
try {
|
|
133
143
|
this.serverOnSocketConnection(socket);
|
|
@@ -145,40 +155,30 @@ export default class SocketIOServer extends Module {
|
|
|
145
155
|
const headers = socket.handshake.headers;
|
|
146
156
|
const callerId = String(headers['x-caller-id'] || '') || socket.id;
|
|
147
157
|
// client ip or caller service ip
|
|
148
|
-
const ip = String(headers['x-real-ip'] ||
|
|
158
|
+
const ip = String(headers['x-real-ip'] || socket.handshake.address);
|
|
149
159
|
// service name
|
|
150
160
|
const caller = String(headers['x-caller'] || 'anonymous');
|
|
151
|
-
const
|
|
152
|
-
|
|
161
|
+
const token = String(headers['x-token'] || '');
|
|
162
|
+
// check token
|
|
163
|
+
const { allow, reason } = oox.checkAllow(ip, caller, token);
|
|
164
|
+
if (!allow) {
|
|
165
|
+
socket.send(reason).disconnect(true);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const connection = new oox.KeepAliveConnection(this.adapter, socket, {
|
|
169
|
+
ip,
|
|
153
170
|
name: caller,
|
|
154
171
|
id: callerId,
|
|
172
|
+
token,
|
|
155
173
|
});
|
|
156
174
|
oox.addKeepAliveConnection(connection);
|
|
157
175
|
this.bindServerConnectionEvents(connection);
|
|
158
176
|
this.adapter.bindCall(connection);
|
|
159
|
-
|
|
160
|
-
socket.emit(OOXEvent.CONNECTED, {
|
|
177
|
+
socket.emit(OOXEvent.READY, {
|
|
161
178
|
id: oox.config.id,
|
|
162
179
|
name: oox.config.name
|
|
163
180
|
});
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* 服务器发送连接列表
|
|
167
|
-
* @param connection
|
|
168
|
-
*/
|
|
169
|
-
[OOXEvent.SYNC_CONNECTIONS](connection) {
|
|
170
|
-
const socket = connection.nativeConnection;
|
|
171
|
-
const datas = [];
|
|
172
|
-
for (const [name, connections] of oox.enabledKeepAliveConnections.entries()) {
|
|
173
|
-
if (name === connection.data.name)
|
|
174
|
-
continue;
|
|
175
|
-
for (const conn of Array.from(connections.values())) {
|
|
176
|
-
if (!conn.data.url || !isWebSocketURL(conn.data.url))
|
|
177
|
-
continue;
|
|
178
|
-
datas.push(conn.data);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return datas;
|
|
181
|
+
connection.enabled = true;
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
184
184
|
* 绑定服务器连接事件
|
|
@@ -186,11 +186,10 @@ export default class SocketIOServer extends Module {
|
|
|
186
186
|
*/
|
|
187
187
|
bindServerConnectionEvents(connection) {
|
|
188
188
|
const socket = connection.nativeConnection;
|
|
189
|
-
socket.on(OOXEvent.
|
|
189
|
+
socket.on(OOXEvent.REGISTRY_SYNC_CONNECTIONS, async (fn) => {
|
|
190
190
|
if ('function' !== typeof fn)
|
|
191
191
|
return;
|
|
192
|
-
|
|
193
|
-
fn(datas);
|
|
192
|
+
oox.registry.onSyncConnections(connection, {}, fn);
|
|
194
193
|
});
|
|
195
194
|
socket.on('disconnecting', (reason) => {
|
|
196
195
|
oox.removeKeepAliveConnection(connection);
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export var OOXEvent;
|
|
2
2
|
(function (OOXEvent) {
|
|
3
|
-
OOXEvent["
|
|
3
|
+
OOXEvent["READY"] = "oox:ready";
|
|
4
|
+
OOXEvent["ENABLED"] = "oox:enabled";
|
|
4
5
|
OOXEvent["DISABLED"] = "oox:disabled";
|
|
5
|
-
OOXEvent["
|
|
6
|
+
OOXEvent["REGISTRY_SYNC_CONNECTIONS"] = "oox:registry:sync_connections";
|
|
7
|
+
OOXEvent["REGISTRY_SUBSCRIBE"] = "oox:registry:subscribe";
|
|
8
|
+
OOXEvent["REGISTRY_NOTIFY"] = "oox:registry:notify";
|
|
6
9
|
})(OOXEvent || (OOXEvent = {}));
|
|
7
10
|
export function isWebSocketURL(url) {
|
|
8
11
|
if ('string' === typeof url) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oox",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "OOX Service Engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"http",
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
"framework",
|
|
11
11
|
"microservice",
|
|
12
12
|
"distributed",
|
|
13
|
-
"tracing"
|
|
13
|
+
"tracing",
|
|
14
|
+
"service-discovery",
|
|
15
|
+
"load-balancing"
|
|
14
16
|
],
|
|
15
17
|
"type": "module",
|
|
16
18
|
"main": "./index.js",
|
|
@@ -22,13 +24,17 @@
|
|
|
22
24
|
"types": "./types/index.d.ts"
|
|
23
25
|
},
|
|
24
26
|
"./loader": "./bin/loader.mjs",
|
|
25
|
-
"./cli": "./bin/cli.js"
|
|
27
|
+
"./cli": "./bin/cli.js",
|
|
28
|
+
"./samples": {
|
|
29
|
+
"types": "./types/samples/index.d.ts",
|
|
30
|
+
"default": "./samples/index.js"
|
|
31
|
+
}
|
|
26
32
|
},
|
|
27
33
|
"bin": {
|
|
28
34
|
"oox": "./bin/cli.js"
|
|
29
35
|
},
|
|
30
36
|
"author": "lipingruan",
|
|
31
|
-
"homepage": "https://
|
|
37
|
+
"homepage": "https://gitee.com/lipingruan/oox",
|
|
32
38
|
"license": "MIT",
|
|
33
39
|
"dependencies": {
|
|
34
40
|
"chalk": "^5.6.2",
|
package/registry.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { config } from './index.js';
|
|
2
|
+
import { enabledKeepAliveConnections, keepAliveConnectionAdapters, keepAliveConnections } from './keepalive-connection.js';
|
|
3
|
+
const unsubscribeListeners = new Map();
|
|
4
|
+
const subscribes = new Map();
|
|
5
|
+
let broadcastTimer = null;
|
|
6
|
+
/**
|
|
7
|
+
* 取消订阅连接列表
|
|
8
|
+
* @param connection
|
|
9
|
+
*/
|
|
10
|
+
export function unsubscribe(connection) {
|
|
11
|
+
subscribes.delete(connection);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 订阅连接列表
|
|
15
|
+
* @param connection
|
|
16
|
+
* @param query
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
export function subscribe(connection, query) {
|
|
20
|
+
if (!config.isRegistry)
|
|
21
|
+
return;
|
|
22
|
+
if (!unsubscribeListeners.has(connection)) {
|
|
23
|
+
const listener = () => {
|
|
24
|
+
unsubscribe(connection);
|
|
25
|
+
};
|
|
26
|
+
unsubscribeListeners.set(connection, listener);
|
|
27
|
+
connection.once('disconnect', listener);
|
|
28
|
+
}
|
|
29
|
+
subscribes.set(connection, query);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 停止广播连接列表
|
|
33
|
+
*/
|
|
34
|
+
export function stopBroadcastTimer() {
|
|
35
|
+
if (!broadcastTimer)
|
|
36
|
+
return;
|
|
37
|
+
clearInterval(broadcastTimer);
|
|
38
|
+
broadcastTimer = null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 开始广播连接列表
|
|
42
|
+
*/
|
|
43
|
+
export function startBroadcastTimer() {
|
|
44
|
+
if (!config.isRegistry)
|
|
45
|
+
return;
|
|
46
|
+
if (broadcastTimer)
|
|
47
|
+
clearInterval(broadcastTimer);
|
|
48
|
+
broadcastTimer = setInterval(broadcast, 1000);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 广播连接列表
|
|
52
|
+
*/
|
|
53
|
+
export function broadcast() {
|
|
54
|
+
if (!config.isRegistry)
|
|
55
|
+
return;
|
|
56
|
+
for (const [connection, query] of subscribes.entries()) {
|
|
57
|
+
try {
|
|
58
|
+
onSyncConnections(connection, query, returns => {
|
|
59
|
+
if (!returns.success)
|
|
60
|
+
return;
|
|
61
|
+
connection.adapter['registry:notify'](connection, returns.body || []);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error(error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 服务器发送连接列表
|
|
71
|
+
* @param connection
|
|
72
|
+
* @param query
|
|
73
|
+
* @param callback
|
|
74
|
+
*/
|
|
75
|
+
export function onSyncConnections(connection, query, callback) {
|
|
76
|
+
// 检查是否开启服务注册功能
|
|
77
|
+
if (!config.isRegistry) {
|
|
78
|
+
const returns = {
|
|
79
|
+
success: false,
|
|
80
|
+
error: {
|
|
81
|
+
message: 'Service registration is not enabled',
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
callback(returns);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const datas = [];
|
|
88
|
+
if (query.name) {
|
|
89
|
+
const names = Array.isArray(query.name) ? query.name : [query.name];
|
|
90
|
+
for (const [name, connections] of enabledKeepAliveConnections.entries()) {
|
|
91
|
+
if (names.includes(name))
|
|
92
|
+
continue;
|
|
93
|
+
for (const conn of Array.from(connections.values())) {
|
|
94
|
+
if (!conn.data.url)
|
|
95
|
+
continue;
|
|
96
|
+
datas.push(conn.data);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
for (const [name, connections] of enabledKeepAliveConnections.entries()) {
|
|
102
|
+
if (name === connection.data.name)
|
|
103
|
+
continue;
|
|
104
|
+
for (const conn of Array.from(connections.values())) {
|
|
105
|
+
if (!conn.data.url)
|
|
106
|
+
continue;
|
|
107
|
+
datas.push(conn.data);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const returns = {
|
|
112
|
+
success: true,
|
|
113
|
+
body: datas,
|
|
114
|
+
};
|
|
115
|
+
callback(returns);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 同步连接列表
|
|
119
|
+
* @param datas 连接参数列表
|
|
120
|
+
*/
|
|
121
|
+
export function syncConnections(returns) {
|
|
122
|
+
if (!returns.success) {
|
|
123
|
+
if (returns.error) {
|
|
124
|
+
console.error(new Error(returns.error.message || 'Sync connections failed'));
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
for (const data of returns.body || []) {
|
|
129
|
+
// 获取适配器
|
|
130
|
+
const adapter = keepAliveConnectionAdapters.get(data.adapter);
|
|
131
|
+
if (!adapter)
|
|
132
|
+
continue;
|
|
133
|
+
// 忽略自己
|
|
134
|
+
if (data.name === config.name)
|
|
135
|
+
continue;
|
|
136
|
+
// 忽略无效URL
|
|
137
|
+
if (!data.url)
|
|
138
|
+
continue;
|
|
139
|
+
// 忽略已存在连接
|
|
140
|
+
if (keepAliveConnections.has(data.name, data.id))
|
|
141
|
+
continue;
|
|
142
|
+
// 建立连接
|
|
143
|
+
adapter.open(data).catch((error) => console.error(error));
|
|
144
|
+
}
|
|
145
|
+
}
|
package/samples/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SampleKeepAliveConnectionAdapter } from './keepalive-connection-sample.js';
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as oox from '../index.js';
|
|
2
|
+
export class SampleKeepAliveConnectionAdapter {
|
|
3
|
+
OOXEvent = {
|
|
4
|
+
READY: 'oox:ready',
|
|
5
|
+
ENABLED: 'oox:enabled',
|
|
6
|
+
DISABLED: 'oox:disabled',
|
|
7
|
+
REGISTRY_SYNC_CONNECTIONS: 'oox:registry:sync_connections',
|
|
8
|
+
REGISTRY_SUBSCRIBE: 'oox:registry:subscribe',
|
|
9
|
+
REGISTRY_NOTIFY: 'oox:registry:notify',
|
|
10
|
+
};
|
|
11
|
+
nativeEvent = {
|
|
12
|
+
CONNECT: 'connect',
|
|
13
|
+
DISCONNECT: 'disconnect',
|
|
14
|
+
ERROR: 'error',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 通知连接列表
|
|
18
|
+
*/
|
|
19
|
+
['registry:notify'](connection, datas) {
|
|
20
|
+
connection.nativeConnection.emit(this.OOXEvent.REGISTRY_NOTIFY, datas);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 订阅连接列表
|
|
24
|
+
*/
|
|
25
|
+
['registry:subscribe'](connection, query) {
|
|
26
|
+
connection.nativeConnection.emit(this.OOXEvent.REGISTRY_SUBSCRIBE, query);
|
|
27
|
+
}
|
|
28
|
+
bindConnectionEvents(connection) {
|
|
29
|
+
const socket = connection.nativeConnection;
|
|
30
|
+
socket.on(this.OOXEvent.READY, (params) => {
|
|
31
|
+
connection.ready(params);
|
|
32
|
+
socket.emit(this.OOXEvent.REGISTRY_SYNC_CONNECTIONS, oox.registry.syncConnections);
|
|
33
|
+
});
|
|
34
|
+
socket.on(this.OOXEvent.REGISTRY_NOTIFY, (datas) => {
|
|
35
|
+
oox.registry.syncConnections({
|
|
36
|
+
success: true,
|
|
37
|
+
body: datas,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
socket.on(this.OOXEvent.ENABLED, () => {
|
|
41
|
+
connection.enabled = true;
|
|
42
|
+
});
|
|
43
|
+
socket.on(this.OOXEvent.DISABLED, () => {
|
|
44
|
+
connection.enabled = false;
|
|
45
|
+
});
|
|
46
|
+
socket.on(this.nativeEvent.DISCONNECT, (reason) => {
|
|
47
|
+
oox.removeKeepAliveConnection(connection);
|
|
48
|
+
socket.removeAllListeners();
|
|
49
|
+
connection.emit('disconnect');
|
|
50
|
+
});
|
|
51
|
+
socket.on(this.nativeEvent.CONNECT, () => {
|
|
52
|
+
connection.emit('connect');
|
|
53
|
+
});
|
|
54
|
+
socket.on(this.nativeEvent.ERROR, (error) => {
|
|
55
|
+
oox.removeKeepAliveConnection(connection);
|
|
56
|
+
socket.removeAllListeners();
|
|
57
|
+
connection.emit('error', new oox.KeepAliveConnectionError(error.message, connection));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async open(identify) {
|
|
61
|
+
const connection = this.newConnection(identify);
|
|
62
|
+
oox.addKeepAliveConnection(connection);
|
|
63
|
+
this.bindConnectionEvents(connection);
|
|
64
|
+
this.bindCall(connection);
|
|
65
|
+
await new Promise((resolve, reject) => {
|
|
66
|
+
connection.once('enabled', resolve);
|
|
67
|
+
connection.once('error', reject);
|
|
68
|
+
connection.once('disconnect', () => {
|
|
69
|
+
reject(new Error('disconnect'));
|
|
70
|
+
});
|
|
71
|
+
if (connection.nativeConnection.connect) {
|
|
72
|
+
connection.nativeConnection.connect();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return connection;
|
|
76
|
+
}
|
|
77
|
+
async close(connection) {
|
|
78
|
+
connection.nativeConnection.disconnect();
|
|
79
|
+
return Promise.resolve();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 发送事件
|
|
83
|
+
* @param socket
|
|
84
|
+
* @param event
|
|
85
|
+
* @param params
|
|
86
|
+
*/
|
|
87
|
+
async emit(socket, event, params) {
|
|
88
|
+
if (!socket.connected)
|
|
89
|
+
throw new Error('Socket not connected');
|
|
90
|
+
return await new Promise((resolve, reject) => {
|
|
91
|
+
const onError = (reason) => {
|
|
92
|
+
const message = 'string' === typeof reason ? reason : reason instanceof Error ? reason.message : 'connect error';
|
|
93
|
+
reject(new Error(message));
|
|
94
|
+
};
|
|
95
|
+
// RPC 执行时中断连接
|
|
96
|
+
socket.once(this.nativeEvent.DISCONNECT, onError);
|
|
97
|
+
socket.emit(event, ...params, (returns) => {
|
|
98
|
+
socket.off(this.nativeEvent.DISCONNECT, onError);
|
|
99
|
+
resolve(returns);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* RPC
|
|
105
|
+
*/
|
|
106
|
+
async rpc(connection, action, params, context) {
|
|
107
|
+
if (!context)
|
|
108
|
+
context = oox.getContext();
|
|
109
|
+
const miniContext = {
|
|
110
|
+
sourceIP: context.sourceIP,
|
|
111
|
+
traceId: context.traceId,
|
|
112
|
+
};
|
|
113
|
+
const { success, error, body } = await this.emit(connection.nativeConnection, 'call', [action, params, miniContext]);
|
|
114
|
+
if (success)
|
|
115
|
+
return body;
|
|
116
|
+
else if (error)
|
|
117
|
+
throw new Error(error.message);
|
|
118
|
+
else
|
|
119
|
+
throw new Error('[RPC] Unknown Error');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 绑定 call 事件
|
|
123
|
+
* @param connection
|
|
124
|
+
*/
|
|
125
|
+
bindCall(connection) {
|
|
126
|
+
const { id, name, ip } = connection.data;
|
|
127
|
+
connection.nativeConnection.on('call', async (action, params, context, callback) => {
|
|
128
|
+
const validContext = new oox.Context({
|
|
129
|
+
...context,
|
|
130
|
+
ip: ip,
|
|
131
|
+
caller: name,
|
|
132
|
+
callerId: id,
|
|
133
|
+
connection
|
|
134
|
+
});
|
|
135
|
+
this.call(action, params, validContext, callback);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async call(action, params, context, callback) {
|
|
139
|
+
const returns = await oox.call(action, params, context);
|
|
140
|
+
if (returns.error && !oox.config.errorStack) {
|
|
141
|
+
// 不返回错误调用栈信息
|
|
142
|
+
delete returns.error.stack;
|
|
143
|
+
}
|
|
144
|
+
'function' === typeof callback && callback(returns);
|
|
145
|
+
return returns;
|
|
146
|
+
}
|
|
147
|
+
}
|
package/types/app.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
3
|
export * as logger from './logger.js';
|
|
4
|
-
export interface ReturnsBody {
|
|
5
|
-
traceId
|
|
4
|
+
export interface ReturnsBody<T = any> {
|
|
5
|
+
traceId?: string;
|
|
6
6
|
success: boolean;
|
|
7
|
-
body?:
|
|
7
|
+
body?: T;
|
|
8
8
|
error?: {
|
|
9
9
|
message: string;
|
|
10
10
|
stack?: string;
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
export declare class
|
|
13
|
+
export declare class AppContext {
|
|
14
14
|
[x: string]: any;
|
|
15
|
-
traceId?: string;
|
|
15
|
+
traceId?: string | undefined;
|
|
16
16
|
}
|
|
17
|
-
export declare const asyncStore: AsyncLocalStorage<
|
|
17
|
+
export declare const asyncStore: AsyncLocalStorage<AppContext>;
|
|
18
18
|
export declare const eventHub: EventEmitter<[never]>;
|
|
19
19
|
/**
|
|
20
20
|
* the kvMethods is all actions refs [has bind this]
|
|
@@ -24,21 +24,21 @@ export declare const sourceKVMethods: Map<string, Function>;
|
|
|
24
24
|
export declare function setMethods(methods: any): void;
|
|
25
25
|
export declare function getMethods(): any;
|
|
26
26
|
export declare function on(event: 'app:configured' | 'app:served' | 'app:stopped', listener: () => void): void;
|
|
27
|
-
export declare function on(event: 'call:start', listener: (timestamp: number, action: string, params: any[], context:
|
|
28
|
-
export declare function on(event: 'call:success', listener: (timestamp: number, action: string, params: any[], context:
|
|
29
|
-
export declare function on(event: 'call:fail', listener: (timestamp: number, action: string, params: any[], context:
|
|
30
|
-
export declare function on(event: 'log', listener: (timestamp: number, context:
|
|
27
|
+
export declare function on(event: 'call:start', listener: (timestamp: number, action: string, params: any[], context: AppContext) => void): void;
|
|
28
|
+
export declare function on(event: 'call:success', listener: (timestamp: number, action: string, params: any[], context: AppContext, result: ReturnsBody) => void): void;
|
|
29
|
+
export declare function on(event: 'call:fail', listener: (timestamp: number, action: string, params: any[], context: AppContext, error: Error) => void): void;
|
|
30
|
+
export declare function on(event: 'log', listener: (timestamp: number, context: AppContext | null, level: string, msgs: any[]) => void): void;
|
|
31
31
|
export declare function once(event: 'app:configured' | 'app:served' | 'app:stopped', listener: (...args: any[]) => void): void;
|
|
32
|
-
export declare function once(event: 'call:start', listener: (timestamp: number, action: string, params: any[], context:
|
|
33
|
-
export declare function once(event: 'call:success', listener: (timestamp: number, action: string, params: any[], context:
|
|
34
|
-
export declare function once(event: 'call:fail', listener: (timestamp: number, action: string, params: any[], context:
|
|
35
|
-
export declare function once(event: 'log', listener: (timestamp: number, context:
|
|
32
|
+
export declare function once(event: 'call:start', listener: (timestamp: number, action: string, params: any[], context: AppContext) => void): void;
|
|
33
|
+
export declare function once(event: 'call:success', listener: (timestamp: number, action: string, params: any[], context: AppContext, result: ReturnsBody) => void): void;
|
|
34
|
+
export declare function once(event: 'call:fail', listener: (timestamp: number, action: string, params: any[], context: AppContext, error: Error) => void): void;
|
|
35
|
+
export declare function once(event: 'log', listener: (timestamp: number, context: AppContext | null, level: string, msgs: any[]) => void): void;
|
|
36
36
|
export declare function off(event: 'app:configured' | 'app:served' | 'app:stopped' | 'call:start' | 'call:success' | 'call:fail' | 'log', listener: (...args: any[]) => void): void;
|
|
37
37
|
export declare function emit(event: 'app:configured' | 'app:served' | 'app:stopped'): boolean;
|
|
38
|
-
export declare function emit(event: 'call:start', timestamp: number, action: string, params: any[], context:
|
|
39
|
-
export declare function emit(event: 'call:success', timestamp: number, action: string, params: any[], context:
|
|
40
|
-
export declare function emit(event: 'call:fail', timestamp: number, action: string, params: any[], context:
|
|
41
|
-
export declare function emit(event: 'log', timestamp: number, context:
|
|
38
|
+
export declare function emit(event: 'call:start', timestamp: number, action: string, params: any[], context: AppContext): boolean;
|
|
39
|
+
export declare function emit(event: 'call:success', timestamp: number, action: string, params: any[], context: AppContext, result: ReturnsBody): boolean;
|
|
40
|
+
export declare function emit(event: 'call:fail', timestamp: number, action: string, params: any[], context: AppContext, error: Error): boolean;
|
|
41
|
+
export declare function emit(event: 'log', timestamp: number, context: AppContext | null, level: string, content: any): boolean;
|
|
42
42
|
/**
|
|
43
43
|
* Call an Function on RPC server
|
|
44
44
|
* @param action
|
|
@@ -46,5 +46,5 @@ export declare function emit(event: 'log', timestamp: number, context: Context |
|
|
|
46
46
|
* @param context
|
|
47
47
|
* @returns
|
|
48
48
|
*/
|
|
49
|
-
export declare function call(action: string, params: any[], context:
|
|
50
|
-
export declare function execute(action: string, params: Array<any>, context:
|
|
49
|
+
export declare function call(action: string, params: any[] | undefined, context: AppContext): Promise<ReturnsBody>;
|
|
50
|
+
export declare function execute(action: string, params: Array<any>, context: AppContext): Promise<any>;
|
package/types/bin/register.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import * as oox from '../index.js';
|
|
2
|
+
export declare function registry(identifies: string[] | oox.KeepAliveConnectionData[]): Promise<void>;
|
package/types/bin/starter.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import * as oox from '../index.js';
|
|
2
1
|
export declare function configure(env?: {
|
|
3
2
|
[x: string]: any;
|
|
4
|
-
}, entryFilename?: string): Promise<
|
|
3
|
+
}, entryFilename?: string): Promise<import("../config.js").Config>;
|
|
5
4
|
export declare function startup(): Promise<void>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { KeepAliveConnectionData } from "./keepalive-connection.js";
|
|
2
|
+
export interface ConfigAllow {
|
|
3
|
+
untrusted: boolean;
|
|
4
|
+
ip: string[];
|
|
5
|
+
caller: string[];
|
|
6
|
+
}
|
|
7
|
+
interface ConfigInterface {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
group: string;
|
|
11
|
+
ignore: string[];
|
|
12
|
+
entryInfo: {
|
|
13
|
+
path: string;
|
|
14
|
+
group: string;
|
|
15
|
+
};
|
|
16
|
+
host: string;
|
|
17
|
+
port: number;
|
|
18
|
+
origin: string | string[];
|
|
19
|
+
errorStack: boolean;
|
|
20
|
+
isRegistry: boolean;
|
|
21
|
+
registry: string[] | KeepAliveConnectionData[];
|
|
22
|
+
registryToken: string;
|
|
23
|
+
registryAdapter: string;
|
|
24
|
+
token: string;
|
|
25
|
+
allow: ConfigAllow;
|
|
26
|
+
}
|
|
27
|
+
export declare class Config implements ConfigInterface {
|
|
28
|
+
[x: string]: any;
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
group: string;
|
|
32
|
+
ignore: string[];
|
|
33
|
+
entryInfo: {
|
|
34
|
+
path: string;
|
|
35
|
+
group: string;
|
|
36
|
+
};
|
|
37
|
+
host: string;
|
|
38
|
+
port: number;
|
|
39
|
+
origin: string | string[];
|
|
40
|
+
errorStack: boolean;
|
|
41
|
+
isRegistry: boolean;
|
|
42
|
+
registry: string[] | KeepAliveConnectionData[];
|
|
43
|
+
registryToken: string;
|
|
44
|
+
registryAdapter: string;
|
|
45
|
+
token: string;
|
|
46
|
+
allow: ConfigAllow;
|
|
47
|
+
}
|
|
48
|
+
type StrictFormatter<T> = {
|
|
49
|
+
[K in keyof T]: (value: any) => T[K];
|
|
50
|
+
};
|
|
51
|
+
export declare const formatters: StrictFormatter<ConfigInterface> & {
|
|
52
|
+
[x: string]: (v: any) => any;
|
|
53
|
+
};
|
|
54
|
+
export {};
|