@opensumi/ide-connection 2.21.9-rc-1671176957.0 → 2.21.9

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/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "@opensumi/ide-connection",
3
- "version": "2.21.9-rc-1671176957.0",
3
+ "version": "2.21.9",
4
4
  "files": [
5
- "lib",
6
- "src"
5
+ "lib"
7
6
  ],
8
7
  "license": "MIT",
9
8
  "main": "lib/index.js",
@@ -17,15 +16,15 @@
17
16
  "url": "git@github.com:opensumi/core.git"
18
17
  },
19
18
  "dependencies": {
20
- "@opensumi/ide-core-common": "2.21.9-rc-1671176957.0",
19
+ "@opensumi/ide-core-common": "2.21.9",
21
20
  "@opensumi/vscode-jsonrpc": "^8.0.0-next.2",
22
21
  "path-match": "^1.2.4",
23
22
  "ws": "^8.9.0"
24
23
  },
25
24
  "devDependencies": {
26
- "@opensumi/ide-components": "2.21.9-rc-1671176957.0",
25
+ "@opensumi/ide-components": "2.21.9",
27
26
  "@opensumi/ide-dev-tool": "^1.3.1",
28
27
  "mock-socket": "^9.0.2"
29
28
  },
30
- "gitHead": "81fe16f43c329c633bd8b2eeb737363c8f4e7110"
29
+ "gitHead": "6038a6faa5ad85bfb5acb721c1d39190fe674555"
31
30
  }
