@opensumi/ide-connection 2.27.3-rc-1708399099.0 → 2.27.3-rc-1710386185.0

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.
Files changed (201) hide show
  1. package/README.md +1 -1
  2. package/lib/browser/ws-channel-handler.d.ts +1 -1
  3. package/lib/browser/ws-channel-handler.d.ts.map +1 -1
  4. package/lib/browser/ws-channel-handler.js +23 -33
  5. package/lib/browser/ws-channel-handler.js.map +1 -1
  6. package/lib/common/buffers/buffers.d.ts +1 -0
  7. package/lib/common/buffers/buffers.d.ts.map +1 -1
  8. package/lib/common/buffers/buffers.js +3 -3
  9. package/lib/common/buffers/buffers.js.map +1 -1
  10. package/lib/common/{utils.d.ts → capturer.d.ts} +1 -19
  11. package/lib/common/capturer.d.ts.map +1 -0
  12. package/lib/common/capturer.js +26 -0
  13. package/lib/common/capturer.js.map +1 -0
  14. package/lib/common/connection/drivers/frame-decoder.d.ts +40 -1
  15. package/lib/common/connection/drivers/frame-decoder.d.ts.map +1 -1
  16. package/lib/common/connection/drivers/frame-decoder.js +9 -10
  17. package/lib/common/connection/drivers/frame-decoder.js.map +1 -1
  18. package/lib/common/connection/drivers/index.d.ts +0 -1
  19. package/lib/common/connection/drivers/index.d.ts.map +1 -1
  20. package/lib/common/connection/drivers/index.js +0 -1
  21. package/lib/common/connection/drivers/index.js.map +1 -1
  22. package/lib/common/connection/drivers/message-port.d.ts.map +1 -1
  23. package/lib/common/connection/drivers/message-port.js +1 -4
  24. package/lib/common/connection/drivers/message-port.js.map +1 -1
  25. package/lib/common/connection/drivers/node-message-port.d.ts +1 -1
  26. package/lib/common/connection/drivers/node-message-port.d.ts.map +1 -1
  27. package/lib/common/connection/drivers/node-message-port.js.map +1 -1
  28. package/lib/common/connection/drivers/reconnecting-websocket.d.ts.map +1 -1
  29. package/lib/common/connection/drivers/reconnecting-websocket.js +1 -1
  30. package/lib/common/connection/drivers/reconnecting-websocket.js.map +1 -1
  31. package/lib/common/connection/drivers/socket.d.ts +3 -10
  32. package/lib/common/connection/drivers/socket.d.ts.map +1 -1
  33. package/lib/common/connection/drivers/socket.js +3 -36
  34. package/lib/common/connection/drivers/socket.js.map +1 -1
  35. package/lib/common/connection/drivers/stream.d.ts +17 -0
  36. package/lib/common/connection/drivers/stream.d.ts.map +1 -0
  37. package/lib/common/connection/drivers/stream.js +70 -0
  38. package/lib/common/connection/drivers/stream.js.map +1 -0
  39. package/lib/common/connection/drivers/ws-websocket.d.ts +1 -1
  40. package/lib/common/connection/drivers/ws-websocket.d.ts.map +1 -1
  41. package/lib/common/connection/drivers/ws-websocket.js.map +1 -1
  42. package/lib/common/fury-extends/any.d.ts +10 -7
  43. package/lib/common/fury-extends/any.d.ts.map +1 -1
  44. package/lib/common/fury-extends/any.js +126 -105
  45. package/lib/common/fury-extends/any.js.map +1 -1
  46. package/lib/common/fury-extends/one-of.d.ts +10 -5
  47. package/lib/common/fury-extends/one-of.d.ts.map +1 -1
  48. package/lib/common/fury-extends/one-of.js +65 -30
  49. package/lib/common/fury-extends/one-of.js.map +1 -1
  50. package/lib/common/fury-extends/shared.d.ts +2 -0
  51. package/lib/common/fury-extends/shared.d.ts.map +1 -1
  52. package/lib/common/fury-extends/shared.js.map +1 -1
  53. package/lib/common/index.d.ts +2 -2
  54. package/lib/common/index.d.ts.map +1 -1
  55. package/lib/common/index.js +2 -2
  56. package/lib/common/index.js.map +1 -1
  57. package/lib/common/message.d.ts +1 -1
  58. package/lib/common/message.d.ts.map +1 -1
  59. package/lib/common/rpc/connection.d.ts +31 -15
  60. package/lib/common/rpc/connection.d.ts.map +1 -1
  61. package/lib/common/rpc/connection.js +206 -138
  62. package/lib/common/rpc/connection.js.map +1 -1
  63. package/lib/common/rpc/index.d.ts +1 -1
  64. package/lib/common/rpc/index.d.ts.map +1 -1
  65. package/lib/common/rpc/index.js +1 -1
  66. package/lib/common/rpc/index.js.map +1 -1
  67. package/lib/common/rpc/message-io.d.ts +61 -0
  68. package/lib/common/rpc/message-io.d.ts.map +1 -0
  69. package/lib/common/rpc/message-io.js +159 -0
  70. package/lib/common/rpc/message-io.js.map +1 -0
  71. package/lib/common/rpc/multiplexer.d.ts +3 -0
  72. package/lib/common/rpc/multiplexer.d.ts.map +1 -1
  73. package/lib/common/rpc/multiplexer.js +3 -0
  74. package/lib/common/rpc/multiplexer.js.map +1 -1
  75. package/lib/common/rpc/types.d.ts +26 -5
  76. package/lib/common/rpc/types.d.ts.map +1 -1
  77. package/lib/common/rpc-service/center.d.ts +6 -3
  78. package/lib/common/rpc-service/center.d.ts.map +1 -1
  79. package/lib/common/rpc-service/center.js +39 -31
  80. package/lib/common/rpc-service/center.js.map +1 -1
  81. package/lib/common/rpc-service/proxy/base.d.ts +5 -3
  82. package/lib/common/rpc-service/proxy/base.d.ts.map +1 -1
  83. package/lib/common/rpc-service/proxy/base.js +56 -17
  84. package/lib/common/rpc-service/proxy/base.js.map +1 -1
  85. package/lib/common/rpc-service/proxy/index.d.ts +1 -3
  86. package/lib/common/rpc-service/proxy/index.d.ts.map +1 -1
  87. package/lib/common/rpc-service/proxy/index.js +1 -3
  88. package/lib/common/rpc-service/proxy/index.js.map +1 -1
  89. package/lib/common/rpc-service/proxy/{legacy.d.ts → json.d.ts} +5 -5
  90. package/lib/common/rpc-service/proxy/json.d.ts.map +1 -0
  91. package/lib/common/rpc-service/proxy/{legacy.js → json.js} +46 -56
  92. package/lib/common/rpc-service/proxy/json.js.map +1 -0
  93. package/lib/common/rpc-service/proxy/sumi.d.ts +1 -1
  94. package/lib/common/rpc-service/proxy/sumi.d.ts.map +1 -1
  95. package/lib/common/rpc-service/proxy/sumi.js +25 -37
  96. package/lib/common/rpc-service/proxy/sumi.js.map +1 -1
  97. package/lib/common/rpc-service/{proxy/registry.d.ts → registry.d.ts} +12 -1
  98. package/lib/common/rpc-service/registry.d.ts.map +1 -0
  99. package/lib/common/rpc-service/registry.js +99 -0
  100. package/lib/common/rpc-service/registry.js.map +1 -0
  101. package/lib/common/rpc-service/stub.js +4 -6
  102. package/lib/common/rpc-service/stub.js.map +1 -1
  103. package/lib/common/{ext-rpc-protocol.d.ts → rpcProtocol.d.ts} +2 -2
  104. package/lib/common/rpcProtocol.d.ts.map +1 -0
  105. package/lib/common/{ext-rpc-protocol.js → rpcProtocol.js} +5 -6
  106. package/lib/common/rpcProtocol.js.map +1 -0
  107. package/lib/common/server-handler.d.ts +35 -0
  108. package/lib/common/server-handler.d.ts.map +1 -0
  109. package/lib/common/server-handler.js +165 -0
  110. package/lib/common/server-handler.js.map +1 -0
  111. package/lib/common/types.d.ts +14 -0
  112. package/lib/common/types.d.ts.map +1 -1
  113. package/lib/common/ws-channel.d.ts +6 -10
  114. package/lib/common/ws-channel.d.ts.map +1 -1
  115. package/lib/common/ws-channel.js +16 -15
  116. package/lib/common/ws-channel.js.map +1 -1
  117. package/lib/electron/channel-handler.d.ts +14 -0
  118. package/lib/electron/channel-handler.d.ts.map +1 -0
  119. package/lib/electron/channel-handler.js +26 -0
  120. package/lib/electron/channel-handler.js.map +1 -0
  121. package/lib/electron/index.d.ts +2 -0
  122. package/lib/electron/index.d.ts.map +1 -0
  123. package/lib/electron/index.js +5 -0
  124. package/lib/electron/index.js.map +1 -0
  125. package/lib/node/common-channel-handler.d.ts +6 -25
  126. package/lib/node/common-channel-handler.d.ts.map +1 -1
  127. package/lib/node/common-channel-handler.js +9 -151
  128. package/lib/node/common-channel-handler.js.map +1 -1
  129. package/package.json +5 -5
  130. package/src/browser/ws-channel-handler.ts +26 -40
  131. package/src/common/buffers/buffers.ts +1 -1
  132. package/src/common/capturer.ts +36 -0
  133. package/src/common/connection/drivers/frame-decoder.ts +11 -11
  134. package/src/common/connection/drivers/index.ts +0 -1
  135. package/src/common/connection/drivers/message-port.ts +1 -4
  136. package/src/common/connection/drivers/node-message-port.ts +2 -2
  137. package/src/common/connection/drivers/reconnecting-websocket.ts +3 -2
  138. package/src/common/connection/drivers/socket.ts +4 -42
  139. package/src/common/connection/drivers/stream.ts +76 -0
  140. package/src/common/connection/drivers/ws-websocket.ts +2 -2
  141. package/src/common/fury-extends/any.ts +122 -102
  142. package/src/common/fury-extends/one-of.ts +79 -31
  143. package/src/common/fury-extends/shared.ts +3 -0
  144. package/src/common/index.ts +2 -2
  145. package/src/common/message.ts +1 -1
  146. package/src/common/rpc/connection.ts +228 -166
  147. package/src/common/rpc/index.ts +1 -1
  148. package/src/common/rpc/message-io.ts +223 -0
  149. package/src/common/rpc/multiplexer.ts +3 -0
  150. package/src/common/rpc/types.ts +30 -5
  151. package/src/common/rpc-service/center.ts +37 -31
  152. package/src/common/rpc-service/proxy/base.ts +59 -12
  153. package/src/common/rpc-service/proxy/index.ts +1 -3
  154. package/src/common/rpc-service/proxy/{legacy.ts → json.ts} +47 -57
  155. package/src/common/rpc-service/proxy/sumi.ts +23 -35
  156. package/src/common/rpc-service/registry.ts +125 -0
  157. package/src/common/rpc-service/stub.ts +6 -6
  158. package/src/common/{ext-rpc-protocol.ts → rpcProtocol.ts} +2 -2
  159. package/src/common/server-handler.ts +183 -0
  160. package/src/common/types.ts +13 -0
  161. package/src/common/ws-channel.ts +21 -23
  162. package/src/electron/channel-handler.ts +26 -0
  163. package/src/electron/index.ts +1 -0
  164. package/src/node/common-channel-handler.ts +10 -165
  165. package/lib/common/connection/drivers/utils.d.ts +0 -12
  166. package/lib/common/connection/drivers/utils.d.ts.map +0 -1
  167. package/lib/common/connection/drivers/utils.js +0 -49
  168. package/lib/common/connection/drivers/utils.js.map +0 -1
  169. package/lib/common/ext-rpc-protocol.d.ts.map +0 -1
  170. package/lib/common/ext-rpc-protocol.js.map +0 -1
  171. package/lib/common/rpc/packet.d.ts +0 -65
  172. package/lib/common/rpc/packet.d.ts.map +0 -1
  173. package/lib/common/rpc/packet.js +0 -82
  174. package/lib/common/rpc/packet.js.map +0 -1
  175. package/lib/common/rpc/protocol-repository.d.ts +0 -32
  176. package/lib/common/rpc/protocol-repository.d.ts.map +0 -1
  177. package/lib/common/rpc/protocol-repository.js +0 -118
  178. package/lib/common/rpc/protocol-repository.js.map +0 -1
  179. package/lib/common/rpc/utils.d.ts +0 -2
  180. package/lib/common/rpc/utils.d.ts.map +0 -1
  181. package/lib/common/rpc/utils.js +0 -10
  182. package/lib/common/rpc/utils.js.map +0 -1
  183. package/lib/common/rpc-service/proxy/invoker.d.ts +0 -14
  184. package/lib/common/rpc-service/proxy/invoker.d.ts.map +0 -1
  185. package/lib/common/rpc-service/proxy/invoker.js +0 -34
  186. package/lib/common/rpc-service/proxy/invoker.js.map +0 -1
  187. package/lib/common/rpc-service/proxy/legacy.d.ts.map +0 -1
  188. package/lib/common/rpc-service/proxy/legacy.js.map +0 -1
  189. package/lib/common/rpc-service/proxy/registry.d.ts.map +0 -1
  190. package/lib/common/rpc-service/proxy/registry.js +0 -46
  191. package/lib/common/rpc-service/proxy/registry.js.map +0 -1
  192. package/lib/common/utils.d.ts.map +0 -1
  193. package/lib/common/utils.js +0 -57
  194. package/lib/common/utils.js.map +0 -1
  195. package/src/common/connection/drivers/utils.ts +0 -52
  196. package/src/common/rpc/packet.ts +0 -104
  197. package/src/common/rpc/protocol-repository.ts +0 -180
  198. package/src/common/rpc/utils.ts +0 -5
  199. package/src/common/rpc-service/proxy/invoker.ts +0 -45
  200. package/src/common/rpc-service/proxy/registry.ts +0 -56
  201. package/src/common/utils.ts +0 -80
