@opensumi/ide-connection 2.27.3-rc-1706687185.0 → 2.27.3-rc-1708222409.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.
- package/lib/browser/ws-channel-handler.d.ts.map +1 -1
- package/lib/browser/ws-channel-handler.js +2 -6
- package/lib/browser/ws-channel-handler.js.map +1 -1
- package/lib/common/{connection → buffers}/buffers.d.ts +2 -1
- package/lib/common/buffers/buffers.d.ts.map +1 -0
- package/lib/common/{connection → buffers}/buffers.js +21 -3
- package/lib/common/buffers/buffers.js.map +1 -0
- package/lib/common/connection/drivers/base.d.ts +2 -2
- package/lib/common/connection/drivers/base.d.ts.map +1 -1
- package/lib/common/connection/drivers/base.js +0 -4
- package/lib/common/connection/drivers/base.js.map +1 -1
- package/lib/common/connection/drivers/frame-decoder.d.ts +34 -0
- package/lib/common/connection/drivers/frame-decoder.d.ts.map +1 -0
- package/lib/common/connection/drivers/frame-decoder.js +147 -0
- package/lib/common/connection/drivers/frame-decoder.js.map +1 -0
- package/lib/common/connection/drivers/{empty.d.ts → message-port.d.ts} +5 -2
- package/lib/common/connection/drivers/message-port.d.ts.map +1 -0
- package/lib/common/connection/drivers/message-port.js +41 -0
- package/lib/common/connection/drivers/message-port.js.map +1 -0
- package/lib/common/connection/drivers/node-message-port.d.ts +1 -0
- package/lib/common/connection/drivers/node-message-port.d.ts.map +1 -1
- package/lib/common/connection/drivers/node-message-port.js +3 -0
- package/lib/common/connection/drivers/node-message-port.js.map +1 -1
- package/lib/common/connection/drivers/reconnecting-websocket.d.ts +1 -0
- package/lib/common/connection/drivers/reconnecting-websocket.d.ts.map +1 -1
- package/lib/common/connection/drivers/reconnecting-websocket.js +3 -0
- package/lib/common/connection/drivers/reconnecting-websocket.js.map +1 -1
- package/lib/common/connection/drivers/simple.d.ts +17 -0
- package/lib/common/connection/drivers/simple.d.ts.map +1 -0
- package/lib/common/connection/drivers/simple.js +32 -0
- package/lib/common/connection/drivers/simple.js.map +1 -0
- package/lib/common/connection/drivers/socket.d.ts +4 -2
- package/lib/common/connection/drivers/socket.d.ts.map +1 -1
- package/lib/common/connection/drivers/socket.js +10 -7
- package/lib/common/connection/drivers/socket.js.map +1 -1
- package/lib/common/connection/drivers/ws-websocket.d.ts +2 -0
- package/lib/common/connection/drivers/ws-websocket.d.ts.map +1 -1
- package/lib/common/connection/drivers/ws-websocket.js +6 -0
- package/lib/common/connection/drivers/ws-websocket.js.map +1 -1
- package/lib/common/connection/types.d.ts +1 -1
- package/lib/common/connection/types.d.ts.map +1 -1
- package/lib/common/ext-rpc-protocol.d.ts +7 -21
- package/lib/common/ext-rpc-protocol.d.ts.map +1 -1
- package/lib/common/ext-rpc-protocol.js +13 -33
- package/lib/common/ext-rpc-protocol.js.map +1 -1
- package/lib/common/fury-extends/any.d.ts +22 -0
- package/lib/common/fury-extends/any.d.ts.map +1 -0
- package/lib/common/fury-extends/any.js +143 -0
- package/lib/common/fury-extends/any.js.map +1 -0
- package/lib/common/fury-extends/one-of.d.ts +14 -0
- package/lib/common/fury-extends/one-of.d.ts.map +1 -0
- package/lib/common/fury-extends/one-of.js +50 -0
- package/lib/common/fury-extends/one-of.js.map +1 -0
- package/lib/common/fury-extends/shared.d.ts +142 -0
- package/lib/common/fury-extends/shared.d.ts.map +1 -0
- package/lib/common/fury-extends/shared.js +17 -0
- package/lib/common/fury-extends/shared.js.map +1 -0
- package/lib/common/index.d.ts +2 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +2 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/protocols/common-server.d.ts +3 -0
- package/lib/common/protocols/common-server.d.ts.map +1 -0
- package/lib/common/protocols/common-server.js +18 -0
- package/lib/common/protocols/common-server.js.map +1 -0
- package/lib/common/protocols/common.d.ts +24 -0
- package/lib/common/protocols/common.d.ts.map +1 -0
- package/lib/common/protocols/common.js +12 -0
- package/lib/common/protocols/common.js.map +1 -0
- package/lib/common/rpc/connection.d.ts +44 -0
- package/lib/common/rpc/connection.d.ts.map +1 -0
- package/lib/common/rpc/connection.js +256 -0
- package/lib/common/rpc/connection.js.map +1 -0
- package/lib/common/rpc/errors.d.ts +4 -0
- package/lib/common/rpc/errors.d.ts.map +1 -0
- package/lib/common/rpc/errors.js +10 -0
- package/lib/common/rpc/errors.js.map +1 -0
- package/lib/common/rpc/index.d.ts +3 -0
- package/lib/common/rpc/index.d.ts.map +1 -0
- package/lib/common/rpc/index.js +6 -0
- package/lib/common/rpc/index.js.map +1 -0
- package/lib/common/rpc/multiplexer.d.ts +28 -0
- package/lib/common/rpc/multiplexer.d.ts.map +1 -0
- package/lib/common/rpc/multiplexer.js +82 -0
- package/lib/common/rpc/multiplexer.js.map +1 -0
- package/lib/common/rpc/packet.d.ts +65 -0
- package/lib/common/rpc/packet.d.ts.map +1 -0
- package/lib/common/rpc/packet.js +82 -0
- package/lib/common/rpc/packet.js.map +1 -0
- package/lib/common/rpc/protocol-repository.d.ts +32 -0
- package/lib/common/rpc/protocol-repository.d.ts.map +1 -0
- package/lib/common/rpc/protocol-repository.js +118 -0
- package/lib/common/rpc/protocol-repository.js.map +1 -0
- package/lib/common/rpc/types.d.ts +13 -0
- package/lib/common/rpc/types.d.ts.map +1 -0
- package/lib/common/rpc/types.js +3 -0
- package/lib/common/rpc/types.js.map +1 -0
- package/lib/common/rpc/utils.d.ts +2 -0
- package/lib/common/rpc/utils.d.ts.map +1 -0
- package/lib/common/rpc/utils.js +10 -0
- package/lib/common/rpc/utils.js.map +1 -0
- package/lib/common/rpc-service/center.d.ts +12 -5
- package/lib/common/rpc-service/center.d.ts.map +1 -1
- package/lib/common/rpc-service/center.js +47 -42
- package/lib/common/rpc-service/center.js.map +1 -1
- package/lib/common/rpc-service/index.d.ts +6 -0
- package/lib/common/rpc-service/index.d.ts.map +1 -1
- package/lib/common/rpc-service/index.js +7 -0
- package/lib/common/rpc-service/index.js.map +1 -1
- package/lib/common/rpc-service/proxy/base.d.ts +32 -0
- package/lib/common/rpc-service/proxy/base.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/base.js +93 -0
- package/lib/common/rpc-service/proxy/base.js.map +1 -0
- package/lib/common/rpc-service/proxy/index.d.ts +5 -0
- package/lib/common/rpc-service/proxy/index.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/index.js +8 -0
- package/lib/common/rpc-service/proxy/index.js.map +1 -0
- package/lib/common/rpc-service/proxy/invoker.d.ts +14 -0
- package/lib/common/rpc-service/proxy/invoker.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/invoker.js +34 -0
- package/lib/common/rpc-service/proxy/invoker.js.map +1 -0
- package/lib/common/{proxy → rpc-service/proxy}/legacy.d.ts +3 -7
- package/lib/common/rpc-service/proxy/legacy.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/legacy.js +136 -0
- package/lib/common/rpc-service/proxy/legacy.js.map +1 -0
- package/lib/common/rpc-service/proxy/registry.d.ts +18 -0
- package/lib/common/rpc-service/proxy/registry.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/registry.js +46 -0
- package/lib/common/rpc-service/proxy/registry.js.map +1 -0
- package/lib/common/rpc-service/proxy/sumi.d.ts +9 -0
- package/lib/common/rpc-service/proxy/sumi.d.ts.map +1 -0
- package/lib/common/rpc-service/proxy/sumi.js +86 -0
- package/lib/common/rpc-service/proxy/sumi.js.map +1 -0
- package/lib/common/rpc-service/stub.d.ts +0 -1
- package/lib/common/rpc-service/stub.d.ts.map +1 -1
- package/lib/common/rpc-service/stub.js +3 -11
- package/lib/common/rpc-service/stub.js.map +1 -1
- package/lib/common/types.d.ts +1 -1
- package/lib/common/types.d.ts.map +1 -1
- package/lib/common/ws-channel.d.ts +97 -32
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +75 -51
- package/lib/common/ws-channel.js.map +1 -1
- package/lib/node/common-channel-handler.js +1 -1
- package/lib/node/common-channel-handler.js.map +1 -1
- package/package.json +5 -5
- package/src/browser/ws-channel-handler.ts +2 -6
- package/src/common/{connection → buffers}/buffers.ts +24 -3
- package/src/common/connection/drivers/base.ts +2 -6
- package/src/common/connection/drivers/frame-decoder.ts +170 -0
- package/src/common/connection/drivers/message-port.ts +42 -0
- package/src/common/connection/drivers/node-message-port.ts +3 -0
- package/src/common/connection/drivers/reconnecting-websocket.ts +4 -0
- package/src/common/connection/drivers/simple.ts +33 -0
- package/src/common/connection/drivers/socket.ts +11 -7
- package/src/common/connection/drivers/ws-websocket.ts +8 -0
- package/src/common/connection/types.ts +1 -1
- package/src/common/ext-rpc-protocol.ts +16 -51
- package/src/common/fury-extends/any.ts +144 -0
- package/src/common/fury-extends/one-of.ts +61 -0
- package/src/common/fury-extends/shared.ts +15 -0
- package/src/common/index.ts +2 -1
- package/src/common/protocols/common-server.ts +18 -0
- package/src/common/protocols/common.ts +9 -0
- package/src/common/rpc/connection.ts +345 -0
- package/src/common/rpc/errors.ts +5 -0
- package/src/common/rpc/index.ts +2 -0
- package/src/common/rpc/multiplexer.ts +105 -0
- package/src/common/rpc/packet.ts +104 -0
- package/src/common/rpc/protocol-repository.ts +180 -0
- package/src/common/rpc/types.ts +23 -0
- package/src/common/rpc/utils.ts +5 -0
- package/src/common/rpc-service/center.ts +59 -49
- package/src/common/rpc-service/index.ts +9 -0
- package/src/common/rpc-service/proxy/base.ts +126 -0
- package/src/common/rpc-service/proxy/index.ts +4 -0
- package/src/common/rpc-service/proxy/invoker.ts +45 -0
- package/src/common/rpc-service/proxy/legacy.ts +150 -0
- package/src/common/rpc-service/proxy/registry.ts +56 -0
- package/src/common/rpc-service/proxy/sumi.ts +81 -0
- package/src/common/rpc-service/stub.ts +4 -11
- package/src/common/types.ts +1 -1
- package/src/common/ws-channel.ts +100 -61
- package/src/node/common-channel-handler.ts +1 -1
- package/lib/common/connection/buffers.d.ts.map +0 -1
- package/lib/common/connection/buffers.js.map +0 -1
- package/lib/common/connection/drivers/empty.d.ts.map +0 -1
- package/lib/common/connection/drivers/empty.js +0 -21
- package/lib/common/connection/drivers/empty.js.map +0 -1
- package/lib/common/connection/drivers/stream-decoder.d.ts +0 -67
- package/lib/common/connection/drivers/stream-decoder.d.ts.map +0 -1
- package/lib/common/connection/drivers/stream-decoder.js +0 -171
- package/lib/common/connection/drivers/stream-decoder.js.map +0 -1
- package/lib/common/proxy/base.d.ts +0 -22
- package/lib/common/proxy/base.d.ts.map +0 -1
- package/lib/common/proxy/base.js +0 -47
- package/lib/common/proxy/base.js.map +0 -1
- package/lib/common/proxy/index.d.ts +0 -8
- package/lib/common/proxy/index.d.ts.map +0 -1
- package/lib/common/proxy/index.js +0 -12
- package/lib/common/proxy/index.js.map +0 -1
- package/lib/common/proxy/legacy.d.ts.map +0 -1
- package/lib/common/proxy/legacy.js +0 -183
- package/lib/common/proxy/legacy.js.map +0 -1
- package/src/common/connection/drivers/empty.ts +0 -19
- package/src/common/connection/drivers/stream-decoder.ts +0 -196
- package/src/common/proxy/base.ts +0 -67
- package/src/common/proxy/index.ts +0 -10
- package/src/common/proxy/legacy.ts +0 -200
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { BaseConnection } from '../connection';
|
|
2
|
+
|
|
3
|
+
import { ISumiConnectionOptions, SumiConnection } from './connection';
|
|
4
|
+
|
|
5
|
+
export class ProxyIdentifier<T = any> {
|
|
6
|
+
public static count = 0;
|
|
7
|
+
|
|
8
|
+
public readonly serviceId: string;
|
|
9
|
+
public readonly countId: number;
|
|
10
|
+
constructor(serviceId: string) {
|
|
11
|
+
this.serviceId = serviceId;
|
|
12
|
+
this.countId = ++ProxyIdentifier.count;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static for(serviceId: string) {
|
|
16
|
+
return new ProxyIdentifier(serviceId);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const IRPCProtocol = Symbol('IRPCProtocol');
|
|
21
|
+
export interface IRPCProtocol {
|
|
22
|
+
getProxy<T>(proxyId: ProxyIdentifier<T>): T;
|
|
23
|
+
set<T>(identifier: ProxyIdentifier<T>, instance: T): T;
|
|
24
|
+
get<T>(identifier: ProxyIdentifier<T>): T;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const SEP = '/';
|
|
28
|
+
|
|
29
|
+
function getRPCName(serviceId: string, methodName: string) {
|
|
30
|
+
return `${serviceId}${SEP}${methodName}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function extractServiceAndMethod(rpcId: string): [string, string] {
|
|
34
|
+
const idx = rpcId.indexOf(SEP);
|
|
35
|
+
return [rpcId.substring(0, idx), rpcId.substring(idx + 1)];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class SumiConnectionMultiplexer extends SumiConnection implements IRPCProtocol {
|
|
39
|
+
private readonly _locals: Map<string, any>;
|
|
40
|
+
private readonly _proxies: Map<string, any>;
|
|
41
|
+
|
|
42
|
+
constructor(protected socket: BaseConnection<Uint8Array>, protected options: ISumiConnectionOptions = {}) {
|
|
43
|
+
super(socket, options);
|
|
44
|
+
this._locals = new Map();
|
|
45
|
+
this._proxies = new Map();
|
|
46
|
+
|
|
47
|
+
this.onRequestNotFound((rpcName: string, args: any[]) => {
|
|
48
|
+
const [rpcId, methodName] = extractServiceAndMethod(rpcName);
|
|
49
|
+
return this._doInvokeHandler(rpcId, methodName, args);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// call `listen` implicitly
|
|
53
|
+
// compatible behavior with the RPCProtocol
|
|
54
|
+
this.listen();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public set<T>(identifier: ProxyIdentifier<T>, instance: any) {
|
|
58
|
+
this._locals.set(identifier.serviceId, instance);
|
|
59
|
+
return instance;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public get<T>(identifier: ProxyIdentifier<T>) {
|
|
63
|
+
return this._locals.get(identifier.serviceId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public getProxy<T>(proxyId: ProxyIdentifier<T>) {
|
|
67
|
+
if (!this._proxies.has(proxyId.serviceId)) {
|
|
68
|
+
this._proxies.set(proxyId.serviceId, this._createProxy(proxyId.serviceId));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return this._proxies.get(proxyId.serviceId);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private _createProxy(rpcId: string) {
|
|
75
|
+
const handler = {
|
|
76
|
+
get: (target: any, name: string) => {
|
|
77
|
+
if (typeof name === 'symbol') {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
// charCodeAt(0) === 36 means starts with $
|
|
81
|
+
if (!target[name] && name.charCodeAt(0) === 36) {
|
|
82
|
+
const rpcName = getRPCName(rpcId, name);
|
|
83
|
+
target[name] = (...args: any[]) => this.sendRequest(rpcName, ...args);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return target[name];
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return new Proxy(Object.create(null), handler);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private async _doInvokeHandler(rpcId: string, methodName: string, args: any[]): Promise<any> {
|
|
94
|
+
const actor = this._locals.get(rpcId);
|
|
95
|
+
if (!actor) {
|
|
96
|
+
throw new Error('Unknown actor ' + rpcId);
|
|
97
|
+
}
|
|
98
|
+
const method = await actor[methodName];
|
|
99
|
+
if (typeof method !== 'function') {
|
|
100
|
+
throw new Error('Unknown method ' + methodName + ' on actor ' + rpcId);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return method.apply(actor, args);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Serializer, Type } from '@furyjs/fury';
|
|
2
|
+
import { generateSerializer } from '@furyjs/fury/dist/lib/gen';
|
|
3
|
+
|
|
4
|
+
import { stringifyError } from '@opensumi/ide-core-common/lib/utils';
|
|
5
|
+
|
|
6
|
+
import { furyFactory } from '../fury-extends/shared';
|
|
7
|
+
|
|
8
|
+
const ProtoVersionV1 = 1;
|
|
9
|
+
|
|
10
|
+
export enum OperationType {
|
|
11
|
+
Request,
|
|
12
|
+
Notification,
|
|
13
|
+
Response,
|
|
14
|
+
Heartbeat,
|
|
15
|
+
Cancel,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export enum BodyCodec {
|
|
19
|
+
/**
|
|
20
|
+
* Means no body
|
|
21
|
+
*/
|
|
22
|
+
None,
|
|
23
|
+
Text,
|
|
24
|
+
Binary,
|
|
25
|
+
JSON,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export enum ErrorCode {
|
|
29
|
+
OK,
|
|
30
|
+
Err,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const { fury, reader, writer } = furyFactory();
|
|
34
|
+
export { reader };
|
|
35
|
+
|
|
36
|
+
const requestHeadersProto = Type.object('headers', {
|
|
37
|
+
cancelable: Type.bool(),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export interface IRequestHeaders {
|
|
41
|
+
/**
|
|
42
|
+
* If set to true, the request can be canceled.
|
|
43
|
+
*
|
|
44
|
+
* the server will push a `CancellationToken` to the request arguments.
|
|
45
|
+
*/
|
|
46
|
+
cancelable?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const requestHeadersSerializer = generateSerializer(fury, requestHeadersProto) as Serializer;
|
|
50
|
+
|
|
51
|
+
export class MessageIO {
|
|
52
|
+
static Request(requestId: number, rpcType: number, method: string, headers: IRequestHeaders, payload: Uint8Array) {
|
|
53
|
+
writer.reset();
|
|
54
|
+
|
|
55
|
+
writer.uint8(ProtoVersionV1);
|
|
56
|
+
writer.uint8(rpcType);
|
|
57
|
+
writer.uint32(requestId);
|
|
58
|
+
writer.uint8(BodyCodec.Binary);
|
|
59
|
+
writer.stringOfVarUInt32(method);
|
|
60
|
+
requestHeadersSerializer.write(headers);
|
|
61
|
+
writer.varUInt32(payload.length);
|
|
62
|
+
writer.buffer(payload);
|
|
63
|
+
|
|
64
|
+
return writer.dump();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static Cancel(requestId: number) {
|
|
68
|
+
writer.reset();
|
|
69
|
+
|
|
70
|
+
writer.uint8(ProtoVersionV1);
|
|
71
|
+
writer.uint8(OperationType.Cancel);
|
|
72
|
+
writer.uint32(requestId);
|
|
73
|
+
writer.uint8(BodyCodec.None);
|
|
74
|
+
|
|
75
|
+
return writer.dump();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static Response(requestId: number, headers: Record<string, any>, payload: Uint8Array) {
|
|
79
|
+
writer.reset();
|
|
80
|
+
|
|
81
|
+
writer.uint8(ProtoVersionV1);
|
|
82
|
+
writer.uint8(OperationType.Response);
|
|
83
|
+
writer.uint32(requestId);
|
|
84
|
+
writer.uint8(BodyCodec.Binary);
|
|
85
|
+
writer.uint16(ErrorCode.OK);
|
|
86
|
+
writer.varUInt32(payload.length);
|
|
87
|
+
writer.buffer(payload);
|
|
88
|
+
|
|
89
|
+
return writer.dump();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static Error(requestId: number, status: number, headers: Record<string, any>, error: any) {
|
|
93
|
+
writer.reset();
|
|
94
|
+
|
|
95
|
+
writer.uint8(ProtoVersionV1);
|
|
96
|
+
writer.uint8(OperationType.Response);
|
|
97
|
+
writer.uint32(requestId);
|
|
98
|
+
writer.uint8(BodyCodec.JSON);
|
|
99
|
+
writer.uint16(status);
|
|
100
|
+
writer.stringOfVarUInt32(stringifyError(error));
|
|
101
|
+
|
|
102
|
+
return writer.dump();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import Fury, { Type, TypeDescription } from '@furyjs/fury';
|
|
2
|
+
|
|
3
|
+
import { anySerializer } from '../fury-extends/any';
|
|
4
|
+
|
|
5
|
+
import { TSumiProtocol, TSumiProtocolMethod } from './types';
|
|
6
|
+
|
|
7
|
+
export type TRequestTransferable = ITransferable[];
|
|
8
|
+
|
|
9
|
+
export interface ITransferable {
|
|
10
|
+
/**
|
|
11
|
+
* transfer raw value
|
|
12
|
+
*/
|
|
13
|
+
r: any;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* value that cannot be transferred, use string instead
|
|
17
|
+
*/
|
|
18
|
+
$?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type TSerializer = ReturnType<Fury['registerSerializer']>;
|
|
22
|
+
|
|
23
|
+
interface IProtocolProcessor {
|
|
24
|
+
serializeRequest(args: any[]): Uint8Array;
|
|
25
|
+
deserializeRequest(buffer: Uint8Array): any[];
|
|
26
|
+
serializeResult<T = any>(result: T): Uint8Array;
|
|
27
|
+
deserializeResult<T = any>(buffer: Uint8Array): T;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const createTransferable = (name: string, type?: TypeDescription) => {
|
|
31
|
+
const props = {
|
|
32
|
+
$: Type.string(),
|
|
33
|
+
} as Record<string, TypeDescription>;
|
|
34
|
+
if (type) {
|
|
35
|
+
props.r = type;
|
|
36
|
+
}
|
|
37
|
+
return Type.object(name, props);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
class SumiProtocolProcessor implements IProtocolProcessor {
|
|
41
|
+
request: TSerializer;
|
|
42
|
+
result: TSerializer;
|
|
43
|
+
requestArgsLength: number;
|
|
44
|
+
|
|
45
|
+
constructor(methodProtocol: TSumiProtocolMethod, public fury: Fury) {
|
|
46
|
+
const methodName = methodProtocol.method;
|
|
47
|
+
|
|
48
|
+
const argsTuple = [] as TypeDescription[];
|
|
49
|
+
|
|
50
|
+
for (const element of methodProtocol.request) {
|
|
51
|
+
argsTuple.push(createTransferable(methodName + '^' + element.name, element.type));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const requestProto = Type.tuple(argsTuple);
|
|
55
|
+
const resultProto = createTransferable(methodName + 'v', methodProtocol.response.type);
|
|
56
|
+
|
|
57
|
+
this.requestArgsLength = argsTuple.length;
|
|
58
|
+
|
|
59
|
+
this.request = this.fury.registerSerializer(requestProto);
|
|
60
|
+
this.result = this.fury.registerSerializer(resultProto);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
serializeRequest(args: any[]): Uint8Array {
|
|
64
|
+
const newArray: TRequestTransferable = new Array(args.length);
|
|
65
|
+
for (let i = 0; i < args.length; i++) {
|
|
66
|
+
newArray[i] = ObjectTransfer.replacer(args[i]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return this.request.serialize(newArray);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
deserializeRequest(buffer: Uint8Array): any[] {
|
|
73
|
+
const result = new Array(this.requestArgsLength);
|
|
74
|
+
const argsArray = this.request.deserialize(buffer) as TRequestTransferable;
|
|
75
|
+
for (let i = 0; i < this.requestArgsLength; i++) {
|
|
76
|
+
result[i] = ObjectTransfer.reviver(argsArray[i]);
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
serializeResult<T = any>(result: T): Uint8Array {
|
|
82
|
+
return this.result.serialize(ObjectTransfer.replacer(result));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
deserializeResult<T = any>(buffer: Uint8Array): T {
|
|
86
|
+
const payload = this.result.deserialize(buffer) as ITransferable;
|
|
87
|
+
return ObjectTransfer.reviver(payload);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
class AnyProtocolProcessor implements IProtocolProcessor {
|
|
92
|
+
serializeRequest(args: any[]): Uint8Array {
|
|
93
|
+
return anySerializer.serialize(args);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
deserializeRequest(buffer: Uint8Array): any[] {
|
|
97
|
+
return anySerializer.deserialize(buffer);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
serializeResult<T = any>(result: T): Uint8Array {
|
|
101
|
+
return anySerializer.serialize(result);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
deserializeResult<T = any>(buffer: Uint8Array): T {
|
|
105
|
+
return anySerializer.deserialize(buffer);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export class ProtocolRepository {
|
|
110
|
+
fury = new Fury();
|
|
111
|
+
|
|
112
|
+
private processorMap = new Map<string, SumiProtocolProcessor>();
|
|
113
|
+
|
|
114
|
+
private anyProcessor = new AnyProtocolProcessor();
|
|
115
|
+
|
|
116
|
+
has(name: string) {
|
|
117
|
+
return this.processorMap.has(name);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
loadProtocol(
|
|
121
|
+
protocol: TSumiProtocol,
|
|
122
|
+
options?: {
|
|
123
|
+
nameConverter?: (str: string) => string;
|
|
124
|
+
},
|
|
125
|
+
) {
|
|
126
|
+
const { methods } = protocol;
|
|
127
|
+
|
|
128
|
+
for (const proto of methods) {
|
|
129
|
+
let method = proto.method;
|
|
130
|
+
if (options?.nameConverter) {
|
|
131
|
+
method = options.nameConverter(method);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const copy = {
|
|
135
|
+
...proto,
|
|
136
|
+
method,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
this.loadProtocolMethod(copy);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
loadProtocolMethod(methodProtocol: TSumiProtocolMethod) {
|
|
144
|
+
this.processorMap.set(methodProtocol.method, new SumiProtocolProcessor(methodProtocol, this.fury));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
getProcessor(method: string): IProtocolProcessor {
|
|
148
|
+
const processor = this.processorMap.get(method);
|
|
149
|
+
if (processor) {
|
|
150
|
+
return processor;
|
|
151
|
+
}
|
|
152
|
+
return this.anyProcessor;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class ObjectTransfer {
|
|
157
|
+
static TypeUndefined = '$undefined';
|
|
158
|
+
|
|
159
|
+
static replacer(value: any) {
|
|
160
|
+
const payload = {} as ITransferable;
|
|
161
|
+
|
|
162
|
+
if (typeof value === 'undefined') {
|
|
163
|
+
payload.$ = ObjectTransfer.TypeUndefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!payload.$) {
|
|
167
|
+
payload.r = value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return payload;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static reviver(transferable: ITransferable): any {
|
|
174
|
+
if (transferable.$ === ObjectTransfer.TypeUndefined) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return transferable.r;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TypeDescription } from '@furyjs/fury';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
RPCProtocol as _RPCProtocol,
|
|
5
|
+
RPCProtocolMethod as _RPCProtocolMethod,
|
|
6
|
+
Request as _Request,
|
|
7
|
+
Response as _Response,
|
|
8
|
+
} from '@opensumi/ide-core-common/lib/types/rpc';
|
|
9
|
+
|
|
10
|
+
export type TSumiProtocol = _RPCProtocol<TypeDescription>;
|
|
11
|
+
export type TSumiProtocolMethod = _RPCProtocolMethod<TypeDescription>;
|
|
12
|
+
export type TSumiRequest = _Request<TypeDescription>;
|
|
13
|
+
export type TSumiResponse = _Response<TypeDescription>;
|
|
14
|
+
|
|
15
|
+
export type TRequestCallback = (headers: Record<string, any>, error?: any, payload?: Uint8Array | string | any) => void;
|
|
16
|
+
|
|
17
|
+
export type THandlerResult<R> = R | Promise<R>;
|
|
18
|
+
|
|
19
|
+
export type TGenericNotificationHandler = (...args: any[]) => void | Promise<void>;
|
|
20
|
+
export type TGenericRequestHandler<R> = (...args: any[]) => THandlerResult<R>;
|
|
21
|
+
|
|
22
|
+
export type TOnRequestNotFoundHandler = (method: string, args: any[]) => THandlerResult<any>;
|
|
23
|
+
export type TOnNotificationNotFoundHandler = (method: string, args: any[]) => THandlerResult<void>;
|
|
@@ -1,43 +1,25 @@
|
|
|
1
1
|
import { Deferred } from '@opensumi/ide-core-common';
|
|
2
|
+
import { MessageConnection } from '@opensumi/vscode-jsonrpc';
|
|
2
3
|
|
|
3
4
|
import { METHOD_NOT_REGISTERED } from '../constants';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { TSumiProtocol, ProtocolRepository } from '../rpc';
|
|
6
|
+
import { SumiConnection } from '../rpc/connection';
|
|
7
|
+
import { IBench, ILogger, RPCServiceMethod, ServiceType } from '../types';
|
|
6
8
|
import { getMethodName } from '../utils';
|
|
7
|
-
import { WSChannel } from '../ws-channel';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
import { ServiceRegistry, Invoker, ProxyLegacy, ProxySumi } from './proxy';
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
class Invoker {
|
|
14
|
-
legacyProxy: ProxyLegacy;
|
|
15
|
-
|
|
16
|
-
private legacyInvokeProxy: any;
|
|
17
|
-
|
|
18
|
-
setLegacyProxy(proxy: ProxyLegacy) {
|
|
19
|
-
this.legacyProxy = proxy;
|
|
20
|
-
this.legacyInvokeProxy = proxy.getInvokeProxy();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
invoke(name: string, ...args: any[]) {
|
|
24
|
-
if (defaultReservedWordSet.has(name) || typeof name === 'symbol') {
|
|
25
|
-
return Promise.resolve();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return this.legacyInvokeProxy[name](...args);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
12
|
+
const safeProcess: { pid: string } = typeof process === 'undefined' ? { pid: 'unknown' } : (process as any);
|
|
31
13
|
|
|
32
14
|
export class RPCServiceCenter {
|
|
33
15
|
public uid: string;
|
|
34
16
|
|
|
35
17
|
private invokers: Invoker[] = [];
|
|
36
|
-
private connection: Array<WSChannel> = [];
|
|
37
18
|
|
|
38
|
-
private
|
|
19
|
+
private protocolRepository = new ProtocolRepository();
|
|
20
|
+
private registry = new ServiceRegistry();
|
|
39
21
|
|
|
40
|
-
private
|
|
22
|
+
private deferred = new Deferred<void>();
|
|
41
23
|
private logger: ILogger;
|
|
42
24
|
|
|
43
25
|
constructor(private bench?: IBench, logger?: ILogger) {
|
|
@@ -54,47 +36,75 @@ export class RPCServiceCenter {
|
|
|
54
36
|
}
|
|
55
37
|
|
|
56
38
|
ready() {
|
|
57
|
-
return this.
|
|
39
|
+
return this.deferred.promise;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
loadProtocol(protocol: TSumiProtocol) {
|
|
43
|
+
this.protocolRepository.loadProtocol(protocol, {
|
|
44
|
+
nameConverter: (name) => getMethodName(protocol.name, name),
|
|
45
|
+
});
|
|
58
46
|
}
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
this.
|
|
48
|
+
setSumiConnection(connection: SumiConnection) {
|
|
49
|
+
if (this.invokers.length === 0) {
|
|
50
|
+
this.deferred.resolve();
|
|
63
51
|
}
|
|
64
|
-
this.connection.push(channel);
|
|
65
|
-
const index = this.connection.length - 1;
|
|
66
52
|
|
|
67
|
-
const
|
|
68
|
-
const connection = channel.createMessageConnection();
|
|
69
|
-
rpcProxy.listen(connection);
|
|
53
|
+
const index = this.invokers.length - 1;
|
|
70
54
|
|
|
71
55
|
const invoker = new Invoker();
|
|
72
56
|
|
|
73
|
-
|
|
57
|
+
const sumiProxy = new ProxySumi(this.registry, this.logger);
|
|
58
|
+
invoker.attachSumi(sumiProxy);
|
|
59
|
+
sumiProxy.listen(connection);
|
|
74
60
|
|
|
75
61
|
this.invokers.push(invoker);
|
|
76
62
|
|
|
77
63
|
return {
|
|
78
64
|
dispose: () => {
|
|
79
|
-
this.connection.splice(index, 1);
|
|
80
65
|
this.invokers.splice(index, 1);
|
|
81
|
-
|
|
66
|
+
invoker.dispose();
|
|
82
67
|
},
|
|
83
68
|
};
|
|
84
69
|
}
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.serviceMethodMap[name] = method;
|
|
90
|
-
} else {
|
|
91
|
-
this.invokers.forEach((proxy) => {
|
|
92
|
-
proxy.legacyProxy.listenService({ [name]: method });
|
|
93
|
-
});
|
|
71
|
+
setConnection(connection: MessageConnection) {
|
|
72
|
+
if (this.invokers.length === 0) {
|
|
73
|
+
this.deferred.resolve();
|
|
94
74
|
}
|
|
75
|
+
|
|
76
|
+
const index = this.invokers.length - 1;
|
|
77
|
+
|
|
78
|
+
const invoker = new Invoker();
|
|
79
|
+
|
|
80
|
+
const legacyProxy = new ProxyLegacy(this.registry, this.logger);
|
|
81
|
+
legacyProxy.listen(connection);
|
|
82
|
+
|
|
83
|
+
invoker.attachLegacy(legacyProxy);
|
|
84
|
+
|
|
85
|
+
this.invokers.push(invoker);
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
dispose: () => {
|
|
89
|
+
this.invokers.splice(index, 1);
|
|
90
|
+
invoker.dispose();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
onRequest(serviceName: string, _name: string, method: RPCServiceMethod) {
|
|
96
|
+
this.registry.register(getMethodName(serviceName, _name), method);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
onRequestService(serviceName: string, service: any) {
|
|
100
|
+
this.registry.registerService(service, {
|
|
101
|
+
nameConverter: (name) => getMethodName(serviceName, name),
|
|
102
|
+
});
|
|
95
103
|
}
|
|
96
104
|
|
|
97
105
|
async broadcast(serviceName: string, _name: string, ...args: any[]): Promise<any> {
|
|
106
|
+
await this.ready();
|
|
107
|
+
|
|
98
108
|
const name = getMethodName(serviceName, _name);
|
|
99
109
|
const broadcastResult = await Promise.all(this.invokers.map((proxy) => proxy.invoke(name, ...args)));
|
|
100
110
|
|
|
@@ -117,8 +127,8 @@ export class RPCServiceCenter {
|
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
// FIXME: this is an unreasonable design, if remote service only returned doubtful result, we will return an empty array.
|
|
120
|
-
//
|
|
121
|
-
//
|
|
130
|
+
// but actually we should throw an error to tell user that no remote service can handle this call.
|
|
131
|
+
// or just return `undefined`.
|
|
122
132
|
return result.length === 1 ? result[0] : result;
|
|
123
133
|
}
|
|
124
134
|
}
|
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
export * from './stub';
|
|
2
2
|
export * from './center';
|
|
3
|
+
|
|
4
|
+
export abstract class RPCService<T = any> {
|
|
5
|
+
rpcClient?: T[];
|
|
6
|
+
rpcRegistered?: boolean;
|
|
7
|
+
register?(): () => Promise<T>;
|
|
8
|
+
get client() {
|
|
9
|
+
return this.rpcClient ? this.rpcClient[0] : undefined;
|
|
10
|
+
}
|
|
11
|
+
}
|