@opensumi/ide-connection 2.27.3-rc-1706857131.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,144 @@
|
|
|
1
|
+
import { Uri } from '@opensumi/ide-core-common';
|
|
2
|
+
|
|
3
|
+
import { furyFactory } from './shared';
|
|
4
|
+
|
|
5
|
+
const { reader, writer } = furyFactory();
|
|
6
|
+
|
|
7
|
+
export enum ProtocolType {
|
|
8
|
+
String,
|
|
9
|
+
Buffer,
|
|
10
|
+
Number,
|
|
11
|
+
Int32,
|
|
12
|
+
JSONObject,
|
|
13
|
+
BigInt,
|
|
14
|
+
Array,
|
|
15
|
+
Union,
|
|
16
|
+
Object,
|
|
17
|
+
Undefined,
|
|
18
|
+
Boolean,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function serializeWorker(data: unknown) {
|
|
22
|
+
if (typeof data === 'undefined') {
|
|
23
|
+
writer.uint8(ProtocolType.Undefined);
|
|
24
|
+
} else if (Array.isArray(data)) {
|
|
25
|
+
writer.uint8(ProtocolType.Array);
|
|
26
|
+
writer.varUInt32(data.length);
|
|
27
|
+
for (const element of data) {
|
|
28
|
+
serializeWorker(element);
|
|
29
|
+
}
|
|
30
|
+
} else if (typeof data === 'boolean') {
|
|
31
|
+
writer.uint8(ProtocolType.Boolean);
|
|
32
|
+
writer.uint8(data ? 1 : 0);
|
|
33
|
+
} else if (typeof data === 'number') {
|
|
34
|
+
if ((data | 0) === data) {
|
|
35
|
+
writer.uint8(ProtocolType.Int32);
|
|
36
|
+
writer.int32(data);
|
|
37
|
+
} else {
|
|
38
|
+
writer.uint8(ProtocolType.Number);
|
|
39
|
+
writer.double(data);
|
|
40
|
+
}
|
|
41
|
+
} else if (typeof data === 'string') {
|
|
42
|
+
writer.uint8(ProtocolType.String);
|
|
43
|
+
writer.stringOfVarUInt32(data);
|
|
44
|
+
} else if (data instanceof Uint8Array) {
|
|
45
|
+
writer.uint8(ProtocolType.Buffer);
|
|
46
|
+
writer.varUInt32(data.byteLength);
|
|
47
|
+
writer.buffer(data);
|
|
48
|
+
} else if (typeof data === 'bigint') {
|
|
49
|
+
writer.uint8(ProtocolType.BigInt);
|
|
50
|
+
writer.int64(data);
|
|
51
|
+
} else if (typeof data === 'object') {
|
|
52
|
+
writer.uint8(ProtocolType.JSONObject);
|
|
53
|
+
writer.stringOfVarUInt32(JSON.stringify(data, ObjectTransfer.replacer));
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Unknown type ${typeof data}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function deserializeWorker() {
|
|
60
|
+
const type = reader.uint8();
|
|
61
|
+
switch (type) {
|
|
62
|
+
case ProtocolType.Undefined:
|
|
63
|
+
return undefined;
|
|
64
|
+
case ProtocolType.String:
|
|
65
|
+
return reader.stringOfVarUInt32();
|
|
66
|
+
case ProtocolType.Buffer: {
|
|
67
|
+
const length = reader.varUInt32();
|
|
68
|
+
return reader.buffer(length);
|
|
69
|
+
}
|
|
70
|
+
case ProtocolType.Int32:
|
|
71
|
+
return reader.int32();
|
|
72
|
+
case ProtocolType.Number:
|
|
73
|
+
return reader.double();
|
|
74
|
+
case ProtocolType.JSONObject: {
|
|
75
|
+
const json = reader.stringOfVarUInt32();
|
|
76
|
+
return JSON.parse(json, ObjectTransfer.reviver);
|
|
77
|
+
}
|
|
78
|
+
case ProtocolType.BigInt:
|
|
79
|
+
return reader.int64();
|
|
80
|
+
case ProtocolType.Array: {
|
|
81
|
+
const length = reader.varUInt32();
|
|
82
|
+
const data = [] as unknown[];
|
|
83
|
+
for (let i = 0; i < length; i++) {
|
|
84
|
+
data.push(deserializeWorker());
|
|
85
|
+
}
|
|
86
|
+
return data;
|
|
87
|
+
}
|
|
88
|
+
case ProtocolType.Boolean:
|
|
89
|
+
return reader.uint8() === 1;
|
|
90
|
+
default:
|
|
91
|
+
throw new Error(`Unknown type ${type}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const deserialize = (bytes: Uint8Array) => {
|
|
96
|
+
reader.reset(bytes);
|
|
97
|
+
|
|
98
|
+
return deserializeWorker();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const serializeVolatile = (v: any) => {
|
|
102
|
+
writer.reset();
|
|
103
|
+
|
|
104
|
+
serializeWorker(v);
|
|
105
|
+
|
|
106
|
+
return writer.dumpAndOwn();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const serialize = (v: any) => {
|
|
110
|
+
writer.reset();
|
|
111
|
+
serializeWorker(v);
|
|
112
|
+
|
|
113
|
+
return writer.dump();
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const anySerializer = {
|
|
117
|
+
deserialize,
|
|
118
|
+
serialize,
|
|
119
|
+
serializeVolatile,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
class ObjectTransfer {
|
|
123
|
+
static replacer(key: string | undefined, value: any) {
|
|
124
|
+
if (value) {
|
|
125
|
+
if (value.$mid === 1) {
|
|
126
|
+
const uri = Uri.revive(value);
|
|
127
|
+
return {
|
|
128
|
+
$type: 'VSCODE_URI',
|
|
129
|
+
data: uri.toString(),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
static reviver(key: string | undefined, value: any) {
|
|
137
|
+
if (value && value.$type !== undefined && value.data !== undefined) {
|
|
138
|
+
if (value.$type === 'VSCODE_URI') {
|
|
139
|
+
return Uri.parse(value.data);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ObjectTypeDescription, Serializer, TypeDescription } from '@furyjs/fury';
|
|
2
|
+
import { generateSerializer } from '@furyjs/fury/dist/lib/gen';
|
|
3
|
+
|
|
4
|
+
import { furyFactory } from './shared';
|
|
5
|
+
const { fury, reader, writer } = furyFactory();
|
|
6
|
+
|
|
7
|
+
type Writable = Record<string, any> & { kind: string };
|
|
8
|
+
|
|
9
|
+
export const oneOf = (schemas: TypeDescription[]) => {
|
|
10
|
+
const registry = new Map<string, Serializer>();
|
|
11
|
+
|
|
12
|
+
schemas.forEach((schema) => {
|
|
13
|
+
registry.set((schema as ObjectTypeDescription).options.tag, generateSerializer(fury, schema));
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const deserialize = (bytes: Uint8Array) => {
|
|
17
|
+
reader.reset(bytes);
|
|
18
|
+
const kind = reader.stringOfVarUInt32();
|
|
19
|
+
const serializer = registry.get(kind);
|
|
20
|
+
if (!serializer) {
|
|
21
|
+
throw new Error(`Unknown kind: ${kind}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const v = serializer.read();
|
|
25
|
+
v.kind = kind;
|
|
26
|
+
|
|
27
|
+
return v;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const serializeVolatile = (v: Writable) => {
|
|
31
|
+
const serializer = registry.get(v.kind);
|
|
32
|
+
if (!serializer) {
|
|
33
|
+
throw new Error(`Unknown kind: ${v.kind}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
writer.reset();
|
|
37
|
+
writer.stringOfVarUInt32(v.kind);
|
|
38
|
+
serializer.write(v);
|
|
39
|
+
|
|
40
|
+
return writer.dumpAndOwn();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const serialize = (v: Writable) => {
|
|
44
|
+
const serializer = registry.get(v.kind);
|
|
45
|
+
if (!serializer) {
|
|
46
|
+
throw new Error(`Unknown kind: ${v.kind}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
writer.reset();
|
|
50
|
+
writer.stringOfVarUInt32(v.kind);
|
|
51
|
+
serializer.write(v);
|
|
52
|
+
|
|
53
|
+
return writer.dump();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
deserialize,
|
|
58
|
+
serialize,
|
|
59
|
+
serializeVolatile,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Fury from '@furyjs/fury/dist/lib/fury';
|
|
2
|
+
|
|
3
|
+
export const furyFactory = () => {
|
|
4
|
+
const fury = Fury({});
|
|
5
|
+
const reader = fury.binaryReader;
|
|
6
|
+
const writer = fury.binaryWriter;
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
fury,
|
|
10
|
+
reader,
|
|
11
|
+
writer,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type FuryFactoryReturn = ReturnType<typeof furyFactory>;
|
package/src/common/index.ts
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Type } from '@furyjs/fury';
|
|
2
|
+
|
|
3
|
+
import { CommonServerPath } from '@opensumi/ide-core-common';
|
|
4
|
+
|
|
5
|
+
import type { TSumiProtocol } from '../rpc';
|
|
6
|
+
|
|
7
|
+
export const CommonServerProtocol = {
|
|
8
|
+
name: CommonServerPath,
|
|
9
|
+
methods: [
|
|
10
|
+
{
|
|
11
|
+
method: 'getBackendOS',
|
|
12
|
+
request: [],
|
|
13
|
+
response: {
|
|
14
|
+
type: Type.uint16(),
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
} as TSumiProtocol;
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import type net from 'net';
|
|
2
|
+
|
|
3
|
+
import type { WebSocket } from 'ws';
|
|
4
|
+
|
|
5
|
+
import { EventEmitter } from '@opensumi/events';
|
|
6
|
+
import {
|
|
7
|
+
DisposableCollection,
|
|
8
|
+
IDisposable,
|
|
9
|
+
parseError,
|
|
10
|
+
CancellationToken,
|
|
11
|
+
canceled,
|
|
12
|
+
CancellationTokenSource,
|
|
13
|
+
isPromise,
|
|
14
|
+
} from '@opensumi/ide-utils';
|
|
15
|
+
|
|
16
|
+
import { BaseConnection, NetSocketConnection, WSWebSocketConnection } from '../connection';
|
|
17
|
+
import { METHOD_NOT_REGISTERED } from '../constants';
|
|
18
|
+
import { ILogger } from '../types';
|
|
19
|
+
|
|
20
|
+
import { MethodTimeoutError } from './errors';
|
|
21
|
+
import {
|
|
22
|
+
BodyCodec,
|
|
23
|
+
ErrorCode,
|
|
24
|
+
OperationType,
|
|
25
|
+
MessageIO,
|
|
26
|
+
requestHeadersSerializer,
|
|
27
|
+
reader,
|
|
28
|
+
IRequestHeaders,
|
|
29
|
+
} from './packet';
|
|
30
|
+
import { ProtocolRepository } from './protocol-repository';
|
|
31
|
+
import {
|
|
32
|
+
TGenericNotificationHandler,
|
|
33
|
+
TGenericRequestHandler,
|
|
34
|
+
TOnNotificationNotFoundHandler,
|
|
35
|
+
TOnRequestNotFoundHandler,
|
|
36
|
+
TRequestCallback,
|
|
37
|
+
} from './types';
|
|
38
|
+
import { assert } from './utils';
|
|
39
|
+
|
|
40
|
+
const nullHeaders = {};
|
|
41
|
+
|
|
42
|
+
const star = '*';
|
|
43
|
+
|
|
44
|
+
export interface ISumiConnectionOptions {
|
|
45
|
+
timeout?: number;
|
|
46
|
+
logger?: ILogger;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class SumiConnection implements IDisposable {
|
|
50
|
+
protected disposable = new DisposableCollection();
|
|
51
|
+
|
|
52
|
+
private _requestEmitter = new EventEmitter<{
|
|
53
|
+
[key: string]: [requestId: number, method: string, headers: Record<string, any>, args: any[]];
|
|
54
|
+
}>();
|
|
55
|
+
private _notificationEmitter = new EventEmitter<{
|
|
56
|
+
[key: string]: [requestId: number, method: string, headers: Record<string, any>, args: any[]];
|
|
57
|
+
}>();
|
|
58
|
+
|
|
59
|
+
private _requestId = 0;
|
|
60
|
+
private _callbacks = new Map<number, TRequestCallback>();
|
|
61
|
+
|
|
62
|
+
private readonly _timeoutHandles = new Map<number, NodeJS.Timeout | number>();
|
|
63
|
+
private readonly _cancellationTokenSources = new Map<number, CancellationTokenSource>();
|
|
64
|
+
private readonly _knownCanceledRequests = new Set<number>();
|
|
65
|
+
|
|
66
|
+
public protocolRepository = new ProtocolRepository();
|
|
67
|
+
protected logger: ILogger = console;
|
|
68
|
+
|
|
69
|
+
constructor(protected socket: BaseConnection<Uint8Array>, protected options: ISumiConnectionOptions = {}) {
|
|
70
|
+
if (options.logger) {
|
|
71
|
+
this.logger = options.logger;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
sendNotification(method: string, ...args: any[]) {
|
|
76
|
+
const processor = this.protocolRepository.getProcessor(method);
|
|
77
|
+
const payload = processor.serializeRequest(args);
|
|
78
|
+
this.socket.send(MessageIO.Request(this._requestId++, OperationType.Notification, method, nullHeaders, payload));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
sendRequest(method: string, ...args: any[]) {
|
|
82
|
+
return new Promise<any>((resolve, reject) => {
|
|
83
|
+
const requestId = this._requestId++;
|
|
84
|
+
|
|
85
|
+
const processor = this.protocolRepository.getProcessor(method);
|
|
86
|
+
|
|
87
|
+
this._callbacks.set(requestId, (headers, error, buffer) => {
|
|
88
|
+
if (error) {
|
|
89
|
+
if (error === METHOD_NOT_REGISTERED) {
|
|
90
|
+
resolve(error);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
reject(error);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const result = processor.deserializeResult(buffer);
|
|
99
|
+
resolve(result);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Set timeout callback, -1 means no timeout configuration is set.
|
|
103
|
+
if (this.options.timeout && this.options.timeout !== -1) {
|
|
104
|
+
const timeoutHandle = setTimeout(() => {
|
|
105
|
+
this._handleTimeout(method, requestId);
|
|
106
|
+
}, this.options.timeout);
|
|
107
|
+
this._timeoutHandles.set(requestId, timeoutHandle);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const cancellationToken: CancellationToken | undefined =
|
|
111
|
+
args.length && CancellationToken.isCancellationToken(args[args.length - 1]) ? args.pop() : undefined;
|
|
112
|
+
if (cancellationToken && cancellationToken.isCancellationRequested) {
|
|
113
|
+
return Promise.reject(canceled());
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (cancellationToken) {
|
|
117
|
+
cancellationToken.onCancellationRequested(() => this.cancelRequest(requestId));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const payload = processor.serializeRequest(args);
|
|
121
|
+
this.socket.send(
|
|
122
|
+
MessageIO.Request(
|
|
123
|
+
requestId,
|
|
124
|
+
OperationType.Request,
|
|
125
|
+
method,
|
|
126
|
+
{
|
|
127
|
+
cancelable: cancellationToken ? true : false,
|
|
128
|
+
},
|
|
129
|
+
payload,
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
onNotification(method: string, handler: TGenericNotificationHandler): IDisposable {
|
|
136
|
+
const handlerWrapper = (requestId: number, method: string, headers: Record<string, any>, args: any[]) => {
|
|
137
|
+
handler(...args);
|
|
138
|
+
};
|
|
139
|
+
return this._notificationEmitter.on(method, handlerWrapper);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
onNotificationNotFound(handler: TOnNotificationNotFoundHandler): IDisposable {
|
|
143
|
+
const handlerWrapper = (requestId: number, method: string, headers: Record<string, any>, args: any[]) => {
|
|
144
|
+
handler(method, args);
|
|
145
|
+
};
|
|
146
|
+
return this._notificationEmitter.on(star, handlerWrapper);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
cancelRequest(requestId: number) {
|
|
150
|
+
this.socket.send(MessageIO.Cancel(requestId));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private _handleTimeout(method: string, requestId: number) {
|
|
154
|
+
if (!this._callbacks.has(requestId) || !this._timeoutHandles.has(requestId)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const callback = this._callbacks.get(requestId)!;
|
|
159
|
+
this._callbacks.delete(requestId);
|
|
160
|
+
this._timeoutHandles.delete(requestId);
|
|
161
|
+
callback(nullHeaders, new MethodTimeoutError(method));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private runRequestHandler<T extends (...args: any[]) => any>(
|
|
165
|
+
requestId: number,
|
|
166
|
+
method: string,
|
|
167
|
+
args: any[],
|
|
168
|
+
handler: T,
|
|
169
|
+
) {
|
|
170
|
+
let result: any;
|
|
171
|
+
let error: Error | undefined;
|
|
172
|
+
const processor = this.protocolRepository.getProcessor(method);
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
result = handler(...args);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
error = err;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (error) {
|
|
181
|
+
this.socket.send(MessageIO.Error(requestId, ErrorCode.Err, nullHeaders, error));
|
|
182
|
+
this._cancellationTokenSources.delete(requestId);
|
|
183
|
+
} else if (isPromise(result)) {
|
|
184
|
+
result
|
|
185
|
+
.then((result) => {
|
|
186
|
+
const payload = processor.serializeResult(result);
|
|
187
|
+
this.socket.send(MessageIO.Response(requestId, nullHeaders, payload));
|
|
188
|
+
this._cancellationTokenSources.delete(requestId);
|
|
189
|
+
})
|
|
190
|
+
.catch((err) => {
|
|
191
|
+
this.socket.send(MessageIO.Error(requestId, ErrorCode.Err, nullHeaders, err));
|
|
192
|
+
this._cancellationTokenSources.delete(requestId);
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
const payload = processor.serializeResult(result);
|
|
196
|
+
this.socket.send(MessageIO.Response(requestId, nullHeaders, payload));
|
|
197
|
+
this._cancellationTokenSources.delete(requestId);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
onRequest<T = any>(method: string, handler: TGenericRequestHandler<T>): IDisposable {
|
|
202
|
+
const handlerWrapper = (requestId: number, method: string, headers: Record<string, any>, args: any[]) => {
|
|
203
|
+
this.runRequestHandler(requestId, method, args, handler);
|
|
204
|
+
};
|
|
205
|
+
return this._requestEmitter.on(method, handlerWrapper);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
onRequestNotFound(handler: TOnRequestNotFoundHandler): IDisposable {
|
|
209
|
+
const handlerWrapper = (requestId: number, method: string, headers: Record<string, any>, args: any[]) => {
|
|
210
|
+
this.runRequestHandler(requestId, method, [method, args], handler);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return this._requestEmitter.on(star, handlerWrapper);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
setProtocolRepository(protocolRepository: ProtocolRepository) {
|
|
217
|
+
this.protocolRepository = protocolRepository;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
listen() {
|
|
221
|
+
const toDispose = this.socket.onMessage((data) => {
|
|
222
|
+
reader.reset(data);
|
|
223
|
+
// skip version, currently only have version 1
|
|
224
|
+
reader.skip(1);
|
|
225
|
+
|
|
226
|
+
const rpcType = reader.uint8();
|
|
227
|
+
|
|
228
|
+
const requestId = reader.uint32();
|
|
229
|
+
const codec = reader.uint8();
|
|
230
|
+
|
|
231
|
+
if (this._timeoutHandles.has(requestId)) {
|
|
232
|
+
// Ignore some jest test scenarios where clearTimeout is not defined.
|
|
233
|
+
if (typeof clearTimeout === 'function') {
|
|
234
|
+
// @ts-ignore
|
|
235
|
+
clearTimeout(this._timeoutHandles.get(requestId));
|
|
236
|
+
}
|
|
237
|
+
this._timeoutHandles.delete(requestId);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
switch (rpcType) {
|
|
241
|
+
case OperationType.Response: {
|
|
242
|
+
const callback = this._callbacks.get(requestId);
|
|
243
|
+
if (!callback) {
|
|
244
|
+
this.logger.error(`Cannot find callback for request ${requestId}`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this._callbacks.delete(requestId);
|
|
249
|
+
|
|
250
|
+
const status = reader.uint16();
|
|
251
|
+
// const headers = headerSerializer.read();
|
|
252
|
+
|
|
253
|
+
// if error code is not 0, it's an error
|
|
254
|
+
if (status === ErrorCode.Err) {
|
|
255
|
+
// TODO: use binary codec
|
|
256
|
+
assert(codec === BodyCodec.JSON, 'Error response should be JSON encoded');
|
|
257
|
+
const content = reader.stringOfVarUInt32();
|
|
258
|
+
const error = parseError(content);
|
|
259
|
+
callback(nullHeaders, error);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (codec === BodyCodec.Binary) {
|
|
264
|
+
const contentLen = reader.varUInt32();
|
|
265
|
+
const buffer = reader.buffer(contentLen);
|
|
266
|
+
callback(nullHeaders, undefined, buffer);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const content = reader.stringOfVarUInt32();
|
|
271
|
+
if (codec === BodyCodec.JSON) {
|
|
272
|
+
callback(nullHeaders, undefined, JSON.parse(content));
|
|
273
|
+
} else {
|
|
274
|
+
callback(nullHeaders, undefined, content);
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case OperationType.Notification:
|
|
279
|
+
// fall through
|
|
280
|
+
case OperationType.Request: {
|
|
281
|
+
const method = reader.stringOfVarUInt32();
|
|
282
|
+
const headers = requestHeadersSerializer.read() as IRequestHeaders;
|
|
283
|
+
|
|
284
|
+
const contentLen = reader.varUInt32();
|
|
285
|
+
const content = reader.buffer(contentLen);
|
|
286
|
+
const processor = this.protocolRepository.getProcessor(method);
|
|
287
|
+
|
|
288
|
+
const args = processor.deserializeRequest(content);
|
|
289
|
+
|
|
290
|
+
this._receiveRequest(rpcType, requestId, method, headers, args);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case OperationType.Cancel: {
|
|
294
|
+
const cancellationTokenSource = this._cancellationTokenSources.get(requestId);
|
|
295
|
+
if (cancellationTokenSource) {
|
|
296
|
+
cancellationTokenSource.cancel();
|
|
297
|
+
} else {
|
|
298
|
+
this._knownCanceledRequests.add(requestId);
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
default: {
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
if (toDispose) {
|
|
308
|
+
this.disposable.push(toDispose);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
dispose(): void {
|
|
313
|
+
this.disposable.dispose();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
protected _receiveRequest(rpcType: number, requestId: number, method: string, headers: IRequestHeaders, args: any[]) {
|
|
317
|
+
const cancelable = headers.cancelable;
|
|
318
|
+
if (cancelable) {
|
|
319
|
+
const tokenSource = new CancellationTokenSource();
|
|
320
|
+
this._cancellationTokenSources.set(requestId, tokenSource);
|
|
321
|
+
args.push(tokenSource.token);
|
|
322
|
+
|
|
323
|
+
if (this._knownCanceledRequests.has(requestId)) {
|
|
324
|
+
tokenSource.cancel();
|
|
325
|
+
this._knownCanceledRequests.delete(requestId);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (rpcType === OperationType.Request) {
|
|
330
|
+
const eventName = this._requestEmitter.hasListener(method) ? method : star;
|
|
331
|
+
this._requestEmitter.emit(eventName, requestId, method, headers, args);
|
|
332
|
+
} else {
|
|
333
|
+
const eventName = this._notificationEmitter.hasListener(method) ? method : star;
|
|
334
|
+
this._notificationEmitter.emit(eventName, requestId, method, headers, args);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
static forWSWebSocket(socket: WebSocket, options: ISumiConnectionOptions = {}) {
|
|
339
|
+
return new SumiConnection(new WSWebSocketConnection(socket), options);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
static forNetSocket(socket: net.Socket, options: ISumiConnectionOptions = {}) {
|
|
343
|
+
return new SumiConnection(new NetSocketConnection(socket), options);
|
|
344
|
+
}
|
|
345
|
+
}
|