UNPKG

@azure/storage-queue

Version:
663 lines 31.6 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueClient = void 0; const core_auth_1 = require("@azure/core-auth"); const core_util_1 = require("@azure/core-util"); const Pipeline_js_1 = require("./Pipeline.js"); const StorageClient_js_1 = require("./StorageClient.js"); const utils_common_js_1 = require("./utils/utils.common.js"); const storage_common_1 = require("@azure/storage-common"); const storage_common_2 = require("@azure/storage-common"); const tracing_js_1 = require("./utils/tracing.js"); const QueueSASSignatureValues_js_1 = require("./QueueSASSignatureValues.js"); const core_rest_pipeline_1 = require("@azure/core-rest-pipeline"); /** * A QueueClient represents a URL to an Azure Storage Queue's messages allowing you to manipulate its messages. */ class QueueClient extends StorageClient_js_1.StorageClient { /** * messagesContext provided by protocol layer. */ messagesContext; /** * queueContext provided by protocol layer. */ queueContext; _name; _messagesUrl; /** * The name of the queue. */ get name() { return this._name; } constructor(urlOrConnectionString, credentialOrPipelineOrQueueName, // Legacy, no way to fix the eslint error without breaking. Disable the rule for this line. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options */ options) { options = options || {}; let pipeline; let url; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrQueueName)) { // (url: string, pipeline: Pipeline) url = urlOrConnectionString; pipeline = credentialOrPipelineOrQueueName; } else if ((core_util_1.isNode && credentialOrPipelineOrQueueName instanceof storage_common_1.StorageSharedKeyCredential) || credentialOrPipelineOrQueueName instanceof storage_common_2.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrQueueName)) { // (url: string, credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, options?: StoragePipelineOptions) url = urlOrConnectionString; pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrQueueName, options); } else if (!credentialOrPipelineOrQueueName && typeof credentialOrPipelineOrQueueName !== "string") { // (url: string, credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, options?: StoragePipelineOptions) // The second parameter is undefined. Use anonymous credential. url = urlOrConnectionString; pipeline = (0, Pipeline_js_1.newPipeline)(new storage_common_2.AnonymousCredential(), options); } else if (credentialOrPipelineOrQueueName && typeof credentialOrPipelineOrQueueName === "string") { // (connectionString: string, containerName: string, queueName: string, options?: StoragePipelineOptions) const extractedCreds = (0, utils_common_js_1.extractConnectionStringParts)(urlOrConnectionString); if (extractedCreds.kind === "AccountConnString") { if (core_util_1.isNode) { const queueName = credentialOrPipelineOrQueueName; const sharedKeyCredential = new storage_common_1.StorageSharedKeyCredential(extractedCreds.accountName, extractedCreds.accountKey); url = (0, utils_common_js_1.appendToURLPath)(extractedCreds.url, queueName); if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { const queueName = credentialOrPipelineOrQueueName; url = (0, utils_common_js_1.appendToURLPath)(extractedCreds.url, queueName) + "?" + extractedCreds.accountSas; pipeline = (0, Pipeline_js_1.newPipeline)(new storage_common_2.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for queueName parameter"); } super(url, pipeline); this._name = this.getQueueNameFromUrl(); this.queueContext = this.storageClientContext.queue; // MessagesContext // Build the url with "messages" const partsOfUrl = this.url.split("?"); this._messagesUrl = partsOfUrl[1] ? (0, utils_common_js_1.appendToURLPath)(partsOfUrl[0], "messages") + "?" + partsOfUrl[1] : (0, utils_common_js_1.appendToURLPath)(partsOfUrl[0], "messages"); this.messagesContext = (0, StorageClient_js_1.getStorageClientContext)(this._messagesUrl, this.pipeline).messages; } getMessageIdContext(messageId) { // Build the url with messageId const partsOfUrl = this._messagesUrl.split("?"); const urlWithMessageId = partsOfUrl[1] ? (0, utils_common_js_1.appendToURLPath)(partsOfUrl[0], messageId) + "?" + partsOfUrl[1] : (0, utils_common_js_1.appendToURLPath)(partsOfUrl[0], messageId); return (0, StorageClient_js_1.getStorageClientContext)(urlWithMessageId, this.pipeline).messageId; } /** * Creates a new queue under the specified account. * @see https://learn.microsoft.com/rest/api/storageservices/create-queue4 * * @param options - Options to Queue create operation. * @returns Response data for the Queue create operation. * * Example usage: * * ```ts snippet:ReadmeSampleCreateQueue * import { QueueServiceClient } from "@azure/storage-queue"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const queueServiceClient = new QueueServiceClient( * `https://${account}.queue.core.windows.net`, * new DefaultAzureCredential(), * ); * * const queueName = "<valid queue name>"; * const queueClient = queueServiceClient.getQueueClient(queueName); * const createQueueResponse = await queueClient.create(); * console.log( * `Created queue ${queueName} successfully, service assigned request Id: ${createQueueResponse.requestId}`, * ); * ``` */ async create(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-create", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.queueContext.create(updatedOptions)); }); } /** * Creates a new queue under the specified account if it doesn't already exist. * If the queue already exists, it is not changed. * @see https://learn.microsoft.com/rest/api/storageservices/create-queue4 * * @param options - */ async createIfNotExists(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-createIfNotExists", options, async (updatedOptions) => { try { const response = await this.create(updatedOptions); // When a queue with the specified name already exists, the Queue service checks the metadata associated with the existing queue. // If the existing metadata is identical to the metadata specified on the Create Queue request, status code 204 (No Content) is returned. // If the existing metadata does not match, the operation fails and status code 409 (Conflict) is returned. if (response._response.status === 204) { return { succeeded: false, ...response, }; } return { succeeded: true, ...response, }; } catch (e) { if (e.details?.errorCode === "QueueAlreadyExists") { return { succeeded: false, ...e.response?.parsedHeaders, _response: e.response, }; } throw e; } }); } /** * Deletes the specified queue permanently if it exists. * @see https://learn.microsoft.com/rest/api/storageservices/delete-queue3 * * @param options - */ async deleteIfExists(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-deleteIfExists", options, async (updatedOptions) => { try { const res = await this.delete(updatedOptions); return { succeeded: true, ...res, }; } catch (e) { if (e.details?.errorCode === "QueueNotFound") { return { succeeded: false, ...e.response?.parsedHeaders, _response: e.response, }; } throw e; } }); } /** * Deletes the specified queue permanently. * @see https://learn.microsoft.com/rest/api/storageservices/delete-queue3 * * @param options - Options to Queue delete operation. * @returns Response data for the Queue delete operation. * * Example usage: * * ```ts snippet:ReadmeSampleDeleteQueue * import { QueueServiceClient } from "@azure/storage-queue"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const queueServiceClient = new QueueServiceClient( * `https://${account}.queue.core.windows.net`, * new DefaultAzureCredential(), * ); * * const queueName = "<valid queue name>"; * const queueClient = queueServiceClient.getQueueClient(queueName); * const deleteQueueResponse = await queueClient.delete(); * console.log( * `Deleted queue successfully, service assigned request Id: ${deleteQueueResponse.requestId}`, * ); * ``` */ async delete(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-delete", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.queueContext.delete({ abortSignal: options.abortSignal, tracingOptions: updatedOptions.tracingOptions, })); }); } /** * Returns true if the specified queue exists; false otherwise. * * NOTE: use this function with care since an existing queue might be deleted by other clients or * applications. Vice versa new queues might be added by other clients or applications after this * function completes. * * @param options - options to Exists operation. */ async exists(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-exists", options, async (updatedOptions) => { try { await this.getProperties(updatedOptions); return true; } catch (e) { if (e.statusCode === 404) { return false; } throw e; } }); } /** * Gets all user-defined metadata and system properties for the specified * queue. Metadata is associated with the queue as name-values pairs. * @see https://learn.microsoft.com/rest/api/storageservices/get-queue-metadata * * WARNING: The `metadata` object returned in the response will have its keys in lowercase, even if * they originally contained uppercase characters. This differs from the metadata keys returned by * the `listQueues` method of {@link QueueServiceClient} using the `includeMetadata` option, which * will retain their original casing. * * @param options - Options to Queue get properties operation. * @returns Response data for the Queue get properties operation. */ async getProperties(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-getProperties", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.queueContext.getProperties(updatedOptions)); }); } /** * Sets one or more user-defined name-value pairs for the specified queue. * * If no option provided, or no metadata defined in the option parameter, the queue * metadata will be removed. * @see https://learn.microsoft.com/rest/api/storageservices/set-queue-metadata * * @param metadata - If no metadata provided, all existing metadata will be removed. * @param options - Options to Queue set metadata operation. * @returns Response data for the Queue set metadata operation. */ async setMetadata(metadata, options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-setMetadata", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.queueContext.setMetadata({ ...updatedOptions, metadata, })); }); } /** * Gets details about any stored access policies specified on the queue that may be used with Shared Access Signatures. * * WARNING: JavaScript Date will potential lost precision when parsing start and expiry string. * For example, new Date("2018-12-31T03:44:23.8827891Z").toISOString() will get "2018-12-31T03:44:23.882Z". * * @see https://learn.microsoft.com/rest/api/storageservices/get-queue-acl * * @param options - Options to Queue get access policy operation. * @returns Response data for the Queue get access policy operation. */ async getAccessPolicy(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-getAccessPolicy", options, async (updatedOptions) => { const response = (0, utils_common_js_1.assertResponse)(await this.queueContext.getAccessPolicy({ abortSignal: options.abortSignal, tracingOptions: updatedOptions.tracingOptions, })); const res = { _response: response._response, date: response.date, requestId: response.requestId, clientRequestId: response.clientRequestId, signedIdentifiers: [], version: response.version, errorCode: response.errorCode, }; for (const identifier of response) { let accessPolicy = undefined; if (identifier.accessPolicy) { accessPolicy = { permissions: identifier.accessPolicy.permissions, }; if (identifier.accessPolicy.expiresOn) { accessPolicy.expiresOn = new Date(identifier.accessPolicy.expiresOn); } if (identifier.accessPolicy.startsOn) { accessPolicy.startsOn = new Date(identifier.accessPolicy.startsOn); } } res.signedIdentifiers.push({ accessPolicy, id: identifier.id, }); } return res; }); } /** * Sets stored access policies for the queue that may be used with Shared Access Signatures. * @see https://learn.microsoft.com/rest/api/storageservices/set-queue-acl * * @param queueAcl - * @param options - Options to Queue set access policy operation. * @returns Response data for the Queue set access policy operation. */ async setAccessPolicy(queueAcl, options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-setAccessPolicy", options, async (updatedOptions) => { const acl = []; for (const identifier of queueAcl || []) { acl.push({ accessPolicy: { expiresOn: identifier.accessPolicy.expiresOn ? (0, utils_common_js_1.truncatedISO8061Date)(identifier.accessPolicy.expiresOn) : undefined, permissions: identifier.accessPolicy.permissions, startsOn: identifier.accessPolicy.startsOn ? (0, utils_common_js_1.truncatedISO8061Date)(identifier.accessPolicy.startsOn) : undefined, }, id: identifier.id, }); } return (0, utils_common_js_1.assertResponse)(await this.queueContext.setAccessPolicy({ ...updatedOptions, queueAcl: acl, })); }); } /** * Clear deletes all messages from a queue. * @see https://learn.microsoft.com/rest/api/storageservices/clear-messages * * @param options - Options to clear messages operation. * @returns Response data for the clear messages operation. */ async clearMessages(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-clearMessages", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.messagesContext.clear(updatedOptions)); }); } /** * sendMessage adds a new message to the back of a queue. The visibility timeout specifies how long * the message should be invisible to Dequeue and Peek operations. * The message content is up to 64KB in size, and must be in a format that can be included in an XML request with UTF-8 encoding. * To include markup in the message, the contents of the message must either be XML-escaped or Base64-encode. * @see https://learn.microsoft.com/rest/api/storageservices/put-message * * @param messageText - Text of the message to send * @param options - Options to send messages operation. * @returns Response data for the send messages operation. * * Example usage: * * ```ts snippet:ReadmeSampleSendMessage * import { QueueServiceClient } from "@azure/storage-queue"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const queueServiceClient = new QueueServiceClient( * `https://${account}.queue.core.windows.net`, * new DefaultAzureCredential(), * ); * * const queueName = "<valid queue name>"; * const queueClient = queueServiceClient.getQueueClient(queueName); * // Send a message into the queue using the sendMessage method. * const sendMessageResponse = await queueClient.sendMessage("Hello World!"); * console.log( * `Sent message successfully, service assigned message Id: ${sendMessageResponse.messageId}, service assigned request Id: ${sendMessageResponse.requestId}`, * ); * ``` */ async sendMessage(messageText, options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-sendMessage", options, async (updatedOptions) => { const response = (0, utils_common_js_1.assertResponse)(await this.messagesContext.enqueue({ messageText: messageText, }, updatedOptions)); const item = response[0]; return { _response: response._response, date: response.date, requestId: response.requestId, clientRequestId: response.clientRequestId, version: response.version, errorCode: response.errorCode, messageId: item.messageId, popReceipt: item.popReceipt, nextVisibleOn: item.nextVisibleOn, insertedOn: item.insertedOn, expiresOn: item.expiresOn, }; }); } /** * receiveMessages retrieves one or more messages from the front of the queue. * @see https://learn.microsoft.com/rest/api/storageservices/get-messages * * @param options - Options to receive messages operation. * @returns Response data for the receive messages operation. * * Example usage: * * ```ts snippet:ReadmeSampleReceiveMessage * import { QueueServiceClient } from "@azure/storage-queue"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const queueServiceClient = new QueueServiceClient( * `https://${account}.queue.core.windows.net`, * new DefaultAzureCredential(), * ); * * const queueName = "<valid queue name>"; * const queueClient = queueServiceClient.getQueueClient(queueName); * const response = await queueClient.receiveMessages(); * if (response.receivedMessageItems.length === 1) { * const receivedMessageItem = response.receivedMessageItems[0]; * console.log(`Processing & deleting message with content: ${receivedMessageItem.messageText}`); * const deleteMessageResponse = await queueClient.deleteMessage( * receivedMessageItem.messageId, * receivedMessageItem.popReceipt, * ); * console.log( * `Delete message successfully, service assigned request Id: ${deleteMessageResponse.requestId}`, * ); * } * ``` */ async receiveMessages(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-receiveMessages", options, async (updatedOptions) => { const response = (0, utils_common_js_1.assertResponse)(await this.messagesContext.dequeue(updatedOptions)); const res = { _response: response._response, date: response.date, requestId: response.requestId, clientRequestId: response.clientRequestId, receivedMessageItems: [], version: response.version, errorCode: response.errorCode, }; for (const item of response) { res.receivedMessageItems.push(item); } return res; }); } /** * peekMessages retrieves one or more messages from the front of the queue but does not alter the visibility of the message. * @see https://learn.microsoft.com/rest/api/storageservices/peek-messages * * @param options - Options to peek messages operation. * @returns Response data for the peek messages operation. * * Example usage: * * ```ts snippet:ReadmeSamplePeekMessage * import { QueueServiceClient } from "@azure/storage-queue"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const queueServiceClient = new QueueServiceClient( * `https://${account}.queue.core.windows.net`, * new DefaultAzureCredential(), * ); * * const queueName = "<valid queue name>"; * const queueClient = queueServiceClient.getQueueClient(queueName); * const peekMessagesResponse = await queueClient.peekMessages(); * console.log(`The peeked message is: ${peekMessagesResponse.peekedMessageItems[0].messageText}`); * ``` */ async peekMessages(options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-peekMessages", options, async (updatedOptions) => { const response = (0, utils_common_js_1.assertResponse)(await this.messagesContext.peek(updatedOptions)); const res = { _response: response._response, date: response.date, requestId: response.requestId, clientRequestId: response.clientRequestId, peekedMessageItems: [], version: response.version, errorCode: response.errorCode, }; for (const item of response) { res.peekedMessageItems.push(item); } return res; }); } /** * deleteMessage permanently removes the specified message from its queue. * @see https://learn.microsoft.com/rest/api/storageservices/delete-message2 * * @param messageId - Id of the message. * @param popReceipt - A valid pop receipt value returned from an earlier call to the receive messages or update message operation. * @param options - Options to delete message operation. * @returns Response data for the delete message operation. */ async deleteMessage(messageId, popReceipt, options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-deleteMessage", options, async (updatedOptions) => { return (0, utils_common_js_1.assertResponse)(await this.getMessageIdContext(messageId).delete(popReceipt, updatedOptions)); }); } /** * Update changes a message's visibility timeout and contents. * The message content is up to 64KB in size, and must be in a format that can be included in an XML request with UTF-8 encoding. * To include markup in the message, the contents of the message must either be XML-escaped or Base64-encode. * @see https://learn.microsoft.com/rest/api/storageservices/update-message * * @param messageId - Id of the message * @param popReceipt - A valid pop receipt value returned from an earlier call to the receive messages or update message operation. * @param message - Message to update. If this parameter is undefined, then the content of the message won't be updated. * @param visibilityTimeout - Specifies the new visibility timeout value, in seconds, * relative to server time. The new value must be larger than or equal to 0, * and cannot be larger than 7 days. The visibility timeout of a message cannot * be set to a value later than the expiry time. * A message can be updated until it has been deleted or has expired. * @param options - Options to update message operation. * @returns Response data for the update message operation. */ async updateMessage(messageId, popReceipt, message, visibilityTimeout, options = {}) { return tracing_js_1.tracingClient.withSpan("QueueClient-updateMessage", options, async (updatedOptions) => { let queueMessage = undefined; if (message !== undefined) { queueMessage = { messageText: message }; } return (0, utils_common_js_1.assertResponse)(await this.getMessageIdContext(messageId).update(popReceipt, visibilityTimeout || 0, { abortSignal: options.abortSignal, tracingOptions: updatedOptions.tracingOptions, queueMessage, })); }); } getQueueNameFromUrl() { let queueName; try { // URL may look like the following // "https://myaccount.queue.core.windows.net/myqueue?sasString". // "https://myaccount.queue.core.windows.net/myqueue". // IPv4/IPv6 address hosts, Endpoints - `http://127.0.0.1:10001/devstoreaccount1/myqueue` // http://localhost:10001/devstoreaccount1/queuename const parsedUrl = new URL(this.url); if (parsedUrl.hostname.split(".")[1] === "queue") { // "https://myaccount.queue.core.windows.net/queuename". // .getPath() -> /queuename queueName = parsedUrl.pathname.split("/")[1]; } else if ((0, utils_common_js_1.isIpEndpointStyle)(parsedUrl)) { // IPv4/IPv6 address hosts... Example - http://192.0.0.10:10001/devstoreaccount1/queuename // Single word domain without a [dot] in the endpoint... Example - http://localhost:10001/devstoreaccount1/queuename // .getPath() -> /devstoreaccount1/queuename queueName = parsedUrl.pathname.split("/")[2]; } else { // "https://customdomain.com/queuename". // .getPath() -> /queuename queueName = parsedUrl.pathname.split("/")[1]; } if (!queueName) { throw new Error("Provided queueName is invalid."); } return queueName; } catch (error) { throw new Error("Unable to extract queueName with provided information."); } } /** * Only available for QueueClient constructed with a shared key credential. * * Generates a Service Shared Access Signature (SAS) URI based on the client properties * and parameters passed in. The SAS is signed by the shared key credential of the client. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token. */ generateSasUrl(options) { if (!(this.credential instanceof storage_common_1.StorageSharedKeyCredential)) { throw RangeError("Can only generate the SAS when the client is initialized with a shared key credential"); } const sas = (0, QueueSASSignatureValues_js_1.generateQueueSASQueryParameters)({ queueName: this.name, ...options, }, this.credential).toString(); return (0, utils_common_js_1.appendToURLQuery)(this.url, sas); } /** * Only available for QueueClient constructed with a shared key credential. * * Generates string to sign for a Service Shared Access Signature (SAS) URI based on the client properties * and parameters passed in. The SAS is signed by the shared key credential of the client. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token. */ /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ generateSasStringToSign(options) { if (!(this.credential instanceof storage_common_1.StorageSharedKeyCredential)) { throw RangeError("Can only generate the SAS when the client is initialized with a shared key credential"); } return (0, QueueSASSignatureValues_js_1.generateQueueSASQueryParametersInternal)({ queueName: this.name, ...options, }, this.credential).stringToSign; } } exports.QueueClient = QueueClient; //# sourceMappingURL=QueueClient.js.map