oox 0.3.2 → 0.3.4

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/bin/argv.js CHANGED
@@ -1,3 +1,5 @@
1
+ import * as FS from 'node:fs';
2
+ import * as PATH from 'node:path';
1
3
  export function getAllEnvArgs() {
2
4
  const args = process.argv.slice(2);
3
5
  const env = {};
@@ -9,7 +11,14 @@ export function getAllEnvArgs() {
9
11
  env[arg.slice(1)] = true;
10
12
  }
11
13
  else if (!arg.includes('=')) {
12
- env[arg] = true;
14
+ // index.js
15
+ const path = PATH.resolve(process.cwd(), arg);
16
+ if (FS.existsSync(path)) {
17
+ continue;
18
+ }
19
+ else {
20
+ env[arg] = true;
21
+ }
13
22
  }
14
23
  else {
15
24
  const index = arg.indexOf('=');
package/bin/cli.js CHANGED
@@ -27,23 +27,26 @@ if (execFilename.endsWith('oox') || fileURLToPath(import.meta.url) === execFilen
27
27
  console.log();
28
28
  console.log(' oox entry.js port=8080');
29
29
  console.log();
30
- console.log(' oox app/entry/index.js group=app/ env=envs/entry.js ignore=core');
30
+ console.log(' oox entry.js group=app/ registry=:6000');
31
+ console.log(' oox app/entry/index.js group=app/ env=envs/prod.js ignore=core');
31
32
  console.log();
32
33
  console.log(chalk.bold('Params:'));
33
34
  const params = [
34
- [' default-env [ file ] ', '.js or .json file, merge to oox.config'],
35
- [' env [ file ] ', '.js or .json file, merge to oox.config', chalk.bold('(after default-env)')],
36
- [' port [ int ] ', 'set', chalk.bold('0'), 'for random port, or any integer > 0'],
37
- [' group [ dir ] ', 'service group directory, all LocalCall transform to RPC'],
38
- [' ignore [ name ] ', 'set a name for LocalCall do not transform to RPC, support string | array<string>'],
39
- [' http [ json ] ', 'HTTP server options, support flat name, ex: http.path=/api'],
40
- [' socketio [ json ] ', 'SocketIO server options, support flat name'],
41
- [' registry [ urls ] ', 'registry service url, support string | array<string>'],
42
- [' origin [ urls ] ', 'set', chalk.bold('*'), 'allow any connections <Access-Control-Allow-Origin>'],
43
- [' errorStack [ bool ] ', 'set no to hidden error stack return'],
44
- [' ... ', 'set params as', chalk.bold('foo=bar') + ',', 'usage as', chalk.bold('oox.config.foo')]
35
+ ['default-env', 'file', '.js or .json file, merge to oox.config'],
36
+ ['env', 'file', `${chalk.bold.red('default-env')}.js or .json file, merge to oox.config, ${chalk.bold('(after default-env)')}`],
37
+ ['port', 'int', `default is ${chalk.bold('0')}, for random port, or any integer > 0`],
38
+ ['group', 'dir', 'service group directory, all LocalCall transform to RPC'],
39
+ ['ignore', 'name', 'set a name for LocalCall do not transform to RPC, support string | array<string>'],
40
+ ['http', 'json', 'HTTP server options, support flat name, ex: http.path=/api'],
41
+ ['socketio', 'json', 'SocketIO server options, support flat name'],
42
+ ['isRegistry', 'bool', `default is ${chalk.bold.red('true')}, set no to disable service registry`],
43
+ ['registryAdapter', 'name', 'set service registry adapter name'],
44
+ ['registry', 'urls', 'registry service url, support string | array<string>'],
45
+ ['origin', 'urls', `set ${chalk.bold('*')}, allow any connections <Access-Control-Allow-Origin>`],
46
+ ['errorStack', 'bool', 'set no to hidden error stack return'],
45
47
  ];
46
- params.forEach(row => console.log(...row, '\n'));
48
+ console.log(mergeCommandParams(params));
49
+ console.log(' ...', 'set params as', chalk.bold('foo=bar') + ',', 'usage as', chalk.bold('oox.config.foo'));
47
50
  console.log();
48
51
  }
49
52
  if (isStartup) {
@@ -55,3 +58,27 @@ if (execFilename.endsWith('oox') || fileURLToPath(import.meta.url) === execFilen
55
58
  await startup();
56
59
  }
57
60
  }
61
+ function mergeCommandParams(params) {
62
+ let result = '';
63
+ const perLinePrefix = ' '.repeat(2);
64
+ const nameMaxLength = 12;
65
+ const typeMaxLength = 6;
66
+ for (const param of params) {
67
+ const name = param[0];
68
+ const type = param[1];
69
+ const desc = param.slice(2).join(' ');
70
+ result += perLinePrefix + name;
71
+ if (name.length > nameMaxLength) {
72
+ result += '\n' + perLinePrefix;
73
+ result += ' '.repeat(nameMaxLength);
74
+ }
75
+ else {
76
+ result += ' '.repeat(nameMaxLength - name.length);
77
+ }
78
+ result += '[' + type + ']';
79
+ result += ' '.repeat(typeMaxLength - type.length);
80
+ result += desc;
81
+ result += '\n';
82
+ }
83
+ return result;
84
+ }
package/bin/configurer.js CHANGED
@@ -19,6 +19,7 @@ function mergeFlatEnv(env) {
19
19
  tmpEnv = tmpEnv[subKey];
20
20
  }
21
21
  tmpEnv[valueKey] = env[key];
22
+ delete env[key];
22
23
  }
23
24
  }