@@ -1 +0,0 @@
1
- export * from './ws-channel-handler';
@@ -1,124 +0,0 @@
1
- import ReconnectingWebSocket from 'reconnecting-websocket';
2
-
3
- import { uuid } from '@opensumi/ide-core-common';
4
- import { IReporterService, REPORT_NAME, UrlProvider } from '@opensumi/ide-core-common';
5
-
6
- import { stringify, parse } from '../common/utils';
7
- import { WSChannel, MessageString } from '../common/ws-channel';
8
-
9
- // 前台链接管理类
10
- export class WSChannelHandler {
11
- public connection: WebSocket;
12
- private channelMap: Map<number | string, WSChannel> = new Map();
13
- private logger = console;
14
- public clientId: string;
15
- private heartbeatMessageTimer: NodeJS.Timer | null;
16
- private reporterService: IReporterService;
17
-
18
- constructor(public wsPath: UrlProvider, logger: any, public protocols?: string[], clientId?: string) {
19
- this.logger = logger || this.logger;
20
- this.clientId = clientId || `CLIENT_ID_${uuid()}`;
21
- this.connection = new ReconnectingWebSocket(wsPath, protocols, {}) as WebSocket; // new WebSocket(wsPath, protocols);
22
- }
23
- // 为解决建立连接之后,替换成可落盘的 logger
24
- replaceLogger(logger: any) {
25
- if (logger) {
26
- this.logger = logger;
27
- }
28
- }
29
- setReporter(reporterService: IReporterService) {
30
- this.reporterService = reporterService;
31
- }
32
- private clientMessage() {
33
- const clientMsg: MessageString = stringify({
34
- kind: 'client',
35
- clientId: this.clientId,
36
- });
37
- this.connection.send(clientMsg);
38
- }
39
- private heartbeatMessage() {
40
- if (this.heartbeatMessageTimer) {
41
- clearTimeout(this.heartbeatMessageTimer);
42
- }
43
- this.heartbeatMessageTimer = global.setTimeout(() => {
44
- const msg = stringify({
45
- kind: 'heartbeat',
46
- clientId: this.clientId,
47
- });
48
- this.connection.send(msg);
49
- this.heartbeatMessage();
50
- }, 5000);
51
- }
52
-
53
- public async initHandler() {
54
- this.connection.onmessage = (e) => {
55
- // 一个心跳周期内如果有收到消息,则不需要再发送心跳
56
- this.heartbeatMessage();
57
-
58
- const msg = parse(e.data);
59
-
60
- if (msg.id) {
61
- const channel = this.channelMap.get(msg.id);
62
- if (channel) {
63
- if (msg.kind === 'data' && !(channel as any).fireMessage) {
64
- // 要求前端发送初始化消息,但后端最先发送消息时,前端并未准备好
65
- this.logger.error('channel not ready!', msg);
66
- }
67
- channel.handleMessage(msg);
68
- } else {
69
- this.logger.warn(`channel ${msg.id} not found`);
70
- }
71
- }
72
- };
73
- await new Promise((resolve) => {
74
- this.connection.addEventListener('open', () => {
75
- this.clientMessage();
76
- this.heartbeatMessage();
77
- resolve(undefined);
78
- // 重连 channel
79
- if (this.channelMap.size) {
80
- this.channelMap.forEach((channel) => {
81
- channel.onOpen(() => {
82
- this.reporterService && this.reporterService.point(REPORT_NAME.CHANNEL_RECONNECT);
83
- this.logger && this.logger.log(`channel reconnect ${this.clientId}:${channel.channelPath}`);
84
- });
85
- channel.open(channel.channelPath);
86
-
87
- // 针对前端需要重新设置下后台状态的情况
88
- if (channel.fireReOpen) {
89
- channel.fireReOpen();
90
- }
91
- });
92
- }
93
- });
94
- });
95
- }
96
- private getChannelSend = (connection) => (content: string) => {
97
- connection.send(content, (err: Error) => {
98
- if (err) {
99
- this.logger.warn(err);
100
- }
101
- });
102
- };
103
- public async openChannel(channelPath: string) {
104
- const channelSend = this.getChannelSend(this.connection);
105
- const channelId = `${this.clientId}:${channelPath}`;
106
- const channel = new WSChannel(channelSend, channelId);
107
- this.channelMap.set(channel.id, channel);
108
-
109
- await new Promise((resolve) => {
110
- channel.onOpen(() => {
111
- resolve(undefined);
112
- });
113
- channel.open(channelPath);
114
- });
115
-
116
- return channel;
117
- }
118
-
119
- public dispose() {
120
- if (this.heartbeatMessageTimer) {
121
- clearTimeout(this.heartbeatMessageTimer);
122
- }
123
- }
124
- }
@@ -1,199 +0,0 @@
1
- import { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection';
2
-
3
- import { RPCProxy, NOTREGISTERMETHOD } from './proxy';
4
-
5
- export type RPCServiceMethod = (...args: any[]) => any;
6
- export type ServiceProxy = any;
7
-
8
- export enum ServiceType {
9
- Service,
10
- Stub,
11
- }
12
-
13
- export class RPCServiceStub {
14
- constructor(private serviceName: string, private center, private type: ServiceType) {
15
- if (this.type === ServiceType.Service) {
16
- this.center.registerService(serviceName, this.type);
17
- }
18
- }
19
-
20
- async ready() {
21
- return this.center.when();
22
- }
23
- getNotificationName(name: string) {
24
- return `on:${this.serviceName}:${name}`;
25
- }
26
- getRequestName(name: string) {
27
- return `${this.serviceName}:${name}`;
28
- }
29
- // 服务方
30
- on(name: string, method: RPCServiceMethod) {
31
- this.onRequest(name, method);
32
- }
33
- getServiceMethod(service): string[] {
34
- let props: any[] = [];
35
-
36
- if (/^\s*class/.test(service.constructor.toString())) {
37
- let obj = service;
38
- do {
39
- props = props.concat(Object.getOwnPropertyNames(obj));
40
- } while ((obj = Object.getPrototypeOf(obj)));
41
- props = props.sort().filter((e, i, arr) => e !== arr[i + 1] && typeof service[e] === 'function');
42
- } else {
43
- for (const prop in service) {
44
- if (service[prop] && typeof service[prop] === 'function') {
45
- props.push(prop);
46
- }
47
- }
48
- }
49
-
50
- return props;
51
- }
52
- onRequestService(service: any) {
53
- const methods = this.getServiceMethod(service);
54
- for (const method of methods) {
55
- this.onRequest(method, service[method].bind(service));
56
- }
57
- }
58
-
59
- onRequest(name: string, method: RPCServiceMethod) {
60
- this.center.onRequest(this.getMethodName(name), method);
61
- }
62
- broadcast(name: string, ...args) {
63
- return this.center.broadcast(this.getMethodName(name), ...args);
64
- }
65
-
66
- getMethodName(name: string) {
67
- return name.startsWith('on') ? this.getNotificationName(name) : this.getRequestName(name);
68
- }
69
- getProxy = <T>() =>
70
- new Proxy<RPCServiceStub & T>(this as any, {
71
- // 调用方
72
- get: (target, prop: string) => {
73
- if (!target[prop]) {
74
- if (typeof prop === 'symbol') {
75
- return Promise.resolve();
76
- } else {
77
- return (...args) =>
78
- this.ready().then(() => {
79
- const name = this.getMethodName(prop);
80
- return Promise.all(this.center.serviceProxy.map((proxy) => proxy[name](...args)))
81
- .then((result) => result.filter((res) => res !== NOTREGISTERMETHOD))
82
- .then((result) => (result.length === 1 ? result[0] : result));
83
- });
84
- }
85
- } else {
86
- return target[prop];
87
- }
88
- },
89
- });
90
- }
91
-
92
- export function initRPCService<T = void>(center: RPCServiceCenter) {
93
- return {
94
- createRPCService: (name: string, service?: any) => {
95
- const proxy = new RPCServiceStub(name, center, ServiceType.Service).getProxy<T>();
96
- if (service) {
97
- proxy.onRequestService(service);
98
- }
99
-
100
- return proxy;
101
- },
102
- getRPCService: (name: string) => new RPCServiceStub(name, center, ServiceType.Stub).getProxy<T>(),
103
- };
104
- }
105
-
106
- interface IBench {
107
- registerService: (service: string) => void;
108
- }
109
-
110
- export interface RPCMessageConnection extends MessageConnection {
111
- uid?: string;
112
- writer?: any;
113
- reader?: any;
114
- }
115
-
116
- export function createRPCService<T = void>(name: string, center: RPCServiceCenter): any {
117
- return new RPCServiceStub(name, center, ServiceType.Service).getProxy<T>();
118
- }
119
-
120
- export function getRPCService<T = void>(name: string, center: RPCServiceCenter): any {
121
- return new RPCServiceStub(name, center, ServiceType.Stub).getProxy<T>();
122
- }
123
-
124
- export class RPCServiceCenter {
125
- public uid: string;
126
- public rpcProxy: RPCProxy[] = [];
127
- public serviceProxy: ServiceProxy[] = [];
128
- private connection: Array<MessageConnection> = [];
129
- private serviceMethodMap = { client: undefined };
130
-
131
- private createService: string[] = [];
132
- private getService: string[] = [];
133
-
134
- private connectionPromise: Promise<void>;
135
- private connectionPromiseResolve: () => void;
136
- private logger;
137
-
138
- constructor(private bench?: IBench, logger?: any) {
139
- this.uid = 'RPCServiceCenter:' + process.pid;
140
- this.connectionPromise = new Promise((resolve) => {
141
- this.connectionPromiseResolve = resolve;
142
- });
143
- this.logger = logger || console;
144
- }
145
-
146
- registerService(serviceName: string, type: ServiceType): void {
147
- if (type === ServiceType.Service) {
148
- this.createService.push(serviceName);
149
- if (this.bench) {
150
- this.bench.registerService(serviceName);
151
- }
152
- } else if (type === ServiceType.Stub) {
153
- this.getService.push(serviceName);
154
- }
155
- }
156
-
157
- when() {
158
- return this.connectionPromise;
159
- }
160
-
161
- setConnection(connection: MessageConnection) {
162
- if (!this.connection.length) {
163
- this.connectionPromiseResolve();
164
- }
165
- this.connection.push(connection);
166
-
167
- const rpcProxy = new RPCProxy(this.serviceMethodMap, this.logger);
168
- rpcProxy.listen(connection);
169
- this.rpcProxy.push(rpcProxy);
170
-
171
- const serviceProxy = rpcProxy.createProxy();
172
- this.serviceProxy.push(serviceProxy);
173
- }
174
-
175
- removeConnection(connection: MessageConnection) {
176
- const removeIndex = this.connection.indexOf(connection);
177
- if (removeIndex !== -1) {
178
- this.connection.splice(removeIndex, 1);
179
- this.rpcProxy.splice(removeIndex, 1);
180
- this.serviceProxy.splice(removeIndex, 1);
181
- }
182
-
183
- return removeIndex !== -1;
184
- }
185
- onRequest(name, method: RPCServiceMethod) {
186
- if (!this.connection.length) {
187
- this.serviceMethodMap[name] = method;
188
- } else {
189
- this.rpcProxy.forEach((proxy) => {
190
- proxy.listenService({ [name]: method });
191
- });
192
- }
193
- }
194
- broadcast(name, ...args): Promise<any> {
195
- return Promise.all(this.serviceProxy.map((proxy) => proxy[name](...args)) as Promise<any>[])
196
- .then((result) => result.filter((res) => res !== NOTREGISTERMETHOD))
197
- .then((result) => (result.length === 1 ? result[0] : result));
198
- }
199
- }
@@ -1,6 +0,0 @@
1
- export * from './message';
2
- export * from './proxy';
3
- export * from './rpcProtocol';
4
- export * from './utils';
5
- export * from './ws-channel';
6
- export * from './connect';
@@ -1,93 +0,0 @@
1
- import {
2
- AbstractMessageReader,
3
- AbstractMessageWriter,
4
- createMessageConnection,
5
- } from '@opensumi/vscode-jsonrpc/lib/common/api';
6
- import { Disposable } from '@opensumi/vscode-jsonrpc/lib/common/disposable';
7
- import { MessageReader, DataCallback } from '@opensumi/vscode-jsonrpc/lib/common/messageReader';
8
- import { MessageWriter } from '@opensumi/vscode-jsonrpc/lib/common/messageWriter';
9
- /**
10
- * FIXME: 由于 `createMessageConnection` 方法隐式依赖了 `@opensumi/vscode-jsonrpc/lib/browser/main` 或 `@opensumi/vscode-jsonrpc/lib/node/main`
11
- * 的 `RIL.install()` 初始化代码,而 `browser/main` 中仅支持浏览器使用,
12
- * 故需要保证提前引入或执行一次 `@opensumi/vscode-jsonrpc/lib/node/main` 代码才能保证逻辑正常执行
13
- */
14
- import '@opensumi/vscode-jsonrpc/lib/node/main';
15
-
16
- export class WebSocketMessageReader extends AbstractMessageReader implements MessageReader {
17
- protected state: 'initial' | 'listening' | 'closed' = 'initial';
18
- protected callback: DataCallback | undefined;
19
- protected events: { message?: any; error?: any }[] = [];
20
-
21
- constructor(protected readonly socket) {
22
- super();
23
- if (this.socket.onMessage) {
24
- this.socket.onMessage((message) => {
25
- this.readMessage(message);
26
- });
27
- } else if (this.socket.onmessage) {
28
- this.socket.onmessage = (message) => {
29
- this.readMessage(message);
30
- };
31
- } else if (this.socket.on) {
32
- this.socket.on('message', (message) => {
33
- this.readMessage(message);
34
- });
35
- }
36
- }
37
-
38
- public listen(callback: DataCallback): Disposable {
39
- if (this.state === 'initial') {
40
- this.state = 'listening';
41
- this.callback = callback;
42
- }
43
-
44
- while (this.events.length !== 0) {
45
- const event = this.events.pop()!;
46
- if (event.message) {
47
- this.readMessage(event.message);
48
- }
49
- }
50
-
51
- return Disposable.create(() => {
52
- this.state = 'closed';
53
- this.callback = undefined;
54
- this.events = [];
55
- });
56
- }
57
-
58
- protected readMessage(message) {
59
- if (this.state === 'initial') {
60
- this.events.splice(0, 0, { message });
61
- } else if (this.state === 'listening') {
62
- const data = JSON.parse(message);
63
- this.callback!(data);
64
- }
65
- }
66
- }
67
-
68
- export class WebSocketMessageWriter extends AbstractMessageWriter implements MessageWriter {
69
- constructor(protected readonly socket) {
70
- super();
71
- }
72
-
73
- write(msg): Promise<void> {
74
- try {
75
- const content = JSON.stringify(msg);
76
- this.socket.send(content);
77
- return Promise.resolve();
78
- } catch (e) {
79
- return Promise.reject(e);
80
- }
81
- }
82
-
83
- public end(): void {}
84
- }
85
-
86
- /**
87
- * 给服务端的 WebSocket 及 Browser 端的 WebSocket 实例共用的方法
88
- * @param socket
89
- * @returns
90
- */
91
- export function createWebSocketConnection(socket: any) {
92
- return createMessageConnection(new WebSocketMessageReader(socket), new WebSocketMessageWriter(socket));
93
- }