@@ -9,8 +9,8 @@ interface IRPCResult {
9
9
  data: any;
10
10
  }
11
11
 
12
- export class ProxyLegacy extends ProxyBase<MessageConnection> {
13
- protected engine = 'legacy' as const;
12
+ export class ProxyJson extends ProxyBase<MessageConnection> {
13
+ protected engine = 'json' as const;
14
14
 
15
15
  protected bindMethods(methods: string[]): void {
16
16
  for (const method of methods) {
@@ -53,68 +53,58 @@ export class ProxyLegacy extends ProxyBase<MessageConnection> {
53
53
  }
54
54
  }
55
55
 
56
- public getInvokeProxy<T = any>(): T {
57
- return new Proxy(Object.create(null), {
58
- get: (target: any, p: PropertyKey) => {
59
- if (!target[p]) {
60
- target[p] = async (...args: any[]) => {
61
- await this.connectionPromise.promise;
62
-
63
- let isSingleArray = false;
64
- if (args.length === 1 && Array.isArray(args[0])) {
65
- isSingleArray = true;
66
- }
67
- const prop = p.toString();
68
-
69
- // 调用方法为 on 开头时,作为单项通知
70
- if (prop.startsWith('on')) {
71
- this.captureSendNotification(prop, args);
72
- if (isSingleArray) {
73
- this.connection.sendNotification(prop, [...args]);
74
- } else {
75
- this.connection.sendNotification(prop, ...args);
76
- }
77
- } else {
78
- // generate a unique requestId to associate request and requestResult
79
- const requestId = this.nextRequestId();
80
-
81
- let requestResult: Promise<any>;
82
-
83
- if (isSingleArray) {
84
- requestResult = this.connection.sendRequest(prop, [...args]) as Promise<any>;
85
- } else {
86
- requestResult = this.connection.sendRequest(prop, ...args) as Promise<any>;
87
- }
88
-
89
- this.captureSendRequest(requestId, prop, args);
90
-
91
- const result: IRPCResult = await requestResult;
92
-
93
- if (result.error) {
94
- const error = new Error(result.data.message);
95
- if (result.data.stack) {
96
- error.stack = result.data.stack;
97
- }
98
-
99
- this.captureSendRequestFail(requestId, prop, result.data);
100
- throw error;
101
- } else {
102
- this.captureSendRequestResult(requestId, prop, result.data);
103
- return result.data;
104
- }
105
- }
106
- };
56
+ async invoke(prop: string, ...args: any[]): Promise<any> {
57
+ await this.connectionPromise.promise;
58
+
59
+ let isSingleArray = false;
60
+ if (args.length === 1 && Array.isArray(args[0])) {
61
+ isSingleArray = true;
62
+ }
63
+
64
+ // 调用方法为 on 开头时,作为单项通知
65
+ if (prop.startsWith('on')) {
66
+ this.captureSendNotification(prop, args);
67
+ if (isSingleArray) {
68
+ this.connection.sendNotification(prop, [...args]);
69
+ } else {
70
+ this.connection.sendNotification(prop, ...args);
71
+ }
72
+ } else {
73
+ // generate a unique requestId to associate request and requestResult
74
+ const requestId = this.nextRequestId();
75
+
76
+ let requestResult: Promise<any>;
77
+
78
+ if (isSingleArray) {
79
+ requestResult = this.connection.sendRequest(prop, [...args]) as Promise<any>;
80
+ } else {
81
+ requestResult = this.connection.sendRequest(prop, ...args) as Promise<any>;
82
+ }
83
+
84
+ this.captureSendRequest(requestId, prop, args);
85
+
86
+ const result: IRPCResult = await requestResult;
87
+
88
+ if (result.error) {
89
+ const error = new Error(result.data.message);
90
+ if (result.data.stack) {
91
+ error.stack = result.data.stack;
107
92
  }
108
- return target[p];
109
- },
110
- });
93
+
94
+ this.captureSendRequestFail(requestId, prop, result.data);
95
+ throw error;
96
+ } else {
97
+ this.captureSendRequestResult(requestId, prop, result.data);
98
+ return result.data;
99
+ }
100
+ }
111
101
  }
112
102
 
113
103
  /**
114
104
  * 对于纯数组参数的情况,收到请求/通知后做展开操作
115
105
  * 因为在通信层会为每个 rpc 调用添加一个 CancellationToken 参数
116
106
  * 如果参数本身是数组, 在方法中如果使用 spread 运算符获取参数(...args),则会出现 [...args, MutableToken] 这种情况
117
- * 所以发送请求时将这类参数统一再用数组包了一层,形如 [[...args]], 参考 {@link ProxyLegacy.get get} 方法
107
+ * 所以发送请求时将这类参数统一再用数组包了一层,形如 [[...args]], 参考 {@link ProxyJson.get get} 方法
118
108
  * 此时接收到的数组类参数固定长度为 2,且最后一项一定是 MutableToken
119
109
  * @param args
120
110
  * @returns args
@@ -35,47 +35,35 @@ export class ProxySumi extends ProxyBase<SumiConnection> {
35
35
  }
36
36
  }
37
37
 
38
- public getInvokeProxy<T = any>(): T {
39
- return new Proxy(Object.create(null), {
40
- get: (target: any, p: PropertyKey) => {
41
- if (!target[p]) {
42
- target[p] = async (...args: any[]) => {
43
- await this.connectionPromise.promise;
44
- const prop = p.toString();
38
+ async invoke(prop: string, ...args: any[]): Promise<any> {
39
+ await this.connectionPromise.promise;
45
40
 
46
- // 调用方法为 on 开头时,作为单项通知
47
- if (prop.startsWith('on')) {
48
- this.captureSendNotification(prop, args);
49
- this.connection.sendNotification(prop, ...args);
50
- } else {
51
- // generate a unique requestId to associate request and requestResult
52
- const requestId = this.nextRequestId();
53
- this.captureSendRequest(requestId, prop, args);
54
- try {
55
- const result = await this.connection.sendRequest(prop, ...args);
56
- this.captureSendRequestResult(requestId, prop, result);
57
- return result;
58
- } catch (error) {
59
- this.captureSendRequestFail(requestId, prop, error);
60
- throw error;
61
- }
62
- }
63
- };
64
- }
65
- return target[p];
66
- },
67
- });
41
+ // 调用方法为 on 开头时,作为单项通知
42
+ if (prop.startsWith('on')) {
43
+ this.captureSendNotification(prop, args);
44
+ this.connection.sendNotification(prop, ...args);
45
+ } else {
46
+ // generate a unique requestId to associate request and requestResult
47
+ const requestId = this.nextRequestId();
48
+ this.captureSendRequest(requestId, prop, args);
49
+ try {
50
+ const result = await this.connection.sendRequest(prop, ...args);
51
+ this.captureSendRequestResult(requestId, prop, result);
52
+ return result;
53
+ } catch (error) {
54
+ this.captureSendRequestFail(requestId, prop, error);
55
+ throw error;
56
+ }
57
+ }
68
58
  }
69
59
 
70
60
  listen(connection: SumiConnection): void {
71
61
  super.listen(connection);
72
62
  connection.onRequestNotFound((method) => {
73
- if (!this.registry.has(method)) {
74
- const requestId = this.nextRequestId();
75
- this.captureOnRequest(requestId, method, []);
76
- this.captureOnRequestFail(requestId, method, METHOD_NOT_REGISTERED);
77
- throw METHOD_NOT_REGISTERED;
78
- }
63
+ const requestId = this.nextRequestId();
64
+ this.captureOnRequest(requestId, method, []);
65
+ this.captureOnRequestFail(requestId, method, METHOD_NOT_REGISTERED);
66
+ throw METHOD_NOT_REGISTERED;
79
67
  });
80
68
  }
81
69
  }
@@ -0,0 +1,125 @@
1
+ import { Emitter } from '@opensumi/ide-core-common';
2
+
3
+ import { MessageIO, TSumiProtocol, TSumiProtocolMethod } from '../rpc';
4
+ import { RPCServiceMethod } from '../types';
5
+
6
+ export function getServiceMethods(service: any): string[] {
7
+ let props: any[] = [];
8
+
9
+ if (/^\s*class/.test(service.constructor.toString())) {
10
+ let obj = service;
11
+ do {
12
+ props = props.concat(Object.getOwnPropertyNames(obj));
13
+ } while ((obj = Object.getPrototypeOf(obj)));
14
+ props = props.sort().filter((e, i, arr) => e !== arr[i + 1] && typeof service[e] === 'function');
15
+ } else {
16
+ for (const prop in service) {
17
+ if (service[prop] && typeof service[prop] === 'function') {
18
+ props.push(prop);
19
+ }
20
+ }
21
+ }
22
+
23
+ return props;
24
+ }
25
+
26
+ /**
27
+ * Store all executable services
28
+ */
29
+ export class ServiceRegistry {
30
+ protected emitter = new Emitter<string[]>();
31
+
32
+ private serviceMethodMap = new Map<PropertyKey, RPCServiceMethod>();
33
+
34
+ onServicesUpdate = this.emitter.event;
35
+
36
+ register(name: string, methodFn: RPCServiceMethod) {
37
+ this.serviceMethodMap.set(name, methodFn);
38
+ this.emitter.fire([name]);
39
+ }
40
+
41
+ registerService(
42
+ service: any,
43
+ options?: {
44
+ nameConverter?: (str: string) => string;
45
+ },
46
+ ) {
47
+ const serviceNames = [] as string[];
48
+ const { nameConverter } = options || {};
49
+ const methods = getServiceMethods(service);
50
+ for (const method of methods) {
51
+ let methodName = method;
52
+ if (nameConverter) {
53
+ methodName = nameConverter(method);
54
+ }
55
+
56
+ this.serviceMethodMap.set(methodName, service[method].bind(service));
57
+ serviceNames.push(methodName);
58
+ }
59
+
60
+ this.emitter.fire(serviceNames);
61
+ }
62
+
63
+ has(name: PropertyKey) {
64
+ return this.serviceMethodMap.has(name);
65
+ }
66
+
67
+ invoke(name: PropertyKey, ...args: any[]): any {
68
+ // here because we have checked the existence of the method
69
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70
+ return this.serviceMethodMap.get(name)!(...args);
71
+ }
72
+
73
+ methods() {
74
+ return Array.from(this.serviceMethodMap.keys());
75
+ }
76
+ }
77
+
78
+ export class ProtocolRegistry {
79
+ protected emitter = new Emitter<string[]>();
80
+
81
+ private protocolMap = new Map<PropertyKey, TSumiProtocolMethod>();
82
+
83
+ onProtocolUpdate = this.emitter.event;
84
+
85
+ addProtocol(
86
+ protocol: TSumiProtocol,
87
+ options?: {
88
+ nameConverter?: (str: string) => string;
89
+ },
90
+ ) {
91
+ const serviceNames = [] as string[];
92
+ const { nameConverter } = options || {};
93
+ const { methods } = protocol;
94
+
95
+ for (const proto of methods) {
96
+ let method = proto.method;
97
+ if (nameConverter) {
98
+ method = nameConverter(method);
99
+ }
100
+
101
+ this.protocolMap.set(method, {
102
+ ...proto,
103
+ method,
104
+ });
105
+ serviceNames.push(method);
106
+ }
107
+
108
+ this.emitter.fire(serviceNames);
109
+ }
110
+
111
+ applyTo(io: MessageIO) {
112
+ for (const protocol of this.protocolMap.values()) {
113
+ io.loadProtocolMethod(protocol);
114
+ }
115
+
116
+ this.onProtocolUpdate((methods) => {
117
+ for (const method of methods) {
118
+ const protocol = this.protocolMap.get(method);
119
+ if (protocol) {
120
+ io.loadProtocolMethod(protocol);
121
+ }
122
+ }
123
+ });
124
+ }
125
+ }
@@ -27,16 +27,16 @@ export class RPCServiceStub {
27
27
  new Proxy<T extends void ? RPCServiceStub : RPCServiceStub & T>(this as any, {
28
28
  // 调用方
29
29
  get: (target, prop: string) => {
30
- if (!target[prop]) {
31
- if (typeof prop === 'symbol') {
32
- return Promise.resolve();
33
- }
30
+ if (typeof prop === 'symbol') {
31
+ return Promise.resolve();
32
+ }
34
33
 
34
+ if (!target[prop]) {
35
35
  target[prop] = (...args: any[]) => this.broadcast(prop, ...args);
36
36
  return target[prop];
37
- } else {
38
- return target[prop];
39
37
  }
38
+
39
+ return target[prop];
40
40
  },
41
41
  });
42
42
  }
@@ -22,7 +22,7 @@ export interface IProxyIdentifier {
22
22
  countId: number;
23
23
  }
24
24
 
25
- export { ProxyIdentifier, IRPCProtocol } from './rpc/multiplexer';
25
+ export { IRPCProtocol, ProxyIdentifier };
26
26
 
27
27
  export function createExtHostContextProxyIdentifier<T>(serviceId: string): ProxyIdentifier<T> {
28
28
  const identifier = new ProxyIdentifier<T>(serviceId);
@@ -199,7 +199,7 @@ export class RPCProtocol implements IRPCProtocol {
199
199
  this._lastMessageId = 0;
200
200
  this.logger = logger || console;
201
201
  this.logger.error(
202
- "You are using the deprecated 'RPCProtocol' class. Please use the new 'SumiConnectionMultiplexer'",
202
+ "You are using the deprecated class: 'RPCProtocol'. Please use the new one: 'SumiConnectionMultiplexer'",
203
203
  );
204
204
  this._protocol.onMessage((msg) => this._receiveOneMessage(msg));
205
205
  }
@@ -0,0 +1,183 @@
1
+ import { IConnectionShape } from './connection/types';
2
+ import { ILogger } from './types';
3
+ import { ChannelMessage, WSChannel, parse, pongMessage } from './ws-channel';
4
+
5
+ export interface IPathHandler {
6
+ dispose: (channel: WSChannel, connectionId: string) => void;
7
+ handler: (channel: WSChannel, connectionId: string, params?: Record<string, string>) => void;
8
+ reconnect?: (channel: WSChannel, connectionId: string) => void;
9
+ connection?: any;
10
+ }
11
+
12
+ export class CommonChannelPathHandler {
13
+ private handlerMap: Map<string, IPathHandler[]> = new Map();
14
+ private paramsKey: Map<string, string> = new Map();
15
+
16
+ register(channelPath: string, handler: IPathHandler) {
17
+ const paramsIndex = channelPath.indexOf('/:');
18
+ const hasParams = paramsIndex >= 0;
19
+ let channelToken = channelPath;
20
+ if (hasParams) {
21
+ channelToken = channelPath.slice(0, paramsIndex);
22
+ this.paramsKey.set(channelToken, channelPath.slice(paramsIndex + 2));
23
+ }
24
+ if (!this.handlerMap.has(channelToken)) {
25
+ this.handlerMap.set(channelToken, []);
26
+ }
27
+ const handlerArr = this.handlerMap.get(channelToken) as IPathHandler[];
28
+ const handlerFn = handler.handler.bind(handler);
29
+ const setHandler = (channel: WSChannel, clientId: string, params: any) => {
30
+ handler.connection = channel;
31
+ handlerFn(channel, clientId, params);
32
+ };
33
+ handler.handler = setHandler;
34
+ handlerArr.push(handler);
35
+ this.handlerMap.set(channelToken, handlerArr);
36
+ }
37
+ getParams(channelPath: string, value: string): Record<string, string> {
38
+ const params = {} as Record<string, string>;
39
+ if (this.paramsKey.has(channelPath)) {
40
+ const key = this.paramsKey.get(channelPath);
41
+ if (key) {
42
+ params[key] = value;
43
+ }
44
+ }
45
+ return params;
46
+ }
47
+ removeHandler(channelPath: string, handler: IPathHandler) {
48
+ const paramsIndex = channelPath.indexOf(':');
49
+ const hasParams = paramsIndex >= 0;
50
+ let channelToken = channelPath;
51
+ if (hasParams) {
52
+ channelToken = channelPath.slice(0, paramsIndex);
53
+ }
54
+ const handlerArr = this.handlerMap.get(channelToken) || [];
55
+ const removeIndex = handlerArr.indexOf(handler);
56
+ if (removeIndex !== -1) {
57
+ handlerArr.splice(removeIndex, 1);
58
+ }
59
+ this.handlerMap.set(channelPath, handlerArr);
60
+ }
61
+ get(channelPath: string) {
62
+ return this.handlerMap.get(channelPath);
63
+ }
64
+ disposeConnectionClientId(channel: any, clientId: string) {
65
+ this.handlerMap.forEach((handlerArr: IPathHandler[]) => {
66
+ handlerArr.forEach((handler: IPathHandler) => {
67
+ handler.dispose(channel, clientId);
68
+ });
69
+ });
70
+ }
71
+ dispatchChannelOpen(path: string, channel: WSChannel, clientId: string) {
72
+ // 根据 path 拿到注册的 handler
73
+ let handlerArr = this.get(path);
74
+ let params: Record<string, string> | undefined;
75
+ // 尝试通过父路径查找处理函数,如server/:id方式注册的handler
76
+ if (!handlerArr) {
77
+ const slashIndex = path.indexOf('/');
78
+ const hasSlash = slashIndex >= 0;
79
+ if (hasSlash) {
80
+ handlerArr = this.get(path.slice(0, slashIndex));
81
+ params = this.getParams(path.slice(0, slashIndex), path.slice(slashIndex + 1));
82
+ }
83
+ }
84
+
85
+ if (handlerArr) {
86
+ for (let i = 0, len = handlerArr.length; i < len; i++) {
87
+ const handler = handlerArr[i];
88
+ handler.handler(channel, clientId, params);
89
+ }
90
+ }
91
+ }
92
+
93
+ getAll() {
94
+ return Array.from(this.handlerMap.values());
95
+ }
96
+ }
97
+
98
+ export const commonChannelPathHandler = new CommonChannelPathHandler();
99
+
100
+ export abstract class BaseCommonChannelHandler {
101
+ protected channelMap: Map<string, WSChannel> = new Map();
102
+
103
+ heartbeatTimer: NodeJS.Timeout | null = null;
104
+
105
+ constructor(public handlerId: string, protected logger: ILogger = console) {}
106
+
107
+ abstract doHeartbeat(connection: any): void;
108
+
109
+ private heartbeat(connection: any) {
110
+ const timer = global.setTimeout(() => {
111
+ this.doHeartbeat(connection);
112
+ this.heartbeat(connection);
113
+ }, 5000);
114
+
115
+ if (this.heartbeatTimer) {
116
+ clearTimeout(this.heartbeatTimer);
117
+ }
118
+
119
+ this.heartbeatTimer = timer;
120
+ }
121
+
122
+ receiveConnection(connection: IConnectionShape<Uint8Array>) {
123
+ let clientId: string;
124
+ this.heartbeat(connection);
125
+
126
+ connection.onMessage((data: Uint8Array) => {
127
+ let msg: ChannelMessage;
128
+ try {
129
+ msg = parse(data);
130
+
131
+ switch (msg.kind) {
132
+ case 'ping':
133
+ connection.send(pongMessage);
134
+ break;
135
+ case 'open': {
136
+ const { id, path } = msg;
137
+ clientId = msg.clientId;
138
+ this.logger.log(`open a new connection channel ${clientId} with path ${path}`);
139
+
140
+ const channel = new WSChannel(connection, { id, logger: this.logger });
141
+ this.channelMap.set(id, channel);
142
+
143
+ commonChannelPathHandler.dispatchChannelOpen(path, channel, clientId);
144
+ channel.serverReady();
145
+ break;
146
+ }
147
+ default: {
148
+ const { id } = msg;
149
+ const channel = this.channelMap.get(id);
150
+ if (channel) {
151
+ channel.dispatchChannelMessage(msg);
152
+ } else {
153
+ this.logger.warn(`channel ${id} is not found`);
154
+ }
155
+ }
156
+ }
157
+ } catch (e) {
158
+ this.logger.error('handle connection message error', e);
159
+ }
160
+ });
161
+
162
+ connection.onceClose(() => {
163
+ commonChannelPathHandler.disposeConnectionClientId(connection, clientId);
164
+
165
+ Array.from(this.channelMap.values())
166
+ .filter((channel) => channel.id.toString().indexOf(clientId) !== -1)
167
+ .forEach((channel) => {
168
+ channel.close(1, 'close');
169
+ channel.dispose();
170
+ this.channelMap.delete(channel.id);
171
+ this.logger.log(`Remove connection channel ${channel.id}`);
172
+ });
173
+ });
174
+ }
175
+
176
+ dispose() {
177
+ if (this.heartbeatTimer) {
178
+ clearTimeout(this.heartbeatTimer);
179
+ }
180
+ }
181
+ }
182
+
183
+ export const RPCServiceChannelPath = 'RPCService';
@@ -15,3 +15,16 @@ export enum ServiceType {
15
15
  export interface IBench {
16
16
  registerService: (service: string) => void;
17
17
  }
18
+
19
+ export interface WSCloseInfo {
20
+ channelPath: string;
21
+ closeEvent: { code: number; reason: string };
22
+ connectInfo: ConnectionInfo;
23
+ }
24
+
25
+ export interface ConnectionInfo {
26
+ type: string;
27
+ downlink: number;
28
+ uplink: number;
29
+ rtt: number;
30
+ }
@@ -1,16 +1,12 @@
1
- import type net from 'net';
2
-
3
1
  import { Type } from '@furyjs/fury';
4
- import type WebSocket from 'ws';
5
2
 
6
3
  import { EventEmitter } from '@opensumi/events';
7
4
  import { DisposableCollection } from '@opensumi/ide-core-common';
8
5
 
9
- import { NetSocketConnection, WSWebSocketConnection } from './connection';
10
6
  import { IConnectionShape } from './connection/types';
11
- import { oneOf } from './fury-extends/one-of';
7
+ import { oneOf7 } from './fury-extends/one-of';
12
8
  import { createWebSocketConnection } from './message';
13
- import { SumiConnection, ISumiConnectionOptions } from './rpc/connection';
9
+ import { ISumiConnectionOptions, SumiConnection } from './rpc/connection';
14
10
  import { ILogger } from './types';
15
11
 
16
12
  /**
@@ -103,7 +99,6 @@ export class WSChannel {
103
99
  }>();
104
100
 
105
101
  public id: string;
106
- public LOG_TAG = '[WSChannel]';
107
102
 
108
103
  public channelPath: string;
109
104
 
@@ -129,16 +124,6 @@ export class WSChannel {
129
124
  return channel;
130
125
  }
131
126
 
132
- static forWebSocket(socket: WebSocket, options: IWSChannelCreateOptions) {
133
- const wsConnection = new WSWebSocketConnection(socket);
134
- return WSChannel.forClient(wsConnection, options);
135
- }
136
-
137
- static forNetSocket(socket: net.Socket, options: IWSChannelCreateOptions) {
138
- const wsConnection = new NetSocketConnection(socket);
139
- return WSChannel.forClient(wsConnection, options);
140
- }
141
-
142
127
  constructor(public connection: IConnectionShape<Uint8Array>, options: IWSChannelCreateOptions) {
143
128
  const { id, logger } = options;
144
129
  this.id = id;
@@ -146,8 +131,6 @@ export class WSChannel {
146
131
  if (logger) {
147
132
  this.logger = logger;
148
133
  }
149
-
150
- this.LOG_TAG = `[WSChannel] [id:${id}]`;
151
134
  }
152
135
 
153
136
  onMessage(cb: (data: string) => any) {
@@ -236,9 +219,9 @@ export class WSChannel {
236
219
 
237
220
  createConnection() {
238
221
  return {
239
- onceClose: (cb) => this.onceClose(cb),
240
- onMessage: (cb) => this.onBinary(cb),
241
- send: (data) => {
222
+ onceClose: (cb: (code: number, reason: string) => void) => this.onceClose(cb),
223
+ onMessage: (cb: (data: Uint8Array) => any) => this.onBinary(cb),
224
+ send: (data: Uint8Array) => {
242
225
  this.sendBinary(data);
243
226
  },
244
227
  dispose() {},
@@ -291,7 +274,7 @@ export const CloseProtocol = Type.object('close', {
291
274
  reason: Type.string(),
292
275
  });
293
276
 
294
- const serializer = oneOf([
277
+ const serializer = oneOf7([
295
278
  PingProtocol,
296
279
  PongProtocol,
297
280
  OpenProtocol,
@@ -308,3 +291,18 @@ export function stringify(obj: ChannelMessage): Uint8Array {
308
291
  export function parse(input: Uint8Array): ChannelMessage {
309
292
  return serializer.deserialize(input) as any;
310
293
  }
294
+
295
+ const _pingMessage: PingMessage = {
296
+ kind: 'ping',
297
+ id: '',
298
+ clientId: '',
299
+ };
300
+
301
+ const _pongMessage: PongMessage = {
302
+ kind: 'pong',
303
+ id: '',
304
+ clientId: '',
305
+ };
306
+
307
+ export const pingMessage = stringify(_pingMessage);
308
+ export const pongMessage = stringify(_pongMessage);
@@ -0,0 +1,26 @@
1
+ import net from 'net';
2
+
3
+ import { ILogger } from '../common';
4
+ import { NetSocketConnection } from '../common/connection';
5
+ import { BaseCommonChannelHandler } from '../common/server-handler';
6
+
7
+ /**
8
+ * Channel Handler for electron backend
9
+ */
10
+ export class ElectronChannelHandler extends BaseCommonChannelHandler {
11
+ constructor(private server: net.Server, logger: ILogger = console) {
12
+ super('electron-channel-handler', logger);
13
+ }
14
+
15
+ doHeartbeat(connection: any): void {
16
+ // do nothing
17
+ }
18
+
19
+ listen() {
20
+ this.logger.log('init Common Channel Handler');
21
+ this.server.on('connection', (connection: net.Socket) => {
22
+ const netConnection = new NetSocketConnection(connection);
23
+ this.receiveConnection(netConnection);
24
+ });
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ export * from './channel-handler';