24
25
  }
@@ -32,12 +33,13 @@ async function readEnvFile(filePath) {
32
33
  else {
33
34
  const finalPath = path.resolve(filePath).replace(/\\/g, '/');
34
35
  env = await import(`file://${finalPath}`);
36
+ env = env.default || env;
35
37
  }
36
38
  }
37
39
  else {
38
40
  throw new Error('Env file not found: ' + filePath);
39
41
  }
40
- return env.default || env;
42
+ return env;
41
43
  }
42
44
  export async function buildConfig(mergeEnv) {
43
45
  const env = Object.create(null);
package/bin/register.js CHANGED
@@ -1,25 +1,11 @@
1
1
  import chalk from 'chalk';
2
2
  import * as oox from '../index.js';
3
- import { default as SocketIOModule } from '../modules/socketio/index.js';
4
3
  const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
5
- function urlFormatter(url) {
6
- let _url = SocketIOModule.genWebSocketUrl(url);
7
- const urlObject = new URL(_url);
8
- if (urlObject.pathname === '/' && !url.endsWith('/'))
9
- _url += '/socket.io';
10
- return _url;
11
- }
12
4
  async function connect(url, prevError = null) {
13
- const socketio = oox.modules.get('socketio');
14
- const { host } = oox.config;
15
- const { port, path } = socketio.config;
16
- const urlObject = new URL(url);
17
- // check if url is self
18
- if (urlObject.host === host && urlObject.port === String(port))
19
- return;
5
+ const adapter = oox.keepAliveConnectionAdapters.get(oox.config.registryAdapter);
20
6
  try {
21
- const socket = await socketio.connect(url);
22
- onConnection(socket, url);
7
+ const connection = await adapter.open(url);
8
+ onConnection(connection, url);
23
9
  }
24
10
  catch (error) {
25
11
  if (!prevError)
@@ -28,19 +14,19 @@ async function connect(url, prevError = null) {
28
14
  connect(url, error);
29
15
  }
30
16
  }
31
- async function onConnection(socket, url) {
32
- const { name } = socket.data;
33
- socket.once('disconnect', async () => {
34
- console.log(chalk.red('[Registry]'), `Service<${name}>`, chalk.underline.red(`${url}`), 'disconnected.');
17
+ async function onConnection(connection, url) {
18
+ const { name } = connection.data;
19
+ connection.once('disconnect', async () => {
20
+ console.log(chalk.red('[Registry]'), `Service<${name}>`, chalk.underline.red(`${connection.data.url || url}`), 'disconnected.');
35
21
  await delay(1000);
36
22
  connect(url);
37
23
  });
38
- console.log(chalk.green('[Registry]'), `Service<${name}>`, chalk.underline.green(`${url}`), 'connected.');
24
+ console.log(chalk.green('[Registry]'), `Service<${name}>`, chalk.underline.green(`${connection.data.url || url}`), 'connected.');
39
25
  }
40
26
  export async function registry(urls) {
41
27
  if ('string' === typeof urls)
42
28
  urls = [urls];
43
29
  for (const url of urls) {
44
- connect(urlFormatter(url));
30
+ connect(url);
45
31
  }
46
32
  }
package/bin/starter.js CHANGED
@@ -53,9 +53,9 @@ export async function startup() {
53
53
  console.log();
54
54
  console.log('Service', chalk.bold(`${oox.config.name}`), 'running.');
55
55
  if (http.config.enabled)
56
- console.log(' at', chalk.underline.green(http.getUrl()));
56
+ console.log(' at', chalk.underline.green(http.getURL()));
57
57
  if (socketio.config.enabled)
58
- console.log(' at', chalk.underline.green(socketio.getUrl()));
58
+ console.log(' at', chalk.underline.green(socketio.getURL()));
59
59
  console.log();
60
60
  // 服务注册
61
61
  if (config.registry)
package/index.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import * as app from './app.js';
3
3
  import { getIPAddress } from './utils.js';
4
+ import * as registry from './registry.js';
4
5
  import Module, { ModuleConfig } from './modules/module.js';
5
- import Modules from './modules/index.js';
6
- export { Module, ModuleConfig };
7
- export const modules = new Modules;
8
- export const { asyncStore, setMethods, getMethods, kvMethods, sourceKVMethods, call, execute, logger, on, once, off, emit, } = app;
6
+ import { KeepAliveConnection, keepAliveConnectionAdapters, keepAliveConnections, enabledKeepAliveConnections } from './keepalive-connection.js';
9
7
  export class Context extends app.Context {
10
8
  // 请求溯源IP
11
9
  sourceIP = '';
@@ -24,6 +22,8 @@ export class Context extends app.Context {
24
22
  }
25
23
  }
26
24
  export class Config {
25
+ // 服务ID
26
+ id = randomUUID();
27
27
  // 服务名称
28
28
  name = 'local';
29
29
  // 服务列表路径
@@ -45,6 +45,12 @@ export class Config {
45
45
  origin = '';
46
46
  // 默认返回错误调用栈信息信息
47
47
  errorStack = true;
48
+ // 是否开启服务注册功能
49
+ isRegistry = true;
50
+ // 服务注册列表
51
+ registry = [];
52
+ // 服务注册适配器
53
+ registryAdapter = 'socketio';
48
54
  }
49
55
  export const config = new Config();
50
56
  let genTraceIdFunction = () => randomUUID();
@@ -78,55 +84,26 @@ export async function serve() {
78
84
  export async function stop() {
79
85
  await modules.stop();
80
86
  }
81
- export class RPCKeepAliveConnection {
82
- data;
83
- nativeConnection = null;
84
- adapter = null;
85
- constructor(adapter, nativeConnection, data) {
86
- this.adapter = adapter;
87
- this.nativeConnection = nativeConnection;
88
- if (data)
89
- this.data = data;
90
- }
91
- }
92
- export const keepAliveConnections = new Map();
93
- export function getKeepAliveConnections(name) {
94
- return keepAliveConnections.get(name) || new Map();
95
- }
96
- export function getKeepAliveConnection(name, id) {
97
- const connections = keepAliveConnections.get(name);
98
- if (!connections)
99
- return null;
100
- return connections.get(id);
101
- }
102
87
  export function addKeepAliveConnection(connection) {
103
- const { name, id } = connection.data;
104
- if (keepAliveConnections.has(name)) {
105
- keepAliveConnections.get(name).set(id, connection);
106
- }
107
- else {
108
- keepAliveConnections.set(name, new Map([[id, connection]]));
109
- }
88
+ keepAliveConnections.add(connection);
110
89
  }
111
- export function removeKeepAliveConnection(name, id) {
112
- if (name instanceof RPCKeepAliveConnection) {
113
- id = name.data.id;
114
- name = name.data.name;
90
+ export function removeKeepAliveConnection(arg1, arg2) {
91
+ if (typeof arg1 === 'string') {
92
+ keepAliveConnections.remove(arg1, arg2);
93
+ enabledKeepAliveConnections.remove(arg1, arg2);
115
94
  }
116
- if (keepAliveConnections.has(name)) {
117
- const group = keepAliveConnections.get(name);
118
- group.delete(id);
119
- if (!group.size)
120
- keepAliveConnections.delete(name);
95
+ else {
96
+ keepAliveConnections.remove(arg1);
97
+ enabledKeepAliveConnections.remove(arg1);
121
98
  }
122
99
  }
123
100
  /**
124
- * random connection select for default load balance policy
125
- * @param name service name
126
- * @returns selected connection
127
- */
101
+ * random connection select for default load balance policy
102
+ * @param name service name
103
+ * @returns selected connection
104
+ */
128
105
  let loadBalancePolicy = (name) => {
129
- const connections = keepAliveConnections.get(name);
106
+ const connections = enabledKeepAliveConnections.getConnectionsOfService(name);
130
107
  if (!connections || !connections.size)
131
108
  return null;
132
109
  const arrayConnections = Array.from(connections.values());
@@ -141,7 +118,7 @@ export async function rpc(arg1, action, params, context) {
141
118
  context = getContext();
142
119
  }
143
120
  let connection;
144
- if (arg1 instanceof RPCKeepAliveConnection) {
121
+ if (arg1 instanceof KeepAliveConnection) {
145
122
  connection = arg1;
146
123
  }
147
124
  else if ('string' === typeof arg1) {
@@ -151,5 +128,12 @@ export async function rpc(arg1, action, params, context) {
151
128
  }
152
129
  else
153
130
  throw new Error(`Unknown rpc arg1<${arg1}>`);
154
- return connection.adapter.rpc(connection.nativeConnection, action, params, context);
131
+ return connection.adapter.rpc(connection, action, params, context);
155
132
  }
133
+ export { KeepAliveConnection, keepAliveConnectionAdapters, keepAliveConnections, enabledKeepAliveConnections };
134
+ export { Module, ModuleConfig };
135
+ export { registry };
136
+ export const { asyncStore, setMethods, getMethods, kvMethods, sourceKVMethods, call, execute, logger, on, once, off, emit, } = app;
137
+ // 放在最后导入,解决循环依赖问题
138
+ import Modules from './modules/index.js';
139
+ export const modules = new Modules;
@@ -0,0 +1,96 @@
1
+ import EventEmitter from 'node:events';
2
+ export class KeepAliveConnection extends EventEmitter {
3
+ // 连接是否可用
4
+ #enabled = false;
5
+ data;
6
+ nativeConnection;
7
+ adapter;
8
+ constructor(adapter, nativeConnection, data) {
9
+ super();
10
+ this.adapter = adapter;
11
+ this.nativeConnection = nativeConnection;
12
+ this.data = Object.assign(data, {
13
+ adapter: adapter.name,
14
+ });
15
+ }
16
+ /**
17
+ * 设置连接是否可用,并自动触发enabled或disabled事件
18
+ * @param enabled 是否可用
19
+ */
20
+ set enabled(enabled) {
21
+ if (enabled !== this.#enabled) {
22
+ this.#enabled = enabled;
23
+ this.emit(enabled ? 'enabled' : 'disabled');
24
+ if (enabled) {
25
+ enabledKeepAliveConnections.add(this);
26
+ }
27
+ else {
28
+ enabledKeepAliveConnections.remove(this);
29
+ }
30
+ }
31
+ }
32
+ get enabled() {
33
+ return this.#enabled;
34
+ }
35
+ /**
36
+ * enable & mount connection
37
+ * @param params
38
+ * @returns
39
+ */
40
+ ready(params) {
41
+ // 连接已就绪,不允许重复就绪
42
+ if (this.enabled)
43
+ return;
44
+ const { id, name } = params;
45
+ keepAliveConnections.remove(this);
46
+ // 更新连接数据
47
+ this.data.id = id;
48
+ this.data.name = name;
49
+ keepAliveConnections.add(this);
50
+ this.enabled = true;
51
+ }
52
+ }
53
+ export class KeepAliveConnectionStore {
54
+ #map = new Map();
55
+ entries() {
56
+ return this.#map.entries();
57
+ }
58
+ getConnectionsOfService(name) {
59
+ return this.#map.get(name) || new Map();
60
+ }
61
+ has(name, id) {
62
+ const connections = this.#map.get(name);
63
+ if (!connections)
64
+ return false;
65
+ return connections.has(id);
66
+ }
67
+ get(name, id) {
68
+ const connections = this.#map.get(name);
69
+ if (!connections)
70
+ return null;
71
+ return connections.get(id) || null;
72
+ }
73
+ add(connection) {
74
+ const { name, id } = connection.data;
75
+ const connections = this.#map.get(name);
76
+ if (connections) {
77
+ connections.set(id, connection);
78
+ }
79
+ else {
80
+ this.#map.set(name, new Map([[id, connection]]));
81
+ }
82
+ }
83
+ remove(name, id) {
84
+ if (name instanceof KeepAliveConnection) {
85
+ id = name.data.id;
86
+ name = name.data.name;
87
+ }
88
+ const connections = this.#map.get(name);
89
+ if (connections && id !== undefined) {
90
+ connections.delete(id);
91
+ }
92
+ }
93
+ }
94
+ export const keepAliveConnectionAdapters = new Map();
95
+ export const keepAliveConnections = new KeepAliveConnectionStore();
96
+ export const enabledKeepAliveConnections = new KeepAliveConnectionStore();
@@ -28,11 +28,11 @@ export default class HTTPModule extends Module {
28
28
  config = new HTTPConfig;
29
29
  server = null;
30
30
  router = new Router();
31
- getUrl() {
31
+ getURL() {
32
32
  const { host } = oox.config;
33
33
  const { port, path } = this.config;
34
34
  const protocol = this.config.ssl.enabled ? `https:` : `http:`;
35
- return `${protocol}//${host}:${port}${path}`;
35
+ return new URL(`${protocol}//${host}:${port}${path}`);
36
36
  }
37
37
  // 注册GET路由
38
38
  get(path, ...args) {
@@ -0,0 +1,37 @@
1
+ import * as SocketIOClient from 'socket.io-client';
2
+ import * as oox from '../../index.js';
3
+ import { OOXEvent, genWebSocketURL } from './utils.js';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { SampleKeepAliveConnectionAdapter } from '../../samples/index.js';
6
+ export default class SocketIOAdapter extends SampleKeepAliveConnectionAdapter {
7
+ name = 'socketio';
8
+ OOXEvent = OOXEvent;
9
+ nativeEvent = { CONNECT: 'connect', DISCONNECT: 'disconnect', ERROR: 'connect_error' };
10
+ newConnection(url) {
11
+ const { id, host, name } = oox.config;
12
+ const headers = {
13
+ 'x-ip': host,
14
+ 'x-caller': name,
15
+ 'x-caller-id': id,
16
+ };
17
+ let mURL;
18
+ if ('string' === typeof url) {
19
+ mURL = genWebSocketURL(url);
20
+ }
21
+ else {
22
+ mURL = url;
23
+ }
24
+ const socket = SocketIOClient.io(mURL.origin, {
25
+ extraHeaders: headers,
26
+ path: mURL.pathname,
27
+ autoConnect: false,
28
+ });
29
+ const connection = new oox.KeepAliveConnection(this, socket, {
30
+ name: 'anonymous',
31
+ id: randomUUID(),
32
+ host: mURL.host,
33
+ url: mURL
34
+ });
35
+ return connection;
36
+ }
37
+ }
@@ -1,11 +1,7 @@
1
- import * as path from 'node:path';
2
- import SocketIOClient from './client.js';
1
+ import * as PATH from 'node:path';
3
2
  import * as oox from '../../index.js';
4
- import { RPCKeepAliveConnection, removeKeepAliveConnection, addKeepAliveConnection, getKeepAliveConnections } from '../../index.js';
5
- import { sockets } from './socket.js';
6
- export { sockets };
7
- export default class SocketIOModule extends SocketIOClient {
8
- sockets = sockets;
3
+ import SocketINServer from './server.js';
4
+ export default class SocketIOModule extends SocketINServer {
9
5
  async serve() {
10
6
  await this.stop();
11
7
  const _http = oox.modules.builtins.http;
@@ -18,154 +14,10 @@ export default class SocketIOModule extends SocketIOClient {
18
14
  // http 模块未被禁用
19
15
  isShareServer &&= httpConfig.enabled;
20
16
  if (isShareServer) {
21
- config.path = path.posix.join(httpConfig.path, config.path);
17
+ config.path = PATH.posix.join(httpConfig.path, config.path);
22
18
  this.server = _http.server;
23
19
  this.config.ssl = _http.config.ssl;
24
20
  }
25
21
  await super.serve();
26
22
  }
27
- onSyncConnection(socket) {
28
- const mSockets = Array.from(sockets.values())
29
- .filter(s => s !== socket &&
30
- s.data.name !== socket.data.name &&
31
- /^wss?:\/\/.+$/.test(s.data.id));
32
- return mSockets.map(s => s.data);
33
- }
34
- serverOnDisconnect(socket, reason) {
35
- super.serverOnDisconnect(socket, reason);
36
- removeKeepAliveConnection(socket.data.name, socket.data.id);
37
- }
38
- clientOnDisconnect(socket, reason) {
39
- super.clientOnDisconnect(socket, reason);
40
- removeKeepAliveConnection(socket.data.name, socket.data.id);
41
- }
42
- /**
43
- *
44
- * @param socket 是由哪个通道发送过来的
45
- * @param connectionDatas
46
- */
47
- clientOnSyncConnection(socket, connectionDatas) {
48
- for (const data of connectionDatas)
49
- if (!sockets.has(data.id))
50
- this.connect(data.id).catch((error) => console.error(error));
51
- }
52
- onFetchActions(socket, search) {
53
- const data = [];
54
- for (const key of oox.kvMethods.keys())
55
- if (!key.endsWith('_proxy') && key.includes(search))
56
- data.push(key);
57
- return data;
58
- }
59
- fetchActions(id, search = '') {
60
- let socket = sockets.get(id);
61
- if (!socket) {
62
- const connections = getKeepAliveConnections(id);
63
- if (!connections || !connections.size)
64
- throw new Error(`Unknown service identify<${id}>`);
65
- id = connections.keys().next().value;
66
- socket = sockets.get(id);
67
- }
68
- if (!socket)
69
- throw new Error(`Unknown service identify<${id}>`);
70
- return this.emit(socket.data.id, 'fetchActions', [search]);
71
- }
72
- onConnection(socket) {
73
- const { id, name, host } = socket.data;
74
- const connection = new RPCKeepAliveConnection(this, id, socket.data);
75
- addKeepAliveConnection(connection);
76
- const connectionContext = {
77
- sourceIP: '',
78
- ip: host,
79
- caller: name,
80
- callerId: id,
81
- connection
82
- };
83
- socket.on('fetchActions', async (search, fn) => {
84
- if ('function' !== typeof fn)
85
- return;
86
- const data = await this.onFetchActions(socket, search);
87
- fn(data);
88
- });
89
- socket.on('call', async (action, params, context, callback) => {
90
- if ('object' !== typeof context)
91
- context = oox.genContext(connectionContext);
92
- else
93
- context = oox.genContext(Object.assign(context, connectionContext));
94
- this.call(action, params, context, callback);
95
- });
96
- }
97
- /**
98
- *
99
- * @param {Socket} socket
100
- */
101
- serverOnConnection(socket) {
102
- super.serverOnConnection(socket);
103
- socket.setMaxListeners(0);
104
- socket.on('syncConnection', async (fn) => {
105
- if ('function' !== typeof fn)
106
- return;
107
- const data = this.onSyncConnection(socket);
108
- fn(data);
109
- });
110
- this.onConnection(socket);
111
- }
112
- async call(action, params, context, callback) {
113
- const returns = await oox.call(action, params, context);
114
- if (!oox.config.errorStack && returns.error) {
115
- // 不返回错误调用栈信息
116
- delete returns.error.stack;
117
- }
118
- 'function' === typeof callback && callback(returns);
119
- return returns;
120
- }
121
- clientOnConnection(socket) {
122
- super.clientOnConnection(socket);
123
- socket.emit('syncConnection', (socketDatas) => this.clientOnSyncConnection(socket, socketDatas));
124
- this.onConnection(socket);
125
- }
126
- /**
127
- * socketio emit
128
- */
129
- async emit(url, event, params) {
130
- let socket = null;
131
- try {
132
- socket = await this.connect(url);
133
- }
134
- catch (error) {
135
- // try again
136
- socket = await this.connect(url);
137
- }
138
- try {
139
- return await new Promise((resolve, reject) => {
140
- const onError = (reason) => {
141
- const message = 'string' === typeof reason ? reason : reason instanceof Error ? reason.message : 'connect error';
142
- reject(new Error(message));
143
- };
144
- // RPC 执行时中断连接
145
- socket.once('disconnect', onError);
146
- socket.emit(event, ...params, (returns) => {
147
- socket.off('disconnect', onError);
148
- resolve(returns);
149
- });
150
- });
151
- }
152
- catch (error) {
153
- throw new Error(error.message);
154
- }
155
- }
156
- /**
157
- * RPC
158
- */
159
- async rpc(url, action, params, context) {
160
- if (!context || !context.traceId) {
161
- context = oox.getContext();
162
- }
163
- const { success, error, body } = await this.emit(url, 'call', [action, params, context]);
164
- if (success)
165
- return body;
166
- else if (error)
167
- throw new Error(error.message);
168
- else
169
- throw new Error('[RPC] Unknown Error');
170
- }
171
23
  }