@celljs/rpc-core 3.0.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/rpc.js ADDED
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.transformErrorForSerialization = exports.RPCImpl = void 0;
5
+ const disposable_1 = require("@celljs/core/lib/common/utils/disposable");
6
+ const promise_util_1 = require("@celljs/core/lib/common/utils/promise-util");
7
+ const cancellation_1 = require("@celljs/core/lib/common/utils/cancellation");
8
+ const rpc_protocol_1 = require("./rpc-protocol");
9
+ const rpc_multiplexer_1 = require("./rpc-multiplexer");
10
+ function isBoolean(value) {
11
+ return value === true || value === false;
12
+ }
13
+ function isCancellationToken(value) {
14
+ const candidate = value;
15
+ return (candidate &&
16
+ (candidate === cancellation_1.CancellationToken.None ||
17
+ candidate === cancellation_1.CancellationToken.Cancelled ||
18
+ (isBoolean(candidate.isCancellationRequested) && !!candidate.onCancellationRequested)));
19
+ }
20
+ class RPCImpl {
21
+ constructor(connection, transformations) {
22
+ this.locals = new Map();
23
+ this.proxies = new Map();
24
+ this.lastMessageId = 0;
25
+ this.cancellationTokenSources = new Map();
26
+ this.pendingRPCReplies = new Map();
27
+ this.readyDeferred = new promise_util_1.Deferred();
28
+ this.toDispose = new disposable_1.DisposableCollection(disposable_1.Disposable.create(() => {
29
+ /* mark as no disposed */
30
+ }));
31
+ this.toDispose.push((this.multiplexer = new rpc_multiplexer_1.RPCMultiplexer(connection)));
32
+ this.multiplexer.onMessage(msg => this.receiveOneMessage(msg));
33
+ this.toDispose.push(disposable_1.Disposable.create(() => {
34
+ this.proxies.clear();
35
+ for (const reply of this.pendingRPCReplies.values()) {
36
+ reply.reject(rpc_protocol_1.ConnectionClosedError.create());
37
+ }
38
+ this.pendingRPCReplies.clear();
39
+ }));
40
+ this.reviver = (transformations === null || transformations === void 0 ? void 0 : transformations.reviver) || rpc_protocol_1.ObjectsTransferrer.reviver;
41
+ this.replacer = (transformations === null || transformations === void 0 ? void 0 : transformations.replacer) || rpc_protocol_1.ObjectsTransferrer.replacer;
42
+ this.connect();
43
+ }
44
+ async connect() {
45
+ let count = 0;
46
+ const task = setInterval(() => {
47
+ const callId = String(++this.lastMessageId);
48
+ this.multiplexer.send(this.open(callId));
49
+ count++;
50
+ if (count > 300) {
51
+ clearInterval(task);
52
+ }
53
+ }, 500);
54
+ await this.readyDeferred.promise;
55
+ clearInterval(task);
56
+ }
57
+ get isDisposed() {
58
+ return this.toDispose.disposed;
59
+ }
60
+ dispose() {
61
+ this.toDispose.dispose();
62
+ }
63
+ getProxy(proxyId) {
64
+ if (this.isDisposed) {
65
+ throw rpc_protocol_1.ConnectionClosedError.create();
66
+ }
67
+ let proxy = this.proxies.get(proxyId.id);
68
+ if (!proxy) {
69
+ proxy = this.createProxy(proxyId.id);
70
+ this.proxies.set(proxyId.id, proxy);
71
+ }
72
+ return proxy;
73
+ }
74
+ getLocal(proxyId) {
75
+ if (this.isDisposed) {
76
+ throw rpc_protocol_1.ConnectionClosedError.create();
77
+ }
78
+ return this.locals.get(proxyId.id);
79
+ }
80
+ set(identifier, instance) {
81
+ if (this.isDisposed) {
82
+ throw rpc_protocol_1.ConnectionClosedError.create();
83
+ }
84
+ this.locals.set(identifier.id, instance);
85
+ if (disposable_1.Disposable.is(instance)) {
86
+ this.toDispose.push(instance);
87
+ }
88
+ this.toDispose.push(disposable_1.Disposable.create(() => this.locals.delete(identifier.id)));
89
+ return instance;
90
+ }
91
+ createProxy(proxyId) {
92
+ const handler = {
93
+ get: (target, name) => {
94
+ if (!target[name]) {
95
+ target[name] = (...myArgs) => this.remoteCall(proxyId, name, myArgs);
96
+ }
97
+ return target[name];
98
+ },
99
+ };
100
+ return new Proxy(Object.create(null), handler); // eslint-disable-line no-null/no-null
101
+ }
102
+ remoteCall(proxyId, methodName, args) {
103
+ if (this.isDisposed) {
104
+ return Promise.reject(rpc_protocol_1.ConnectionClosedError.create());
105
+ }
106
+ return this.readyDeferred.promise.then(() => {
107
+ const cancellationToken = args.length && isCancellationToken(args[args.length - 1]) ? args.pop() : undefined;
108
+ if (cancellationToken && cancellationToken.isCancellationRequested) {
109
+ return Promise.reject(canceled());
110
+ }
111
+ const callId = String(++this.lastMessageId);
112
+ const result = new promise_util_1.Deferred();
113
+ if (cancellationToken) {
114
+ args.push('add.cancellation.token');
115
+ cancellationToken.onCancellationRequested(() => this.multiplexer.send(this.cancel(callId)));
116
+ }
117
+ this.pendingRPCReplies.set(callId, result);
118
+ this.multiplexer.send(this.request(callId, proxyId, methodName, args));
119
+ return result.promise;
120
+ });
121
+ }
122
+ receiveOneMessage(rawmsg) {
123
+ if (this.isDisposed) {
124
+ return;
125
+ }
126
+ try {
127
+ const msg = JSON.parse(rawmsg, this.reviver);
128
+ switch (msg.type) {
129
+ case 1 /* MessageType.Request */:
130
+ this.receiveRequest(msg);
131
+ break;
132
+ case 2 /* MessageType.Reply */:
133
+ this.receiveReply(msg);
134
+ break;
135
+ case 3 /* MessageType.ReplyErr */:
136
+ this.receiveReplyErr(msg);
137
+ break;
138
+ case 4 /* MessageType.Cancel */:
139
+ this.receiveCancel(msg);
140
+ break;
141
+ case 7 /* MessageType.Open */:
142
+ this.receiveOpen(msg);
143
+ break;
144
+ case 8 /* MessageType.Ready */:
145
+ this.receiveReady(msg);
146
+ break;
147
+ }
148
+ }
149
+ catch (e) {
150
+ // exception does not show problematic content: log it!
151
+ console.log('failed to parse message: ' + rawmsg);
152
+ throw e;
153
+ }
154
+ }
155
+ receiveOpen(msg) {
156
+ this.multiplexer.send(this.replyReady(msg.id));
157
+ }
158
+ receiveReady(msg) {
159
+ this.readyDeferred.resolve();
160
+ }
161
+ receiveCancel(msg) {
162
+ const cancellationTokenSource = this.cancellationTokenSources.get(msg.id);
163
+ if (cancellationTokenSource) {
164
+ cancellationTokenSource.cancel();
165
+ }
166
+ }
167
+ receiveRequest(msg) {
168
+ const callId = msg.id;
169
+ const proxyId = msg.proxyId;
170
+ // convert `null` to `undefined`, since we don't use `null` in internal plugin APIs
171
+ const args = msg.args.map(arg => (arg === null ? undefined : arg)); // eslint-disable-line no-null/no-null
172
+ const addToken = args.length && args[args.length - 1] === 'add.cancellation.token' ? args.pop() : false;
173
+ if (addToken) {
174
+ const tokenSource = new cancellation_1.CancellationTokenSource();
175
+ this.cancellationTokenSources.set(callId, tokenSource);
176
+ args.push(tokenSource.token);
177
+ }
178
+ const invocation = this.invokeHandler(proxyId, msg.method, args);
179
+ invocation.then(result => {
180
+ this.cancellationTokenSources.delete(callId);
181
+ this.multiplexer.send(this.replyOK(callId, result));
182
+ }, error => {
183
+ this.cancellationTokenSources.delete(callId);
184
+ this.multiplexer.send(this.replyErr(callId, error));
185
+ });
186
+ }
187
+ receiveReply(msg) {
188
+ const callId = msg.id;
189
+ const pendingReply = this.pendingRPCReplies.get(callId);
190
+ if (!pendingReply) {
191
+ return;
192
+ }
193
+ this.pendingRPCReplies.delete(callId);
194
+ pendingReply.resolve(msg.res);
195
+ }
196
+ receiveReplyErr(msg) {
197
+ const callId = msg.id;
198
+ const pendingReply = this.pendingRPCReplies.get(callId);
199
+ if (!pendingReply) {
200
+ return;
201
+ }
202
+ this.pendingRPCReplies.delete(callId);
203
+ let err = undefined;
204
+ if (msg.err && msg.err.$isError) {
205
+ err = new Error();
206
+ err.name = msg.err.name;
207
+ err.message = msg.err.message;
208
+ err.stack = msg.err.stack;
209
+ }
210
+ pendingReply.reject(err);
211
+ }
212
+ invokeHandler(proxyId, methodName, args) {
213
+ try {
214
+ return Promise.resolve(this.doInvokeHandler(proxyId, methodName, args));
215
+ }
216
+ catch (err) {
217
+ return Promise.reject(err);
218
+ }
219
+ }
220
+ doInvokeHandler(proxyId, methodName, args) {
221
+ const actor = this.locals.get(proxyId);
222
+ if (!actor) {
223
+ throw new Error('Unknown actor ' + proxyId);
224
+ }
225
+ const method = actor[methodName];
226
+ if (typeof method !== 'function') {
227
+ throw new Error('Unknown method ' + methodName + ' on actor ' + proxyId);
228
+ }
229
+ return method.apply(actor, args);
230
+ }
231
+ cancel(req) {
232
+ return `{"type":${4 /* MessageType.Cancel */},"id":"${req}"}`;
233
+ }
234
+ open(req) {
235
+ return `{"type":${7 /* MessageType.Open */},"id":"${req}"}`;
236
+ }
237
+ request(req, rpcId, method, args) {
238
+ return `{"type":${1 /* MessageType.Request */},"id":"${req}","proxyId":"${rpcId}","method":"${method}","args":${JSON.stringify(args, this.replacer)}}`;
239
+ }
240
+ replyReady(req) {
241
+ return `{"type":${8 /* MessageType.Ready */},"id":"${req}"}`;
242
+ }
243
+ replyOK(req, res) {
244
+ if (typeof res === 'undefined') {
245
+ return `{"type":${2 /* MessageType.Reply */},"id":"${req}"}`;
246
+ }
247
+ return `{"type":${2 /* MessageType.Reply */},"id":"${req}","res":${safeStringify(res, this.replacer)}}`;
248
+ }
249
+ replyErr(req, err) {
250
+ err = typeof err === 'string' ? new Error(err) : err;
251
+ if (err instanceof Error) {
252
+ return `{"type":${3 /* MessageType.ReplyErr */},"id":"${req}","err":${safeStringify(transformErrorForSerialization(err))}}`;
253
+ }
254
+ return `{"type":${3 /* MessageType.ReplyErr */},"id":"${req}","err":null}`;
255
+ }
256
+ }
257
+ exports.RPCImpl = RPCImpl;
258
+ function canceled() {
259
+ const error = new Error('Canceled');
260
+ error.name = error.message;
261
+ return error;
262
+ }
263
+ function transformErrorForSerialization(error) {
264
+ if (error instanceof Error) {
265
+ const { name, message } = error;
266
+ const stack = error.stacktrace || error.stack;
267
+ return {
268
+ $isError: true,
269
+ name,
270
+ message,
271
+ stack,
272
+ };
273
+ }
274
+ // return as is
275
+ return error;
276
+ }
277
+ exports.transformErrorForSerialization = transformErrorForSerialization;
278
+ function safeStringify(obj, replacer) {
279
+ try {
280
+ return JSON.stringify(obj, replacer);
281
+ }
282
+ catch (err) {
283
+ console.error('error stringifying response: ', err);
284
+ return 'null';
285
+ }
286
+ }
287
+ //# sourceMappingURL=rpc.js.map
package/lib/rpc.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@celljs/rpc-core",
3
+ "version": "3.0.0",
4
+ "description": "",
5
+ "main": "lib/index.js",
6
+ "typings": "lib/index.d.ts",
7
+ "dependencies": {
8
+ "@celljs/core": "3.0.0"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "keywords": [
14
+ "cell-component"
15
+ ],
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/cellbang/cell.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/cellbang/cell/issues"
23
+ },
24
+ "homepage": "https://github.com/cellbang/cell",
25
+ "files": [
26
+ "lib",
27
+ "src",
28
+ "cell.yml"
29
+ ],
30
+ "scripts": {
31
+ "lint": "cell-component lint",
32
+ "build": "cell-component build",
33
+ "watch": "cell-component watch",
34
+ "clean": "cell-component clean",
35
+ "test": "cell-component test:js"
36
+ },
37
+ "devDependencies": {
38
+ "@celljs/component": "3.0.0"
39
+ },
40
+ "gitHead": "c0ef8d269e33a795406bcbb240cac4b845c6c24c"
41
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './rpc-multiplexer';
2
+ export * from './rpc-protocol';
3
+ export * from './rpc';
@@ -0,0 +1,4 @@
1
+ describe('rpc core package', () => {
2
+
3
+ it('support code coverage statistics', () => {});
4
+ });
@@ -0,0 +1,65 @@
1
+ import { Event } from '@celljs/core/lib/common/utils/event';
2
+ import { Emitter } from '@celljs/core/lib/common/utils/emitter';
3
+ import { DisposableCollection, Disposable } from '@celljs/core/lib/common/utils/disposable';
4
+ import { ConnectionClosedError, MessageConnection } from './rpc-protocol';
5
+
6
+ /**
7
+ * Sends/Receives multiple messages in one go:
8
+ * - multiple messages to be sent from one stack get sent in bulk at `process.nextTick`.
9
+ * - each incoming message is handled in a separate `process.nextTick`.
10
+ */
11
+ export class RPCMultiplexer implements Disposable, MessageConnection {
12
+ private readonly connection: MessageConnection;
13
+ private readonly sendAccumulatedBound: () => void;
14
+
15
+ private messagesToSend: string[];
16
+
17
+ private readonly messageEmitter = new Emitter<string>();
18
+ private readonly toDispose = new DisposableCollection();
19
+
20
+ constructor(connection: MessageConnection) {
21
+ this.connection = connection;
22
+ this.sendAccumulatedBound = this.sendAccumulated.bind(this);
23
+
24
+ this.toDispose.push(Disposable.create(() => (this.messagesToSend = [])));
25
+ this.toDispose.push(
26
+ this.connection.onMessage((msg: string) => {
27
+ try {
28
+ const messages = JSON.parse(msg);
29
+ for (const message of messages) {
30
+ this.messageEmitter.fire(message);
31
+ }
32
+ } catch (e) {
33
+ // NoOp
34
+ }
35
+ })
36
+ );
37
+ this.toDispose.push(this.messageEmitter);
38
+
39
+ this.messagesToSend = [];
40
+ }
41
+
42
+ dispose(): void {
43
+ this.toDispose.dispose();
44
+ }
45
+
46
+ get onMessage(): Event<string> {
47
+ return this.messageEmitter.event;
48
+ }
49
+
50
+ private sendAccumulated(): void {
51
+ const tmp = this.messagesToSend;
52
+ this.messagesToSend = [];
53
+ this.connection.send(JSON.stringify(tmp));
54
+ }
55
+
56
+ public send(msg: string): void {
57
+ if (this.toDispose.disposed) {
58
+ throw ConnectionClosedError.create();
59
+ }
60
+ if (this.messagesToSend.length === 0) {
61
+ setTimeout(this.sendAccumulatedBound, 0);
62
+ }
63
+ this.messagesToSend.push(msg);
64
+ }
65
+ }
@@ -0,0 +1,137 @@
1
+ import { Disposable } from '@celljs/core/lib/common/utils/disposable';
2
+ import { CustomError } from '@celljs/core/lib/common/error';
3
+
4
+ import { Event } from '@celljs/core/lib/common/utils/event';
5
+ export { CancellationTokenSource } from '@celljs/core/lib/common/utils/cancellation';
6
+
7
+ export class ProxyIdentifier<T> {
8
+ public readonly id: string;
9
+ constructor(public readonly isMain: boolean, id: string | T) {
10
+ // TODO this is nasty, rewrite this
11
+ this.id = (id as any).toString();
12
+ }
13
+ }
14
+
15
+ export function createProxyIdentifier<T>(identifier: string): ProxyIdentifier<T> {
16
+ return new ProxyIdentifier(false, identifier);
17
+ }
18
+
19
+ export interface MessageConnection {
20
+ send(msg: string): void;
21
+ onMessage: Event<string>;
22
+ }
23
+
24
+ export const RPC = Symbol('RPC');
25
+ export interface RPC extends Disposable {
26
+ /**
27
+ * Returns a proxy to an object addressable/named in the iframe window or in the main window.
28
+ */
29
+ getProxy<T>(proxyId: ProxyIdentifier<T>): T;
30
+
31
+ /**
32
+ * Returns a local to an object addressable/named in the iframe window or in the main window.
33
+ */
34
+ getLocal<T>(proxyId: ProxyIdentifier<T>): T;
35
+
36
+ /**
37
+ * Register manually created instance.
38
+ */
39
+ set<T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R;
40
+ }
41
+
42
+ export interface ConnectionClosedError extends CustomError {
43
+ code: 'RPC_PROTOCOL_CLOSED';
44
+ }
45
+ export namespace ConnectionClosedError {
46
+ const code: ConnectionClosedError['code'] = 'RPC_PROTOCOL_CLOSED';
47
+ export function create(message: string = 'connection is closed'): ConnectionClosedError {
48
+ return Object.assign(new Error(message), { code });
49
+ }
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ export function is(error: any): error is ConnectionClosedError {
52
+ return !!error && typeof error === 'object' && 'code' in error && error['code'] === code;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * These functions are responsible for correct transferring objects via rpc channel.
58
+ *
59
+ * To reach that some specific kind of objects is converted to json in some custom way
60
+ * and then, after receiving, revived to objects again,
61
+ * so there is feeling that object was transferred via rpc channel.
62
+ *
63
+ * To distinguish between regular and altered objects, field $type is added to altered ones.
64
+ * Also value of that field specifies kind of the object.
65
+ */
66
+ export namespace ObjectsTransferrer {
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ export function replacer(key: string | undefined, value: any): any {
69
+ return value;
70
+ }
71
+
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ export function reviver(key: string | undefined, value: any): any {
74
+ return value;
75
+ }
76
+ }
77
+
78
+ export const enum MessageType {
79
+ Request = 1,
80
+ Reply = 2,
81
+ ReplyErr = 3,
82
+ Cancel = 4,
83
+ Terminate = 5,
84
+ Terminated = 6,
85
+ Open = 7,
86
+ Ready = 8
87
+ }
88
+
89
+ export class OpenMessage {
90
+ type: MessageType.Open;
91
+ id: string;
92
+ channalId: number;
93
+ }
94
+
95
+ export class ReadyMessage {
96
+ type: MessageType.Ready;
97
+ id: string;
98
+ channalId: number;
99
+ }
100
+
101
+ export class CancelMessage {
102
+ type: MessageType.Cancel;
103
+ id: string;
104
+ channalId: number;
105
+ }
106
+
107
+ export class RequestMessage {
108
+ type: MessageType.Request;
109
+ id: string;
110
+ channalId: number;
111
+ proxyId: string;
112
+ method: string;
113
+ args: any[];
114
+ }
115
+
116
+ export class ReplyMessage {
117
+ type: MessageType.Reply;
118
+ id: string;
119
+ channalId: number;
120
+ res: any;
121
+ }
122
+
123
+ export class ReplyErrMessage {
124
+ type: MessageType.ReplyErr;
125
+ id: string;
126
+ channalId: number;
127
+ err: SerializedError;
128
+ }
129
+
130
+ export type RPCMessage = RequestMessage | ReplyMessage | ReplyErrMessage | CancelMessage | OpenMessage | ReadyMessage;
131
+
132
+ export interface SerializedError {
133
+ readonly $isError: true;
134
+ readonly name: string;
135
+ readonly message: string;
136
+ readonly stack: string;
137
+ }