UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

121 lines (119 loc) 4.43 kB
import { from, Observable, of, throwError } from 'rxjs'; import { filter, mergeMap, take } from 'rxjs/operators'; import { Logging } from '../diagnostics/logging'; import { RpcInboundClient } from './rpc-inbound-client'; import { RpcOutboundClient } from './rpc-outbound-client'; /** * RPC Observable Client class. */ export class RpcObservableClient { rpc; command; version; id = 0; requestCommand; resultCommand; resultBuffer = []; resultObservers = []; /** * Initializes a new instance of the RpcObservableClient class. * * @param rpc The rpc object. * @param command the command string. * @param version the version string. */ constructor(rpc, command, version) { this.rpc = rpc; this.command = command; this.version = version; this.requestCommand = `${command}-Request`; this.resultCommand = `${command}-Result`; this.rpc.register(this.resultCommand, this.handler.bind(this)); this.rpc.registerInboundHandler(this.resultCommand, this.handler.bind(this)); this.rpc.registerOutboundHandler(this.resultCommand, this.handler.bind(this)); } /** * Make observable call. * * @param request The the request data. * @param outbound The outbound RPC channel. (request initiated from Shell.) * @return An observable for the response message */ observableCall(request, outbound) { const id = this.id++; const observableRequest = { id, request }; Logging.logDebug(this.requestCommand, `Sending request: "${this.requestCommand}"`, observableRequest); const replayResult = this.replayResult(); return from(this.rpcCall(observableRequest, outbound)) .pipe(mergeMap(() => replayResult), filter(observableResult => { if (observableResult.id !== observableRequest.id) { return false; } // clean up the buffer. const index = this.resultBuffer.findIndex(item => item.id === observableResult.id); if (index >= 0) { this.resultBuffer.splice(index, 1); } return true; }), take(1), mergeMap((result) => { if (result.error) { result.error.sourceName = result.sourceName; result.error.sourceSubName = result.sourceSubName; result.error.sourceVersion = result.sourceVersion; return throwError(() => result.error); } result.result = result.result || {}; result.result.sourceName = result.sourceName; result.result.sourceSubName = result.sourceSubName; result.result.sourceVersion = result.sourceVersion; return of(result.result); })); } /** * Making rpc call to shell or module. * * @param request the request packet data. * @param outbound the outbound object from Shell to module request. * @return Promise<void> the promise object. */ rpcCall(request, outbound) { if (outbound) { return RpcOutboundClient.callOutbound(this.rpc.rpcManager.rpcChannel, outbound, this.requestCommand, this.version, request); } return RpcInboundClient.call(this.rpc, this.requestCommand, this.version, request); } /** * Create a replay observable. Replays result data if results exists. */ replayResult() { return new Observable(observer => { this.resultObservers.push(observer); // replay. for (const item of this.resultBuffer) { observer.next(item); } return () => { const index = this.resultObservers.findIndex(item => item === observer); if (index >= 0) { this.resultObservers.splice(index, 1); } observer.complete(); }; }); } /** * Handles rpc response messages. * * @param result the result of observable request. */ handler(result) { // store. this.resultBuffer.push(result); // distributed to all active observers. for (const observer of this.resultObservers) { observer.next(result); } return Promise.resolve(); } } //# sourceMappingURL=rpc-observable-client.js.map