UNPKG

@message-queue-toolkit/sns

Version:
184 lines 7.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateOutgoingMessageSize = void 0; exports.getTopicAttributes = getTopicAttributes; exports.getSubscriptionAttributes = getSubscriptionAttributes; exports.assertTopic = assertTopic; exports.deleteTopic = deleteTopic; exports.deleteSubscription = deleteSubscription; exports.findSubscriptionByTopicAndQueue = findSubscriptionByTopicAndQueue; exports.getTopicArnByName = getTopicArnByName; const client_sns_1 = require("@aws-sdk/client-sns"); const client_sns_2 = require("@aws-sdk/client-sns"); const node_core_1 = require("@lokalise/node-core"); const sqs_1 = require("@message-queue-toolkit/sqs"); const snsAttributeUtils_1 = require("./snsAttributeUtils"); const stsUtils_1 = require("./stsUtils"); async function getTopicAttributes(snsClient, topicArn) { const command = new client_sns_2.GetTopicAttributesCommand({ TopicArn: topicArn, }); try { const response = await snsClient.send(command); return { result: { attributes: response.Attributes, }, }; } catch (err) { // @ts-ignore if (err.Code === 'AWS.SimpleQueueService.NonExistentQueue') { return { // @ts-ignore error: 'not_found', }; } throw err; } } async function getSubscriptionAttributes(snsClient, subscriptionArn) { const command = new client_sns_2.GetSubscriptionAttributesCommand({ SubscriptionArn: subscriptionArn, }); try { const response = await snsClient.send(command); return { result: { attributes: response.Attributes, }, }; } catch (err) { // @ts-ignore if (err.Code === 'AWS.SimpleQueueService.NonExistentQueue') { return { // @ts-ignore error: 'not_found', }; } throw err; } } async function assertTopic(snsClient, stsClient, topicOptions, extraParams) { let topicArn; try { const command = new client_sns_2.CreateTopicCommand(topicOptions); const response = await snsClient.send(command); if (!response.TopicArn) throw new Error('No topic arn in response'); topicArn = response.TopicArn; } catch (error) { if (!(0, node_core_1.isError)(error)) throw error; // To build ARN we need topic name and error should be "topic already exist with different tags" if (!topicOptions.Name || !isTopicAlreadyExistWithDifferentTagsError(error)) throw error; topicArn = await (0, stsUtils_1.buildTopicArn)(stsClient, topicOptions.Name); if (!extraParams?.forceTagUpdate) { const currentTags = await snsClient.send(new client_sns_1.ListTagsForResourceCommand({ ResourceArn: topicArn })); throw new node_core_1.InternalError({ message: `${topicOptions.Name} - ${error.message}`, details: { currentTags: JSON.stringify(currentTags), newTags: JSON.stringify(topicOptions.Tags), }, errorCode: 'SNS_TOPIC_ALREADY_EXISTS_WITH_DIFFERENT_TAGS', cause: error, }); } } if (extraParams?.queueUrlsWithSubscribePermissionsPrefix || extraParams?.allowedSourceOwner) { const setTopicAttributesCommand = new client_sns_2.SetTopicAttributesCommand({ TopicArn: topicArn, AttributeName: 'Policy', AttributeValue: (0, snsAttributeUtils_1.generateTopicSubscriptionPolicy)({ topicArn, allowedSqsQueueUrlPrefix: extraParams.queueUrlsWithSubscribePermissionsPrefix, allowedSourceOwner: extraParams.allowedSourceOwner, }), }); await snsClient.send(setTopicAttributesCommand); } if (extraParams?.forceTagUpdate && topicOptions.Tags) { const tagTopicCommand = new client_sns_1.TagResourceCommand({ ResourceArn: topicArn, Tags: topicOptions.Tags, }); await snsClient.send(tagTopicCommand); } return topicArn; } async function deleteTopic(snsClient, stsClient, topicName) { try { const topicArn = await assertTopic(snsClient, stsClient, { Name: topicName, }); await snsClient.send(new client_sns_2.DeleteTopicCommand({ TopicArn: topicArn, })); } catch (_) { // we don't care it operation has failed } } async function deleteSubscription(client, subscriptionArn) { const command = new client_sns_2.UnsubscribeCommand({ SubscriptionArn: subscriptionArn, }); try { await client.send(command); } catch (_) { // we don't care it operation has failed } } async function findSubscriptionByTopicAndQueue(snsClient, topicArn, queueArn) { const listSubscriptionsCommand = new client_sns_2.ListSubscriptionsByTopicCommand({ TopicArn: topicArn, }); const listSubscriptionResult = await snsClient.send(listSubscriptionsCommand); return listSubscriptionResult.Subscriptions?.find((entry) => { return entry.Endpoint === queueArn; }); } async function getTopicArnByName(snsClient, topicName) { if (!topicName) { throw new Error('topicName is not provided'); } // Use paginator to automatically handle NextToken const paginator = (0, client_sns_1.paginateListTopics)({ client: snsClient }, {}); for await (const page of paginator) { for (const topic of page.Topics || []) { if (topic.TopicArn?.includes(topicName)) { return topic.TopicArn; } } } throw new Error(`Failed to resolve topic by name ${topicName}`); } /** * Calculates the size of an outgoing SNS message. * * SNS imposes a 256 KB limit on the total size of a message, which includes both the message body and any metadata (attributes). * This function currently computes the size based solely on the message body, as no attributes are included at this time. * For future updates, if message attributes are added, their sizes should also be considered. * * Reference: https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html * * A wrapper around the equivalent function in the SQS package. */ const calculateOutgoingMessageSize = (message) => (0, sqs_1.calculateOutgoingMessageSize)(message); exports.calculateOutgoingMessageSize = calculateOutgoingMessageSize; const isTopicAlreadyExistWithDifferentTagsError = (error) => !!error && (0, node_core_1.isError)(error) && 'Error' in error && !!error.Error && typeof error.Error === 'object' && 'Code' in error.Error && 'Message' in error.Error && typeof error.Error.Message === 'string' && error.Error.Code === 'InvalidParameter' && error.Error.Message.includes('already exists with different tags'); //# sourceMappingURL=snsUtils.js.map