@azure/core-amqp
Version:
Common library for amqp based azure sdks like @azure/event-hubs.
286 lines (285 loc) • 11.7 kB
JavaScript
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