libshv-js 3.11.1 → 3.12.1
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 +1 -1
- package/src/rpcmessage.ts +4 -1
- package/src/ws-client.ts +214 -105
package/package.json
CHANGED
package/src/rpcmessage.ts
CHANGED
|
@@ -9,6 +9,7 @@ export const RPC_MESSAGE_PARAMS = 1;
|
|
|
9
9
|
export const RPC_MESSAGE_RESULT = 2;
|
|
10
10
|
export const RPC_MESSAGE_ERROR = 3;
|
|
11
11
|
export const RPC_MESSAGE_DELAY = 4;
|
|
12
|
+
export const RPC_MESSAGE_ABORT = 5;
|
|
12
13
|
|
|
13
14
|
export const ERROR_CODE = 1;
|
|
14
15
|
export const ERROR_MESSAGE = 2;
|
|
@@ -46,7 +47,9 @@ const RpcRequestMetaZod = z.metamap({
|
|
|
46
47
|
|
|
47
48
|
const RpcRequestValueZod = z.imap({
|
|
48
49
|
[RPC_MESSAGE_PARAMS]: z.rpcvalue().optional(),
|
|
49
|
-
})
|
|
50
|
+
}).or(z.imap({
|
|
51
|
+
[RPC_MESSAGE_ABORT]: z.boolean(),
|
|
52
|
+
}));
|
|
50
53
|
|
|
51
54
|
const RpcResponseMetaZod = z.metamap({
|
|
52
55
|
[RPC_MESSAGE_CALLER_IDS]: z.int().or(z.array(z.int())).optional(),
|
package/src/ws-client.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ChainPackReader, CHAINPACK_PROTOCOL_TYPE, ChainPackWriter, toChainPack} from './chainpack';
|
|
2
2
|
import {type CponReader, CPON_PROTOCOL_TYPE, toCpon} from './cpon';
|
|
3
|
-
import {ERROR_MESSAGE, ErrorCode, ERROR_CODE, RpcMessageZod, type RpcMessage, isSignal, isRequest, type RpcRequest, isResponse, ERROR_DATA, type ErrorMap, RPC_MESSAGE_METHOD, RPC_MESSAGE_SHV_PATH, RPC_MESSAGE_REQUEST_ID, RPC_MESSAGE_PARAMS, RPC_MESSAGE_ERROR, RPC_MESSAGE_RESULT, RPC_MESSAGE_CALLER_IDS, RpcResponseValue, RPC_MESSAGE_DELAY} from './rpcmessage';
|
|
3
|
+
import {ERROR_MESSAGE, ErrorCode, ERROR_CODE, RpcMessageZod, type RpcMessage, isSignal, isRequest, type RpcRequest, isResponse, ERROR_DATA, type ErrorMap, RPC_MESSAGE_METHOD, RPC_MESSAGE_SHV_PATH, RPC_MESSAGE_REQUEST_ID, RPC_MESSAGE_PARAMS, RPC_MESSAGE_ERROR, RPC_MESSAGE_RESULT, RPC_MESSAGE_CALLER_IDS, RpcResponseValue, RPC_MESSAGE_DELAY, RPC_MESSAGE_ABORT, RpcSignal, RpcResponse} from './rpcmessage';
|
|
4
4
|
import {type RpcValue, type Null, type Int, type IMap, type ShvMap, makeMap, makeIMap, RpcValueWithMetaData, makeMetaMap, Double} from './rpcvalue';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_TIMEOUT = 5000;
|
|
@@ -50,6 +50,16 @@ type WsClientOptionsCommon = {
|
|
|
50
50
|
wsUri: string;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
export class RequestHandler {
|
|
54
|
+
constructor(public options: {
|
|
55
|
+
result: Promise<RpcValue>;
|
|
56
|
+
onAbort?: () => void;
|
|
57
|
+
onProgressQuery?: () => number | Promise<number>;
|
|
58
|
+
}) {
|
|
59
|
+
/* nothing */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
type WsClientOptionsLogin = WsClientOptionsCommon & {
|
|
54
64
|
mountPoint?: string;
|
|
55
65
|
login: Login;
|
|
@@ -58,7 +68,7 @@ type WsClientOptionsLogin = WsClientOptionsCommon & {
|
|
|
58
68
|
onConnected: () => void;
|
|
59
69
|
onConnectionFailure: (error: Error) => void;
|
|
60
70
|
onDisconnected: () => void;
|
|
61
|
-
onRequest: (shvPath: string, method: string, param: RpcValue, delay: (progress: number) => void) => RpcValue | Promise<RpcValue
|
|
71
|
+
onRequest: (shvPath: string, method: string, param: RpcValue, delay: (progress: number) => void) => RpcValue | Promise<RpcValue> | RequestHandler;
|
|
62
72
|
};
|
|
63
73
|
|
|
64
74
|
type WsClientOptionsWorkflows = WsClientOptionsCommon & {
|
|
@@ -96,7 +106,25 @@ type DirResult = Array<IMap<{
|
|
|
96
106
|
|
|
97
107
|
class RpcError extends Error {
|
|
98
108
|
constructor(readonly err_info: ErrorMap) {
|
|
99
|
-
|
|
109
|
+
const errorCodeToMessage = (code: ErrorMap[typeof ERROR_CODE]) => {
|
|
110
|
+
switch (code) {
|
|
111
|
+
case ErrorCode.InvalidRequest: return 'InvalidRequest';
|
|
112
|
+
case ErrorCode.MethodNotFound: return 'MethodNotFound';
|
|
113
|
+
case ErrorCode.InvalidParams: return 'InvalidParams';
|
|
114
|
+
case ErrorCode.InternalError: return 'InternalError';
|
|
115
|
+
case ErrorCode.ParseError: return 'ParseError';
|
|
116
|
+
case ErrorCode.MethodCallTimeout: return 'MethodCallTimeout';
|
|
117
|
+
case ErrorCode.MethodCallCancelled: return 'MethodCallCancelled';
|
|
118
|
+
case ErrorCode.MethodCallException: return 'MethodCallException';
|
|
119
|
+
case ErrorCode.Unknown: return 'Unknown';
|
|
120
|
+
case ErrorCode.LoginRequired: return 'LoginRequired';
|
|
121
|
+
case ErrorCode.UserIDRequired: return 'UserIDRequired';
|
|
122
|
+
case ErrorCode.NotImplemented: return 'NotImplemented';
|
|
123
|
+
default: return 'Unknown RpcError';
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
super(err_info[ERROR_MESSAGE] ?? `${errorCodeToMessage(err_info[ERROR_CODE])} (${err_info[ERROR_CODE]})`);
|
|
100
128
|
}
|
|
101
129
|
|
|
102
130
|
data() {
|
|
@@ -137,13 +165,30 @@ export const UserIDRequired = createErrorClass(ErrorCode.UserIDRequired);
|
|
|
137
165
|
export const NotImplemented = createErrorClass(ErrorCode.NotImplemented);
|
|
138
166
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
139
167
|
|
|
168
|
+
const makeTimeout = (ms: number, resolve: RpcResponseResolver) => globalThis.setTimeout(() => {
|
|
169
|
+
resolve(new MethodCallTimeout(makeIMap({
|
|
170
|
+
[ERROR_CODE]: ErrorCode.MethodCallTimeout,
|
|
171
|
+
[ERROR_MESSAGE]: `Shv call timeout after: ${ms} msec.`,
|
|
172
|
+
[ERROR_DATA]: undefined,
|
|
173
|
+
})));
|
|
174
|
+
}, ms);
|
|
175
|
+
|
|
176
|
+
class RpcRequestPromise<Result> extends Promise<Result> {
|
|
177
|
+
constructor(executor: (resolve: (value: Result | PromiseLike<Result>) => void, reject: (reason?: unknown) => void) => void, public readonly abort: () => void, public readonly progressQuery: () => void) {
|
|
178
|
+
super(executor);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
140
182
|
class WsClient {
|
|
141
183
|
private requestId = 1;
|
|
142
184
|
private pingTimerId: ReturnType<typeof globalThis.setInterval> | undefined = undefined;
|
|
143
185
|
private rpcHandlers: Array<{
|
|
144
186
|
resolve: RpcResponseResolver;
|
|
187
|
+
delayCallback?: (progress: number) => void;
|
|
145
188
|
timeout_handle: ReturnType<typeof globalThis.setTimeout>;
|
|
146
189
|
}> = [];
|
|
190
|
+
private requestHandlers: RequestHandler[] = [];
|
|
191
|
+
private abortedRequests = new Set<number>();
|
|
147
192
|
private readonly subscriptions: Subscription[] = [];
|
|
148
193
|
private readonly websocket: WebSocket;
|
|
149
194
|
private readonly options: WsClientOptions;
|
|
@@ -160,105 +205,166 @@ class WsClient {
|
|
|
160
205
|
this.websocket = new WebSocket(options.wsUri);
|
|
161
206
|
this.websocket.binaryType = 'arraybuffer';
|
|
162
207
|
|
|
163
|
-
|
|
164
|
-
const
|
|
208
|
+
const handleSignal = (signal: RpcSignal) => {
|
|
209
|
+
for (const sub of this.subscriptions) {
|
|
210
|
+
const shvPath = signal.meta[RPC_MESSAGE_SHV_PATH];
|
|
211
|
+
const method = signal.meta[RPC_MESSAGE_METHOD];
|
|
165
212
|
|
|
166
|
-
|
|
167
|
-
|
|
213
|
+
if (shvPath.startsWith(sub.path) && method === sub.method) {
|
|
214
|
+
sub.callback(shvPath, method, signal.value[RPC_MESSAGE_PARAMS]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const handleRequest = async (request: RpcRequest) => {
|
|
220
|
+
if ('onRequest' in this.options) {
|
|
221
|
+
const requestId = request.meta[RPC_MESSAGE_REQUEST_ID];
|
|
222
|
+
const respond = (value: RpcResponseValue) => {
|
|
223
|
+
this.sendRpcMessage(new RpcValueWithMetaData(
|
|
224
|
+
makeMetaMap({
|
|
225
|
+
[RPC_MESSAGE_CALLER_IDS]: request.meta[RPC_MESSAGE_CALLER_IDS],
|
|
226
|
+
[RPC_MESSAGE_REQUEST_ID]: requestId,
|
|
227
|
+
}),
|
|
228
|
+
value,
|
|
229
|
+
));
|
|
230
|
+
};
|
|
168
231
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
232
|
+
const sendDelay = (progress: number) => {
|
|
233
|
+
respond(makeIMap({
|
|
234
|
+
[RPC_MESSAGE_DELAY]: new Double(progress),
|
|
235
|
+
}));
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
if (RPC_MESSAGE_ABORT in request.value) {
|
|
239
|
+
const requestHandler = this.requestHandlers[requestId];
|
|
240
|
+
|
|
241
|
+
if (request.value[RPC_MESSAGE_ABORT] === true && requestHandler?.options.onAbort !== undefined) {
|
|
242
|
+
this.abortedRequests.add(requestId);
|
|
243
|
+
requestHandler.options.onAbort();
|
|
244
|
+
}
|
|
173
245
|
|
|
174
|
-
if (
|
|
175
|
-
|
|
246
|
+
if (request.value[RPC_MESSAGE_ABORT] === false && requestHandler?.options.onProgressQuery !== undefined) {
|
|
247
|
+
const progress = requestHandler.options.onProgressQuery();
|
|
248
|
+
sendDelay(progress instanceof Promise ? await progress : progress);
|
|
176
249
|
}
|
|
250
|
+
|
|
251
|
+
return;
|
|
177
252
|
}
|
|
178
|
-
} else if (isRequest(rpcMsg)) {
|
|
179
|
-
if ('onRequest' in this.options) {
|
|
180
|
-
const respond = (value: RpcResponseValue) => {
|
|
181
|
-
this.sendRpcMessage(new RpcValueWithMetaData(
|
|
182
|
-
makeMetaMap({
|
|
183
|
-
[RPC_MESSAGE_CALLER_IDS]: rpcMsg.meta[RPC_MESSAGE_CALLER_IDS],
|
|
184
|
-
[RPC_MESSAGE_REQUEST_ID]: rpcMsg.meta[RPC_MESSAGE_REQUEST_ID],
|
|
185
|
-
}),
|
|
186
|
-
value,
|
|
187
|
-
));
|
|
188
|
-
};
|
|
189
253
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
254
|
+
try {
|
|
255
|
+
let result = this.options.onRequest(request.meta[RPC_MESSAGE_SHV_PATH], request.meta[RPC_MESSAGE_METHOD], request.value[RPC_MESSAGE_PARAMS], sendDelay);
|
|
256
|
+
if (result instanceof RequestHandler) {
|
|
257
|
+
this.requestHandlers[requestId] = result;
|
|
258
|
+
result = result.options.result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const resultOrError = makeIMap({
|
|
262
|
+
[RPC_MESSAGE_RESULT]: result instanceof Promise ? await result : result,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
if (!this.abortedRequests.has(requestId)) {
|
|
266
|
+
respond(resultOrError);
|
|
267
|
+
} else {
|
|
268
|
+
this.abortedRequests.delete(requestId);
|
|
269
|
+
}
|
|
196
270
|
|
|
197
|
-
|
|
271
|
+
if (requestId in this.requestHandlers) {
|
|
272
|
+
// eslint-disable-next-line @typescript-eslint/no-array-delete
|
|
273
|
+
delete this.requestHandlers[requestId];
|
|
274
|
+
}
|
|
275
|
+
} catch (error: unknown) {
|
|
276
|
+
const sendError = (error: RpcError) => {
|
|
198
277
|
respond(makeIMap({
|
|
199
|
-
[
|
|
278
|
+
[RPC_MESSAGE_ERROR]: error.err_info,
|
|
200
279
|
}));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
sendError(new InternalError(error.message));
|
|
214
|
-
break;
|
|
215
|
-
default:
|
|
216
|
-
sendError(new InternalError('Unknown error'));
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
switch (true) {
|
|
283
|
+
case error instanceof RpcError:
|
|
284
|
+
sendError(error);
|
|
285
|
+
break;
|
|
286
|
+
case error instanceof Error:
|
|
287
|
+
sendError(new InternalError(error.message));
|
|
288
|
+
break;
|
|
289
|
+
default:
|
|
290
|
+
sendError(new InternalError('Unknown error'));
|
|
291
|
+
break;
|
|
219
292
|
}
|
|
220
293
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
case ErrorCode.MethodCallTimeout: return MethodCallTimeout;
|
|
239
|
-
case ErrorCode.MethodCallCancelled: return MethodCallCancelled;
|
|
240
|
-
case ErrorCode.MethodCallException: return MethodCallException;
|
|
241
|
-
case ErrorCode.Unknown: return Unknown;
|
|
242
|
-
case ErrorCode.LoginRequired: return LoginRequired;
|
|
243
|
-
case ErrorCode.UserIDRequired: return UserIDRequired;
|
|
244
|
-
case ErrorCode.NotImplemented: return NotImplemented;
|
|
245
|
-
default: return Unknown;
|
|
246
|
-
}
|
|
247
|
-
})();
|
|
248
|
-
|
|
249
|
-
return new ErrorTypeCtor(rpcMsg.value[RPC_MESSAGE_ERROR]);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (RPC_MESSAGE_RESULT in rpcMsg.value) {
|
|
253
|
-
return rpcMsg.value[RPC_MESSAGE_RESULT];
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// If both result and error are missing, the result is implicitly Null.
|
|
257
|
-
// https://silicon-heaven.github.io/shv-doc/rpcmessage.html#response
|
|
258
|
-
})());
|
|
259
|
-
// eslint-disable-next-line @typescript-eslint/no-array-delete
|
|
260
|
-
delete this.rpcHandlers[Number(requestId)];
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const handleResponse = (response: RpcResponse) => {
|
|
298
|
+
const requestId = response.meta[RPC_MESSAGE_REQUEST_ID];
|
|
299
|
+
|
|
300
|
+
if (this.rpcHandlers[Number(requestId)] !== undefined) {
|
|
301
|
+
const handler = this.rpcHandlers[Number(requestId)];
|
|
302
|
+
clearTimeout(handler.timeout_handle);
|
|
303
|
+
|
|
304
|
+
if (RPC_MESSAGE_DELAY in response.value) {
|
|
305
|
+
if (handler.delayCallback !== undefined) {
|
|
306
|
+
handler.delayCallback(response.value[RPC_MESSAGE_DELAY].value);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
handler.timeout_handle = makeTimeout(this.timeout, handler.resolve);
|
|
310
|
+
return;
|
|
261
311
|
}
|
|
312
|
+
|
|
313
|
+
handler.resolve((() => {
|
|
314
|
+
if (RPC_MESSAGE_ERROR in response.value) {
|
|
315
|
+
const code = response.value[RPC_MESSAGE_ERROR][ERROR_CODE] as unknown;
|
|
316
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
317
|
+
const ErrorTypeCtor = (() => {
|
|
318
|
+
switch (code) {
|
|
319
|
+
case ErrorCode.InvalidRequest: return InvalidRequest;
|
|
320
|
+
case ErrorCode.MethodNotFound: return MethodNotFound;
|
|
321
|
+
case ErrorCode.InvalidParams: return InvalidParams;
|
|
322
|
+
case ErrorCode.InternalError: return InternalError;
|
|
323
|
+
case ErrorCode.ParseError: return ParseError;
|
|
324
|
+
case ErrorCode.MethodCallTimeout: return MethodCallTimeout;
|
|
325
|
+
case ErrorCode.MethodCallCancelled: return MethodCallCancelled;
|
|
326
|
+
case ErrorCode.MethodCallException: return MethodCallException;
|
|
327
|
+
case ErrorCode.Unknown: return Unknown;
|
|
328
|
+
case ErrorCode.LoginRequired: return LoginRequired;
|
|
329
|
+
case ErrorCode.UserIDRequired: return UserIDRequired;
|
|
330
|
+
case ErrorCode.NotImplemented: return NotImplemented;
|
|
331
|
+
default: return Unknown;
|
|
332
|
+
}
|
|
333
|
+
})();
|
|
334
|
+
|
|
335
|
+
return new ErrorTypeCtor(response.value[RPC_MESSAGE_ERROR]);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (RPC_MESSAGE_RESULT in response.value) {
|
|
339
|
+
return response.value[RPC_MESSAGE_RESULT];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// At this point, the RpcResponse either has:
|
|
343
|
+
// - no keys, which means that the response has an implicit Null result.
|
|
344
|
+
// - has some unknown keys, in which case we will produce an error for the client.
|
|
345
|
+
// https://silicon-heaven.github.io/shv-doc/rpcmessage.html#response
|
|
346
|
+
const rpcMessageKeys = Object.keys(response.value);
|
|
347
|
+
if (rpcMessageKeys.length !== 0) {
|
|
348
|
+
return new NotImplemented(`Got an RpcResponse with unsupported keys: ${rpcMessageKeys.join(' ')}`);
|
|
349
|
+
}
|
|
350
|
+
})());
|
|
351
|
+
// eslint-disable-next-line @typescript-eslint/no-array-delete
|
|
352
|
+
delete this.rpcHandlers[Number(requestId)];
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
this.websocket.addEventListener('message', async (evt: MessageEvent<ArrayBuffer>) => {
|
|
357
|
+
const rpcVal = dataToRpcValue(evt.data);
|
|
358
|
+
|
|
359
|
+
const rpcMsg = RpcMessageZod.parse(rpcVal);
|
|
360
|
+
this.logDebug(`message received: ${toCpon(rpcMsg)}`);
|
|
361
|
+
|
|
362
|
+
if (isSignal(rpcMsg)) {
|
|
363
|
+
handleSignal(rpcMsg);
|
|
364
|
+
} else if (isRequest(rpcMsg)) {
|
|
365
|
+
await handleRequest(rpcMsg);
|
|
366
|
+
} else if (isResponse(rpcMsg)) {
|
|
367
|
+
handleResponse(rpcMsg);
|
|
262
368
|
}
|
|
263
369
|
});
|
|
264
370
|
|
|
@@ -274,31 +380,34 @@ class WsClient {
|
|
|
274
380
|
}
|
|
275
381
|
}
|
|
276
382
|
|
|
277
|
-
callRpcMethod(shvPath: '.broker/currentClient', method: 'accessGrantForMethodCall', params: [string, string]):
|
|
278
|
-
callRpcMethod(shvPath: string | undefined, method: 'dir', params?: RpcValue):
|
|
279
|
-
callRpcMethod(shvPath: string | undefined, method: 'ls', params?: RpcValue):
|
|
280
|
-
callRpcMethod(shvPath: string | undefined, method: string, params?: RpcValue):
|
|
281
|
-
callRpcMethod(shvPath: string | undefined, method: string, params?: RpcValue):
|
|
383
|
+
callRpcMethod(shvPath: '.broker/currentClient', method: 'accessGrantForMethodCall', params: [string, string], delayCallback?: (progress: number) => void): RpcRequestPromise<ResultOrError<string>>;
|
|
384
|
+
callRpcMethod(shvPath: string | undefined, method: 'dir', params?: RpcValue, delayCallback?: (progress: number) => void): RpcRequestPromise<ResultOrError<DirResult>>;
|
|
385
|
+
callRpcMethod(shvPath: string | undefined, method: 'ls', params?: RpcValue, delayCallback?: (progress: number) => void): RpcRequestPromise<ResultOrError<LsResult>>;
|
|
386
|
+
callRpcMethod(shvPath: string | undefined, method: string, params?: RpcValue, delayCallback?: (progress: number) => void): RpcRequestPromise<ResultOrError>;
|
|
387
|
+
callRpcMethod(shvPath: string | undefined, method: string, params?: RpcValue, delayCallback?: (progress: number) => void): RpcRequestPromise<ResultOrError> {
|
|
282
388
|
const rqId = this.requestId++;
|
|
283
|
-
const
|
|
389
|
+
const makeRq = (value: IMap) => new RpcValueWithMetaData(makeMetaMap({
|
|
284
390
|
[RPC_MESSAGE_CALLER_IDS]: undefined,
|
|
285
391
|
[RPC_MESSAGE_REQUEST_ID]: rqId,
|
|
286
392
|
[RPC_MESSAGE_METHOD]: method ?? '',
|
|
287
393
|
[RPC_MESSAGE_SHV_PATH]: shvPath ?? '',
|
|
288
|
-
}),
|
|
394
|
+
}), value);
|
|
395
|
+
const rq: RpcRequest = makeRq(makeIMap({
|
|
289
396
|
[RPC_MESSAGE_PARAMS]: params,
|
|
290
397
|
}));
|
|
291
398
|
|
|
292
399
|
this.sendRpcMessage(rq);
|
|
293
400
|
|
|
294
|
-
const promise = new
|
|
295
|
-
this.rpcHandlers[rqId] = {resolve, timeout_handle:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
401
|
+
const promise = new RpcRequestPromise<ResultOrError>(resolve => {
|
|
402
|
+
this.rpcHandlers[rqId] = {resolve, timeout_handle: makeTimeout(this.timeout, resolve), delayCallback};
|
|
403
|
+
}, () => {
|
|
404
|
+
this.sendRpcMessage(makeRq(makeIMap({
|
|
405
|
+
[RPC_MESSAGE_ABORT]: true,
|
|
406
|
+
})));
|
|
407
|
+
}, () => {
|
|
408
|
+
this.sendRpcMessage(makeRq(makeIMap({
|
|
409
|
+
[RPC_MESSAGE_ABORT]: false,
|
|
410
|
+
})));
|
|
302
411
|
});
|
|
303
412
|
|
|
304
413
|
return promise;
|