UNPKG

@itwin/core-common

Version:

iTwin.js components common to frontend and backend

134 lines 5.14 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module RpcInterface */ import { Base64 } from "js-base64"; import { RpcInterface } from "../../RpcInterface"; import { RpcManager } from "../../RpcManager"; import { RpcConfiguration } from "./RpcConfiguration"; import { RpcOperation } from "./RpcOperation"; import { RpcRegistry } from "./RpcRegistry"; /** An RPC operation control response. * @public */ export class RpcControlResponse { message = "RpcControlResponse"; } /** A pending RPC operation response. * @public */ export class RpcPendingResponse extends RpcControlResponse { /** Extended status regarding the pending operation. */ message; /** Constructs a pending response. */ constructor(message = "") { super(); this.message = message; } } /** A RPC operation response. * @public */ export class RpcNotFoundResponse extends RpcControlResponse { message = "Not found"; } /** Manages requests and responses for an RPC configuration. * @internal */ export class RpcControlChannel { /** @internal */ static channels = []; static _obtainLock = 0; _configuration; _initialized = false; _clientActive = false; _describeEndpoints = undefined; /** @internal */ static ensureInitialized() { this.channels.forEach((channel) => channel.initialize()); } constructor(configuration) { this._configuration = configuration; RpcControlChannel.channels.push(this); } /** @internal */ async describeEndpoints() { this.activateClient(); if (!this._channelInterface.interfaceName) { return []; } return this._describeEndpoints(); } /** @internal */ static obtain(configuration) { if (RpcControlChannel._obtainLock) return undefined; ++RpcControlChannel._obtainLock; const channel = new RpcControlChannel(configuration); --RpcControlChannel._obtainLock; return channel; } _channelInterface = class extends RpcInterface { static interfaceVersion = "CONTROL"; static interfaceName = ""; async describeEndpoints() { return this.forward(arguments); } }; _channelImpl = class extends RpcInterface { async describeEndpoints() { const endpoints = []; this.configuration.interfaces().forEach((definition) => { if (!RpcRegistry.instance.isRpcInterfaceInitialized(definition)) return; const description = { interfaceName: definition.interfaceName, interfaceVersion: definition.interfaceVersion, operationNames: [], compatible: true }; RpcOperation.forEach(definition, (operation) => description.operationNames.push(operation.operationName)); endpoints.push(description); }); return endpoints; } }; computeId() { const interfaces = []; this._configuration.interfaces().forEach((definition) => interfaces.push(`${definition.interfaceName}@${definition.interfaceVersion}`)); const id = interfaces.sort().join(","); return Base64.encode(id); } activateClient() { if (this._clientActive) return; this.initialize(); const token = { key: "none", iTwinId: "none", iModelId: "none", changeset: { id: "none" } }; RpcOperation.forEach(this._channelInterface, (operation) => operation.policy.token = (_request) => RpcOperation.fallbackToken ?? token); const client = RpcManager.getClientForInterface(this._channelInterface); this._describeEndpoints = async () => client.describeEndpoints(); this._clientActive = true; } /** @internal */ initialize() { if (this._initialized) { return; } const id = this.computeId(); Object.defineProperty(this._channelInterface, "interfaceName", { value: id }); Object.defineProperty(this._channelImpl, "interfaceName", { value: id }); RpcConfiguration.assign(this._channelInterface, () => this._configuration.constructor); RpcManager.registerImpl(this._channelInterface, this._channelImpl); RpcManager.initializeInterface(this._channelInterface); this._initialized = true; } /** @internal */ handleUnknownOperation(invocation, _error) { this.initialize(); const op = invocation.request.operation; if (op.interfaceVersion === "CONTROL" && op.operationName === "describeEndpoints") { if (this._channelInterface.interfaceName) { op.interfaceDefinition = this._channelInterface.interfaceName; } return true; } return false; } } //# sourceMappingURL=RpcControl.js.map