UNPKG

@azure/core-amqp

Version:

Common library for amqp based azure sdks like @azure/event-hubs.

286 lines (285 loc) • 11.7 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var cbs_exports = {}; __export(cbs_exports, { CbsClient: () => CbsClient }); module.exports = __toCommonJS(cbs_exports); var import_abort_controller = require("@azure/abort-controller"); var import_rhea_promise = require("rhea-promise"); var import_log = require("./log.js"); var import_constants = require("./util/constants.js"); var import_requestResponseLink = require("./requestResponseLink.js"); var import_constants2 = require("./util/constants.js"); var import_utils = require("./util/utils.js"); var import_core_util = require("@azure/core-util"); var import_errors = require("./errors.js"); class CbsClient { /** * CBS endpoint - "$cbs" */ endpoint = import_constants.Constants.cbsEndpoint; /** * CBS replyTo - The receiver link name that the service should reply to. */ replyTo = `${import_constants.Constants.cbsReplyTo}-${(0, import_rhea_promise.generate_uuid)()}`; /** * The unique lock name per $cbs session per connection that is used to * acquire the lock for establishing a cbs session if one does not exist for an amqp connection. */ cbsLock = `${import_constants.Constants.negotiateCbsKey}-${(0, import_rhea_promise.generate_uuid)()}`; /** * The unique lock name per connection that is used to * acquire the lock for establishing an amqp connection if one does not exist. */ connectionLock; /** * The AMQP connection. */ connection; /** * CBS sender, receiver on the same session. */ _cbsSenderReceiverLink; /** * @param connection - The AMQP connection. * @param connectionLock - A unique string (usually a guid) per connection. */ constructor(connection, connectionLock) { this.connection = connection; this.connectionLock = connectionLock; } /** * Creates a singleton instance of the CBS session if it hasn't been initialized previously on * the given connection. * @param options - Optional parameters that can be used to affect this method's behavior. * For example, `abortSignal` can be passed to allow cancelling an in-progress `init` invocation. * @returns Promise<void>. */ async init(options = {}) { const { abortSignal, timeoutInMs } = options; try { if (abortSignal?.aborted) { throw new import_abort_controller.AbortError(import_constants2.StandardAbortMessage); } if (!this.connection.isOpen()) { import_log.logger.verbose("The CBS client is trying to establish an AMQP connection."); await import_utils.defaultCancellableLock.acquire( this.connectionLock, () => { return this.connection.open({ abortSignal }); }, { abortSignal, timeoutInMs } ); } if (!this.isOpen()) { const rxOpt = { source: { address: this.endpoint }, name: this.replyTo, onSessionError: (context) => { const id = context.connection.options.id; const ehError = (0, import_errors.translate)(context.session.error); import_log.logger.verbose( "[%s] An error occurred on the session for request/response links for $cbs: %O", id, ehError ); } }; const srOpt = { target: { address: this.endpoint } }; import_log.logger.verbose( "[%s] Creating sender/receiver links on a session for $cbs endpoint.", this.connection.id ); this._cbsSenderReceiverLink = await import_requestResponseLink.RequestResponseLink.create( this.connection, srOpt, rxOpt, { abortSignal } ); this._cbsSenderReceiverLink.sender.on(import_rhea_promise.SenderEvents.senderError, (context) => { const id = context.connection.options.id; const ehError = (0, import_errors.translate)(context.sender.error); import_log.logger.verbose("[%s] An error occurred on the cbs sender link.. %O", id, ehError); }); this._cbsSenderReceiverLink.receiver.on( import_rhea_promise.ReceiverEvents.receiverError, (context) => { const id = context.connection.options.id; const ehError = (0, import_errors.translate)(context.receiver.error); import_log.logger.verbose("[%s] An error occurred on the cbs receiver link.. %O", id, ehError); } ); import_log.logger.verbose( "[%s] Successfully created the cbs sender '%s' and receiver '%s' links over cbs session.", this.connection.id, this._cbsSenderReceiverLink.sender.name, this._cbsSenderReceiverLink.receiver.name ); } else { import_log.logger.verbose( "[%s] CBS session is already present. Reusing the cbs sender '%s' and receiver '%s' links over cbs session.", this.connection.id, this._cbsSenderReceiverLink.sender.name, this._cbsSenderReceiverLink.receiver.name ); } } catch (err) { const translatedError = (0, import_errors.translate)(err); import_log.logger.warning( "[%s] An error occurred while establishing the cbs links: %s", this.connection.id, `${translatedError?.name}: ${translatedError?.message}` ); (0, import_log.logErrorStackTrace)(translatedError); throw translatedError; } } /** * Negotiates the CBS claim with the EventHub/ServiceBus Service. * @param audience - The entity token audience for which the token is requested in one * of the following forms: * * - **ServiceBus** * - **Sender** * - `"sb://<yournamespace>.servicebus.windows.net/<queue-name>"` * - `"sb://<yournamespace>.servicebus.windows.net/<topic-name>"` * * - **Receiver** * - `"sb://<yournamespace>.servicebus.windows.net/<queue-name>"` * - `"sb://<yournamespace>.servicebus.windows.net/<topic-name>"` * * - **ManagementClient** * - `"sb://<your-namespace>.servicebus.windows.net/<queue-name>/$management"`. * - `"sb://<your-namespace>.servicebus.windows.net/<topic-name>/$management"`. * * - **EventHubs** * - **Sender** * - `"sb://<yournamespace>.servicebus.windows.net/<hubName>"` * - `"sb://<yournamespace>.servicebus.windows.net/<hubName>/Partitions/<partitionId>"`. * * - **Receiver** * - `"sb://<your-namespace>.servicebus.windows.net/<event-hub-name>/ConsumerGroups/<consumer-group-name>/Partitions/<partition-id>"`. * * - **ManagementClient** * - `"sb://<your-namespace>.servicebus.windows.net/<event-hub-name>/$management"`. * @param token - The token that needs to be sent in the put-token request. * @param tokenType - The type of token being used. For example, 'jwt' or 'servicebus.windows.net:sastoken'. * @param options - Optional parameters that can be used to affect this method's behavior. * For example, `abortSignal` can be passed to allow cancelling an in-progress `negotiateClaim` invocation. * @returns A Promise that resolves when $cbs authentication is successful * and rejects when an error occurs during $cbs authentication. */ async negotiateClaim(audience, token, tokenType, options = {}) { const { abortSignal, timeoutInMs } = options; try { if (abortSignal?.aborted) { throw new import_abort_controller.AbortError(import_constants2.StandardAbortMessage); } if (!this._cbsSenderReceiverLink) { throw new Error("Attempted to negotiate a claim but the CBS link does not exist."); } const request = { body: token, message_id: (0, import_rhea_promise.generate_uuid)(), reply_to: this.replyTo, to: this.endpoint, application_properties: { operation: import_constants.Constants.operationPutToken, name: audience, type: tokenType } }; const responseMessage = await this._cbsSenderReceiverLink.sendRequest(request, { abortSignal, timeoutInMs, requestName: "negotiateClaim" }); import_log.logger.verbose("[%s] The CBS response is: %O", this.connection.id, responseMessage); return this._fromRheaMessageResponse(responseMessage); } catch (err) { import_log.logger.warning( "[%s] An error occurred while negotiating the cbs claim: %s", this.connection.id, (0, import_core_util.isError)(err) ? `${err.name}: ${err.message}` : String(err) ); (0, import_log.logErrorStackTrace)(err); throw err; } } /** * Closes the AMQP cbs session to the EventHub/ServiceBus for this client, * returning a promise that will be resolved when disconnection is completed. * @returns */ async close() { try { if (this.isOpen()) { const cbsLink = this._cbsSenderReceiverLink; this._cbsSenderReceiverLink = void 0; await cbsLink.close(); import_log.logger.verbose("[%s] Successfully closed the cbs session.", this.connection.id); } } catch (err) { const msg = `An error occurred while closing the cbs link: ${(0, import_core_util.isError)(err) && err.stack ? err.stack : JSON.stringify(err)}.`; import_log.logger.verbose("[%s] %s", this.connection.id, msg); throw new Error(msg); } } /** * Removes the AMQP cbs session to the EventHub/ServiceBus for this client, * @returns void */ remove() { try { if (this._cbsSenderReceiverLink) { const cbsLink = this._cbsSenderReceiverLink; this._cbsSenderReceiverLink = void 0; cbsLink.remove(); import_log.logger.verbose("[%s] Successfully removed the cbs session.", this.connection.id); } } catch (err) { const msg = `An error occurred while removing the cbs link: ${(0, import_core_util.isError)(err) && err.stack ? err.stack : JSON.stringify(err)}.`; import_log.logger.verbose("[%s] %s", this.connection.id, msg); throw new Error(msg); } } /** * Indicates whether the cbs sender receiver link is open or closed. * @returns `true` open, `false` closed. */ isOpen() { return Boolean(this._cbsSenderReceiverLink?.isOpen()); } _fromRheaMessageResponse(msg) { const cbsResponse = { correlationId: msg.correlation_id, statusCode: msg.application_properties ? msg.application_properties["status-code"] : "", statusDescription: msg.application_properties ? msg.application_properties["status-description"] : "" }; import_log.logger.verbose("[%s] The deserialized CBS response is: %o", this.connection.id, cbsResponse); return cbsResponse; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { CbsClient }); //# sourceMappingURL=cbs.js.map