From eebce7cc8bc537e6637f32eb6e89cbc5357883d4 Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Fri, 22 Aug 2025 08:42:56 -0500 Subject: [PATCH 1/7] Check if RUM is available --- package-lock.json | 1254 +++++++++++++++-- package.json | 3 +- .../opportunity-status-processor/handler.js | 71 +- .../opportunity-status-processor.test.js | 266 +++- 4 files changed, 1445 insertions(+), 149 deletions(-) diff --git a/package-lock.json b/package-lock.json index 614148d..4c2b2ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@adobe/spacecat-shared-data-access": "2.54.0", "@adobe/spacecat-shared-http-utils": "1.15.2", "@adobe/spacecat-shared-ims-client": "1.8.8", + "@adobe/spacecat-shared-rum-api-client": "^2.36.4", "@adobe/spacecat-shared-slack-client": "^1.3.12", "@adobe/spacecat-shared-utils": "1.48.0", "@aws-sdk/client-lambda": "3.865.0", @@ -1613,6 +1614,12 @@ "@adobe/helix-log": "6.0.6" } }, + "node_modules/@adobe/rum-distiller": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@adobe/rum-distiller/-/rum-distiller-1.17.0.tgz", + "integrity": "sha512-Mc26gnG0yD9B3BgWDSyxYCdwiJCNKCeymWJKEsaclfJTX23PEav+sbLqr+pMMmN4WMSmp9N8LblwkZ/ypFd9vQ==", + "license": "Apache-2.0" + }, "node_modules/@adobe/semantic-release-coralogix": { "version": "1.1.38", "resolved": "https://registry.npmjs.org/@adobe/semantic-release-coralogix/-/semantic-release-coralogix-1.1.38.tgz", @@ -6048,36 +6055,26 @@ "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@adobe/spacecat-shared-slack-client": { - "version": "1.5.23", - "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-slack-client/-/spacecat-shared-slack-client-1.5.23.tgz", - "integrity": "sha512-v8tGA5tbU/J4VSj8ZjNcLhPuw5SD9JpswlBGgshCwubKFO+uSoTij7YfKKwmOwBz/3YlNkt6mREGXOmH58whrA==", + "node_modules/@adobe/spacecat-shared-rum-api-client": { + "version": "2.36.4", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-rum-api-client/-/spacecat-shared-rum-api-client-2.36.4.tgz", + "integrity": "sha512-al/HV57b7ELGENfSk/I5nwyaFxhZJAIv27Susbs54Up9UxHXJ2oppJ/rRPGKXjW7iTBKx5JoYd/PEadVZZnCmQ==", "license": "Apache-2.0", "dependencies": { + "@adobe/fetch": "4.2.2", + "@adobe/helix-shared-wrap": "2.0.2", "@adobe/helix-universal": "5.2.2", + "@adobe/rum-distiller": "1.17.0", "@adobe/spacecat-shared-utils": "1.26.4", - "@slack/web-api": "7.9.3" + "aws4": "1.13.2", + "urijs": "1.19.11" }, "engines": { "node": ">=22.0.0 <23.0.0", "npm": ">=10.9.0 <12.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@adobe/fetch": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.11.tgz", - "integrity": "sha512-Zak2kPJuIdg9UQQfUgNm848vRAg2pdOqYYU+7DkCYWO+SgZiMV+qy99BpO1geDiP2rQ2M7JH5oNXRTEvEWglRQ==", - "license": "Apache-2.0", - "dependencies": { - "debug": "4.4.0", - "http-cache-semantics": "4.1.1", - "lru-cache": "7.18.3" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@adobe/spacecat-shared-utils": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@adobe/spacecat-shared-utils": { "version": "1.26.4", "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-utils/-/spacecat-shared-utils-1.26.4.tgz", "integrity": "sha512-d/GZ6j//dXW9+YjgRO0PhZcvhXMlhfUHrPxcG/2OMD5gkd8fOd39+Y1JMu/6fgpNVOR7iQogb/5d5UXaHEWygg==", @@ -6096,7 +6093,21 @@ "npm": ">=10.9.0 <12.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-s3": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/fetch": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.11.tgz", + "integrity": "sha512-Zak2kPJuIdg9UQQfUgNm848vRAg2pdOqYYU+7DkCYWO+SgZiMV+qy99BpO1geDiP2rQ2M7JH5oNXRTEvEWglRQ==", + "license": "Apache-2.0", + "dependencies": { + "debug": "4.4.0", + "http-cache-semantics": "4.1.1", + "lru-cache": "7.18.3" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-s3": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.726.1.tgz", "integrity": "sha512-UpOGcob87DiuS2d3fW6vDZg94g57mNiOSkzvR/6GOdvBSlUgk8LLwVzGASB71FdKMl1EGEr4MeD5uKH9JsG+dw==", @@ -6165,7 +6176,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-secrets-manager": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-secrets-manager": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.726.1.tgz", "integrity": "sha512-eO9WpE8IyQrs2xWhfQCdHcVTHQTwJ56JGx3FhwhtFWWYHIS0c1bTIAvP5E3jSWAZNaK1iWdVexz3yGi3aAnGzA==", @@ -6219,7 +6230,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", @@ -6232,7 +6243,7 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sqs": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-sqs": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.726.1.tgz", "integrity": "sha512-QSsmlMNVgKUzDpDC3Ya1i0tvFjVcvTBoJfSh7LBkuMJiboY2j2aeD74OX7xGkxu+QLc8wWUjT//KYDm6KwHk7w==", @@ -6286,7 +6297,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sso": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-sso": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.726.0.tgz", "integrity": "sha512-NM5pjv2qglEc4XN3nnDqtqGsSGv1k5YTmzDo3W3pObItHmpS8grSeNfX9zSH+aVl0Q8hE4ZIgvTPNZ+GzwVlqg==", @@ -6335,7 +6346,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sts": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/client-sts": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.726.1.tgz", "integrity": "sha512-qh9Q9Vu1hrM/wMBOBIaskwnE4GTFaZu26Q6WHwyWNfj7J8a40vBxpW16c2vYXHLBtwRKM1be8uRLkmDwghpiNw==", @@ -6386,7 +6397,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/core": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/core": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.723.0.tgz", "integrity": "sha512-UraXNmvqj3vScSsTkjMwQkhei30BhXlW5WxX6JacMKVtl95c7z0qOXquTWeTalYkFfulfdirUhvSZrl+hcyqTw==", @@ -6408,7 +6419,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-env": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-env": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.723.0.tgz", "integrity": "sha512-OuH2yULYUHTVDUotBoP/9AEUIJPn81GQ/YBtZLoo2QyezRJ2QiO/1epVtbJlhNZRwXrToLEDmQGA2QfC8c7pbA==", @@ -6424,7 +6435,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-http": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-http": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.723.0.tgz", "integrity": "sha512-DTsKC6xo/kz/ZSs1IcdbQMTgiYbpGTGEd83kngFc1bzmw7AmK92DBZKNZpumf8R/UfSpTcj9zzUUmrWz1kD0eQ==", @@ -6445,7 +6456,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-ini": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.726.0.tgz", "integrity": "sha512-seTtcKL2+gZX6yK1QRPr5mDJIBOatrpoyrO8D5b8plYtV/PDbDW3mtDJSWFHet29G61ZmlNElyXRqQCXn9WX+A==", @@ -6471,7 +6482,7 @@ "@aws-sdk/client-sts": "^3.726.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-node": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-node": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.726.0.tgz", "integrity": "sha512-jjsewBcw/uLi24x8JbnuDjJad4VA9ROCE94uVRbEnGmUEsds75FWOKp3fWZLQlmjLtzsIbJOZLALkZP86liPaw==", @@ -6494,7 +6505,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-process": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-process": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.723.0.tgz", "integrity": "sha512-fgupvUjz1+jeoCBA7GMv0L6xEk92IN6VdF4YcFhsgRHlHvNgm7ayaoKQg7pz2JAAhG/3jPX6fp0ASNy+xOhmPA==", @@ -6511,7 +6522,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-sso": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.726.0.tgz", "integrity": "sha512-WxkN76WeB08j2yw7jUH9yCMPxmT9eBFd9ZA/aACG7yzOIlsz7gvG3P2FQ0tVg25GHM0E4PdU3p/ByTOawzcOAg==", @@ -6530,7 +6541,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.723.0.tgz", "integrity": "sha512-hniWi1x4JHVwKElANh9afKIMUhAutHVBRD8zo6usr0PAoj+Waf220+1ULS74GXtLXAPCiNXl5Og+PHA7xT8ElQ==", @@ -6549,7 +6560,7 @@ "@aws-sdk/client-sso-oidc": "^3.723.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-web-identity": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.723.0.tgz", "integrity": "sha512-tl7pojbFbr3qLcOE6xWaNCf1zEfZrIdSJtOPeSXfV/thFMMAvIjgf3YN6Zo1a6cxGee8zrV/C8PgOH33n+Ev/A==", @@ -6568,7 +6579,7 @@ "@aws-sdk/client-sts": "^3.723.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-bucket-endpoint": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.726.0.tgz", "integrity": "sha512-vpaP80rZqwu0C3ELayIcRIW84/nd1tadeoqllT+N9TDshuEvq4UJ+w47OBHB7RkHFJoc79lXXNYle0fdQdaE/A==", @@ -6586,7 +6597,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-expect-continue": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-expect-continue": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.723.0.tgz", "integrity": "sha512-w/O0EkIzkiqvGu7U8Ke7tue0V0HYM5dZQrz6nVU+R8T2LddWJ+njEIHU4Wh8aHPLQXdZA5NQumv0xLPdEutykw==", @@ -6601,7 +6612,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-flexible-checksums": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-flexible-checksums": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.723.0.tgz", "integrity": "sha512-JY76mrUCLa0FHeMZp8X9+KK6uEuZaRZaQrlgq6zkXX/3udukH0T3YdFC+Y9uw5ddbiwZ5+KwgmlhnPpiXKfP4g==", @@ -6625,7 +6636,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-host-header": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-host-header": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.723.0.tgz", "integrity": "sha512-LLVzLvk299pd7v4jN9yOSaWDZDfH0SnBPb6q+FDPaOCMGBY8kuwQso7e/ozIKSmZHRMGO3IZrflasHM+rI+2YQ==", @@ -6640,7 +6651,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-location-constraint": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-location-constraint": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.723.0.tgz", "integrity": "sha512-inp9tyrdRWjGOMu1rzli8i2gTo0P4X6L7nNRXNTKfyPNZcBimZ4H0H1B671JofSI5isaklVy5r4pvv2VjjLSHw==", @@ -6654,7 +6665,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-logger": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-logger": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.723.0.tgz", "integrity": "sha512-chASQfDG5NJ8s5smydOEnNK7N0gDMyuPbx7dYYcm1t/PKtnVfvWF+DHCTrRC2Ej76gLJVCVizlAJKM8v8Kg3cg==", @@ -6668,7 +6679,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-recursion-detection": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.723.0.tgz", "integrity": "sha512-7usZMtoynT9/jxL/rkuDOFQ0C2mhXl4yCm67Rg7GNTstl67u7w5WN1aIRImMeztaKlw8ExjoTyo6WTs1Kceh7A==", @@ -6683,7 +6694,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-sdk-s3": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-sdk-s3": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.723.0.tgz", "integrity": "sha512-wfjOvNJVp8LDWhq4wO5jtSMb8Vgf4tNlR7QTEQfoYc6AGU3WlK5xyUQcpfcpwytEhQTN9u0cJLQpSyXDO+qSCw==", @@ -6708,7 +6719,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-sdk-sqs": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-sdk-sqs": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.723.0.tgz", "integrity": "sha512-CnOCbwq5VRSawX4FIWO9gb00iEoOKuD0ygbPQZLADNgeMimmJXIEa3eSYUtBYaXafwPIiMh2vffd2mGhx5rVWQ==", @@ -6725,7 +6736,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-ssec": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-ssec": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.723.0.tgz", "integrity": "sha512-Bs+8RAeSMik6ZYCGSDJzJieGsDDh2fRbh1HQG94T8kpwBXVxMYihm6e9Xp2cyl+w9fyyCnh0IdCKChP/DvrdhA==", @@ -6739,7 +6750,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-user-agent": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/middleware-user-agent": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.726.0.tgz", "integrity": "sha512-hZvzuE5S0JmFie1r68K2wQvJbzyxJFdzltj9skgnnwdvLe8F/tz7MqLkm28uV0m4jeHk0LpiBo6eZaPkQiwsZQ==", @@ -6757,7 +6768,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/region-config-resolver": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/region-config-resolver": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.723.0.tgz", "integrity": "sha512-tGF/Cvch3uQjZIj34LY2mg8M2Dr4kYG8VU8Yd0dFnB1ybOEOveIK/9ypUo9ycZpB9oO6q01KRe5ijBaxNueUQg==", @@ -6774,7 +6785,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/signature-v4-multi-region": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/signature-v4-multi-region": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.723.0.tgz", "integrity": "sha512-lJlVAa5Sl589qO8lwMLVUtnlF1Q7I+6k1Iomv2goY9d1bRl4q2N5Pit2qJVr2AMW0sceQXeh23i2a/CKOqVAdg==", @@ -6791,7 +6802,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/types": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/types": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.723.0.tgz", "integrity": "sha512-LmK3kwiMZG1y5g3LGihT9mNkeNOmwEyPk6HGcJqh0wOSV4QpWoKu2epyKE4MLQNUUlz2kOVbVbOrwmI6ZcteuA==", @@ -6804,7 +6815,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-endpoints": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/util-endpoints": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.726.0.tgz", "integrity": "sha512-sLd30ASsPMoPn3XBK50oe/bkpJ4N8Bpb7SbhoxcY3Lk+fSASaWxbbXE81nbvCnkxrZCvkPOiDHzJCp1E2im71A==", @@ -6819,7 +6830,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-user-agent-browser": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.723.0.tgz", "integrity": "sha512-Wh9I6j2jLhNFq6fmXydIpqD1WyQLyTfSxjW9B+PXSnPyk3jtQW8AKQur7p97rO8LAUzVI0bv8kb3ZzDEVbquIg==", @@ -6831,7 +6842,7 @@ "tslib": "^2.6.2" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-user-agent-node": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/util-user-agent-node": { "version": "3.726.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.726.0.tgz", "integrity": "sha512-iEj6KX9o6IQf23oziorveRqyzyclWai95oZHDJtYav3fvLJKStwSjygO4xSF7ycHcTYeCHSLO1FFOHgGVs4Viw==", @@ -6855,7 +6866,7 @@ } } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/xml-builder": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@aws-sdk/xml-builder": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.723.0.tgz", "integrity": "sha512-5xK2SqGU1mzzsOeemy7cy3fGKxR1sEpUs4pEiIjaT0OIvU+fZaDVUEYWOqsgns6wI90XZEQJlXtI8uAHX/do5Q==", @@ -6868,7 +6879,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@smithy/service-error-classification": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@smithy/service-error-classification": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz", "integrity": "sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ==", @@ -6880,7 +6891,7 @@ "node": ">=14.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@smithy/service-error-classification/node_modules/@smithy/types": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/@smithy/service-error-classification/node_modules/@smithy/types": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", @@ -6892,7 +6903,7 @@ "node": ">=14.0.0" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/aws-xray-sdk": { "version": "3.10.2", "resolved": "https://registry.npmjs.org/aws-xray-sdk/-/aws-xray-sdk-3.10.2.tgz", "integrity": "sha512-T9Qwq65hUQo4GtZ7WPAzpLGd7y8bDKODlJkKAYsQKMcUIIpMPYWsSxd38ZLy3uwTY0ErkrG6Pqmc5Zs1p0BmZg==", @@ -6907,7 +6918,7 @@ "node": ">= 14.x" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-core": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/aws-xray-sdk-core": { "version": "3.10.2", "resolved": "https://registry.npmjs.org/aws-xray-sdk-core/-/aws-xray-sdk-core-3.10.2.tgz", "integrity": "sha512-hAFEB+Stqm4FoQmIuyw5AzGVJh3BSfvLjK7IK4YYRXXLt1Oq9KS6pv2samYgRTTTXsxhmVpDjiYF3Xo/gfXIXA==", @@ -6924,7 +6935,7 @@ "node": ">= 14.x" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-express": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/aws-xray-sdk-express": { "version": "3.10.2", "resolved": "https://registry.npmjs.org/aws-xray-sdk-express/-/aws-xray-sdk-express-3.10.2.tgz", "integrity": "sha512-1NJnQNTmRcQSl0hdwIdQ+3UXhzeXTYR+yyY87bmzDDjHer1GPGQYeYRhkpCGLx8bRF7JpYlHoclA1RVhH3pWMw==", @@ -6939,7 +6950,7 @@ "aws-xray-sdk-core": "^3.10.2" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-mysql": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/aws-xray-sdk-mysql": { "version": "3.10.2", "resolved": "https://registry.npmjs.org/aws-xray-sdk-mysql/-/aws-xray-sdk-mysql-3.10.2.tgz", "integrity": "sha512-TybN+z0XIWbputEy57T+jQEp5OKFs0daRrQ0t8aU+jAJfpuVgN69WoQrV/LFj2HITVL+ISMQsaUR5dvxWY+ZYQ==", @@ -6954,7 +6965,7 @@ "aws-xray-sdk-core": "^3.10.2" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-postgres": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/aws-xray-sdk-postgres": { "version": "3.10.2", "resolved": "https://registry.npmjs.org/aws-xray-sdk-postgres/-/aws-xray-sdk-postgres-3.10.2.tgz", "integrity": "sha512-ku17VjrT25BpCYUb5Vqcfh8pkc62SaVIeritCH2No85LOzU9jl0oPUhlRG4NzHkdmIJuUtLP1IxQlwIGAQgreg==", @@ -6969,7 +6980,7 @@ "aws-xray-sdk-core": "^3.10.2" } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/debug": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", @@ -6986,13 +6997,13 @@ } } }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/http-cache-semantics": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "license": "BSD-2-Clause" }, - "node_modules/@adobe/spacecat-shared-slack-client/node_modules/uuid": { + "node_modules/@adobe/spacecat-shared-rum-api-client/node_modules/uuid": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", @@ -7005,65 +7016,36 @@ "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@adobe/spacecat-shared-utils": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-utils/-/spacecat-shared-utils-1.48.0.tgz", - "integrity": "sha512-SRt7/2Tu6mdrPWOiSbyHsbIJ3Qik7xeWQocLXg9Bo2Vn6mikHBKA6FoWYebjH317JDiqthehgS+3yHuoejSxKQ==", - "license": "Apache-2.0", - "dependencies": { - "@adobe/fetch": "4.2.2", - "@adobe/spacecat-shared-data-access": "2.45.0", - "@adobe/spacecat-shared-ims-client": "1.8.3", - "@aws-sdk/client-s3": "3.864.0", - "@aws-sdk/client-secrets-manager": "3.864.0", - "@aws-sdk/client-sqs": "3.864.0", - "@json2csv/plainjs": "7.0.6", - "aws-xray-sdk": "3.10.3", - "date-fns": "2.30.0", - "uuid": "11.1.0" - }, - "engines": { - "node": ">=22.0.0 <23.0.0", - "npm": ">=10.9.0 <12.0.0" - } - }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-data-access": { - "version": "2.45.0", - "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-data-access/-/spacecat-shared-data-access-2.45.0.tgz", - "integrity": "sha512-ctvtTNdufP5g51lpfy2MoNrd1J/z/zWucOxAnEKDJl1k+S5+OEQL3cZXK8EcDwMyMr88h8ai3rXE2UvGdjWX9g==", + "node_modules/@adobe/spacecat-shared-slack-client": { + "version": "1.5.23", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-slack-client/-/spacecat-shared-slack-client-1.5.23.tgz", + "integrity": "sha512-v8tGA5tbU/J4VSj8ZjNcLhPuw5SD9JpswlBGgshCwubKFO+uSoTij7YfKKwmOwBz/3YlNkt6mREGXOmH58whrA==", "license": "Apache-2.0", "dependencies": { - "@adobe/spacecat-shared-utils": "1.39.1", - "@aws-sdk/client-dynamodb": "3.859.0", - "@aws-sdk/lib-dynamodb": "3.859.0", - "@types/joi": "17.2.3", - "aws-xray-sdk": "3.10.3", - "electrodb": "3.4.3", - "joi": "17.13.3", - "pluralize": "8.0.0", - "uuid": "11.1.0" + "@adobe/helix-universal": "5.2.2", + "@adobe/spacecat-shared-utils": "1.26.4", + "@slack/web-api": "7.9.3" }, "engines": { "node": ">=22.0.0 <23.0.0", "npm": ">=10.9.0 <12.0.0" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-ims-client/-/spacecat-shared-ims-client-1.8.3.tgz", - "integrity": "sha512-G1E8whUWr1dFzWdzq/iacODwmNuYlUY8V2l4Y2TWzymjpOzsj42f/Xbjh5EAOxGQlbUIhf6aEO7QnZJEdcugyA==", + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@adobe/fetch": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.11.tgz", + "integrity": "sha512-Zak2kPJuIdg9UQQfUgNm848vRAg2pdOqYYU+7DkCYWO+SgZiMV+qy99BpO1geDiP2rQ2M7JH5oNXRTEvEWglRQ==", "license": "Apache-2.0", "dependencies": { - "@adobe/fetch": "4.2.2", - "@adobe/helix-universal": "5.2.2", - "@adobe/spacecat-shared-utils": "1.26.4" + "debug": "4.4.0", + "http-cache-semantics": "4.1.1", + "lru-cache": "7.18.3" }, "engines": { - "node": ">=22.0.0 <23.0.0", - "npm": ">=10.9.0 <12.0.0" + "node": ">=14.16" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@adobe/spacecat-shared-utils": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@adobe/spacecat-shared-utils": { "version": "1.26.4", "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-utils/-/spacecat-shared-utils-1.26.4.tgz", "integrity": "sha512-d/GZ6j//dXW9+YjgRO0PhZcvhXMlhfUHrPxcG/2OMD5gkd8fOd39+Y1JMu/6fgpNVOR7iQogb/5d5UXaHEWygg==", @@ -7082,21 +7064,7 @@ "npm": ">=10.9.0 <12.0.0" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/fetch": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.11.tgz", - "integrity": "sha512-Zak2kPJuIdg9UQQfUgNm848vRAg2pdOqYYU+7DkCYWO+SgZiMV+qy99BpO1geDiP2rQ2M7JH5oNXRTEvEWglRQ==", - "license": "Apache-2.0", - "dependencies": { - "debug": "4.4.0", - "http-cache-semantics": "4.1.1", - "lru-cache": "7.18.3" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-s3": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-s3": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.726.1.tgz", "integrity": "sha512-UpOGcob87DiuS2d3fW6vDZg94g57mNiOSkzvR/6GOdvBSlUgk8LLwVzGASB71FdKMl1EGEr4MeD5uKH9JsG+dw==", @@ -7165,7 +7133,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-secrets-manager": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-secrets-manager": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.726.1.tgz", "integrity": "sha512-eO9WpE8IyQrs2xWhfQCdHcVTHQTwJ56JGx3FhwhtFWWYHIS0c1bTIAvP5E3jSWAZNaK1iWdVexz3yGi3aAnGzA==", @@ -7219,7 +7187,7 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", @@ -7232,7 +7200,7 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-sqs": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sqs": { "version": "3.726.1", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.726.1.tgz", "integrity": "sha512-QSsmlMNVgKUzDpDC3Ya1i0tvFjVcvTBoJfSh7LBkuMJiboY2j2aeD74OX7xGkxu+QLc8wWUjT//KYDm6KwHk7w==", @@ -7286,7 +7254,1007 @@ "node": ">=18.0.0" } }, - "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/core": { + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sso": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.726.0.tgz", + "integrity": "sha512-NM5pjv2qglEc4XN3nnDqtqGsSGv1k5YTmzDo3W3pObItHmpS8grSeNfX9zSH+aVl0Q8hE4ZIgvTPNZ+GzwVlqg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/middleware-host-header": "3.723.0", + "@aws-sdk/middleware-logger": "3.723.0", + "@aws-sdk/middleware-recursion-detection": "3.723.0", + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/region-config-resolver": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@aws-sdk/util-user-agent-browser": "3.723.0", + "@aws-sdk/util-user-agent-node": "3.726.0", + "@smithy/config-resolver": "^4.0.0", + "@smithy/core": "^3.0.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/hash-node": "^4.0.0", + "@smithy/invalid-dependency": "^4.0.0", + "@smithy/middleware-content-length": "^4.0.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/middleware-retry": "^4.0.0", + "@smithy/middleware-serde": "^4.0.0", + "@smithy/middleware-stack": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/url-parser": "^4.0.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.0", + "@smithy/util-defaults-mode-node": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-retry": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/client-sts": { + "version": "3.726.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.726.1.tgz", + "integrity": "sha512-qh9Q9Vu1hrM/wMBOBIaskwnE4GTFaZu26Q6WHwyWNfj7J8a40vBxpW16c2vYXHLBtwRKM1be8uRLkmDwghpiNw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.726.0", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/credential-provider-node": "3.726.0", + "@aws-sdk/middleware-host-header": "3.723.0", + "@aws-sdk/middleware-logger": "3.723.0", + "@aws-sdk/middleware-recursion-detection": "3.723.0", + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/region-config-resolver": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@aws-sdk/util-user-agent-browser": "3.723.0", + "@aws-sdk/util-user-agent-node": "3.726.0", + "@smithy/config-resolver": "^4.0.0", + "@smithy/core": "^3.0.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/hash-node": "^4.0.0", + "@smithy/invalid-dependency": "^4.0.0", + "@smithy/middleware-content-length": "^4.0.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/middleware-retry": "^4.0.0", + "@smithy/middleware-serde": "^4.0.0", + "@smithy/middleware-stack": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/url-parser": "^4.0.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.0", + "@smithy/util-defaults-mode-node": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-retry": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/core": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.723.0.tgz", + "integrity": "sha512-UraXNmvqj3vScSsTkjMwQkhei30BhXlW5WxX6JacMKVtl95c7z0qOXquTWeTalYkFfulfdirUhvSZrl+hcyqTw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/core": "^3.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.723.0.tgz", + "integrity": "sha512-OuH2yULYUHTVDUotBoP/9AEUIJPn81GQ/YBtZLoo2QyezRJ2QiO/1epVtbJlhNZRwXrToLEDmQGA2QfC8c7pbA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.723.0.tgz", + "integrity": "sha512-DTsKC6xo/kz/ZSs1IcdbQMTgiYbpGTGEd83kngFc1bzmw7AmK92DBZKNZpumf8R/UfSpTcj9zzUUmrWz1kD0eQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-stream": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.726.0.tgz", + "integrity": "sha512-seTtcKL2+gZX6yK1QRPr5mDJIBOatrpoyrO8D5b8plYtV/PDbDW3mtDJSWFHet29G61ZmlNElyXRqQCXn9WX+A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/credential-provider-env": "3.723.0", + "@aws-sdk/credential-provider-http": "3.723.0", + "@aws-sdk/credential-provider-process": "3.723.0", + "@aws-sdk/credential-provider-sso": "3.726.0", + "@aws-sdk/credential-provider-web-identity": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/credential-provider-imds": "^4.0.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/shared-ini-file-loader": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.726.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.726.0.tgz", + "integrity": "sha512-jjsewBcw/uLi24x8JbnuDjJad4VA9ROCE94uVRbEnGmUEsds75FWOKp3fWZLQlmjLtzsIbJOZLALkZP86liPaw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.723.0", + "@aws-sdk/credential-provider-http": "3.723.0", + "@aws-sdk/credential-provider-ini": "3.726.0", + "@aws-sdk/credential-provider-process": "3.723.0", + "@aws-sdk/credential-provider-sso": "3.726.0", + "@aws-sdk/credential-provider-web-identity": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/credential-provider-imds": "^4.0.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/shared-ini-file-loader": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.723.0.tgz", + "integrity": "sha512-fgupvUjz1+jeoCBA7GMv0L6xEk92IN6VdF4YcFhsgRHlHvNgm7ayaoKQg7pz2JAAhG/3jPX6fp0ASNy+xOhmPA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/shared-ini-file-loader": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.726.0.tgz", + "integrity": "sha512-WxkN76WeB08j2yw7jUH9yCMPxmT9eBFd9ZA/aACG7yzOIlsz7gvG3P2FQ0tVg25GHM0E4PdU3p/ByTOawzcOAg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.726.0", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/token-providers": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/shared-ini-file-loader": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.723.0.tgz", + "integrity": "sha512-hniWi1x4JHVwKElANh9afKIMUhAutHVBRD8zo6usr0PAoj+Waf220+1ULS74GXtLXAPCiNXl5Og+PHA7xT8ElQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/shared-ini-file-loader": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.723.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.723.0.tgz", + "integrity": "sha512-tl7pojbFbr3qLcOE6xWaNCf1zEfZrIdSJtOPeSXfV/thFMMAvIjgf3YN6Zo1a6cxGee8zrV/C8PgOH33n+Ev/A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.723.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.726.0.tgz", + "integrity": "sha512-vpaP80rZqwu0C3ELayIcRIW84/nd1tadeoqllT+N9TDshuEvq4UJ+w47OBHB7RkHFJoc79lXXNYle0fdQdaE/A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-arn-parser": "3.723.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-config-provider": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.723.0.tgz", + "integrity": "sha512-w/O0EkIzkiqvGu7U8Ke7tue0V0HYM5dZQrz6nVU+R8T2LddWJ+njEIHU4Wh8aHPLQXdZA5NQumv0xLPdEutykw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.723.0.tgz", + "integrity": "sha512-JY76mrUCLa0FHeMZp8X9+KK6uEuZaRZaQrlgq6zkXX/3udukH0T3YdFC+Y9uw5ddbiwZ5+KwgmlhnPpiXKfP4g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-stream": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.723.0.tgz", + "integrity": "sha512-LLVzLvk299pd7v4jN9yOSaWDZDfH0SnBPb6q+FDPaOCMGBY8kuwQso7e/ozIKSmZHRMGO3IZrflasHM+rI+2YQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.723.0.tgz", + "integrity": "sha512-inp9tyrdRWjGOMu1rzli8i2gTo0P4X6L7nNRXNTKfyPNZcBimZ4H0H1B671JofSI5isaklVy5r4pvv2VjjLSHw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-logger": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.723.0.tgz", + "integrity": "sha512-chASQfDG5NJ8s5smydOEnNK7N0gDMyuPbx7dYYcm1t/PKtnVfvWF+DHCTrRC2Ej76gLJVCVizlAJKM8v8Kg3cg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.723.0.tgz", + "integrity": "sha512-7usZMtoynT9/jxL/rkuDOFQ0C2mhXl4yCm67Rg7GNTstl67u7w5WN1aIRImMeztaKlw8ExjoTyo6WTs1Kceh7A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.723.0.tgz", + "integrity": "sha512-wfjOvNJVp8LDWhq4wO5jtSMb8Vgf4tNlR7QTEQfoYc6AGU3WlK5xyUQcpfcpwytEhQTN9u0cJLQpSyXDO+qSCw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-arn-parser": "3.723.0", + "@smithy/core": "^3.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-stream": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-sdk-sqs": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.723.0.tgz", + "integrity": "sha512-CnOCbwq5VRSawX4FIWO9gb00iEoOKuD0ygbPQZLADNgeMimmJXIEa3eSYUtBYaXafwPIiMh2vffd2mGhx5rVWQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-ssec": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.723.0.tgz", + "integrity": "sha512-Bs+8RAeSMik6ZYCGSDJzJieGsDDh2fRbh1HQG94T8kpwBXVxMYihm6e9Xp2cyl+w9fyyCnh0IdCKChP/DvrdhA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.726.0.tgz", + "integrity": "sha512-hZvzuE5S0JmFie1r68K2wQvJbzyxJFdzltj9skgnnwdvLe8F/tz7MqLkm28uV0m4jeHk0LpiBo6eZaPkQiwsZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@smithy/core": "^3.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.723.0.tgz", + "integrity": "sha512-tGF/Cvch3uQjZIj34LY2mg8M2Dr4kYG8VU8Yd0dFnB1ybOEOveIK/9ypUo9ycZpB9oO6q01KRe5ijBaxNueUQg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.723.0.tgz", + "integrity": "sha512-lJlVAa5Sl589qO8lwMLVUtnlF1Q7I+6k1Iomv2goY9d1bRl4q2N5Pit2qJVr2AMW0sceQXeh23i2a/CKOqVAdg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/types": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.723.0.tgz", + "integrity": "sha512-LmK3kwiMZG1y5g3LGihT9mNkeNOmwEyPk6HGcJqh0wOSV4QpWoKu2epyKE4MLQNUUlz2kOVbVbOrwmI6ZcteuA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-endpoints": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.726.0.tgz", + "integrity": "sha512-sLd30ASsPMoPn3XBK50oe/bkpJ4N8Bpb7SbhoxcY3Lk+fSASaWxbbXE81nbvCnkxrZCvkPOiDHzJCp1E2im71A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/types": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.723.0.tgz", + "integrity": "sha512-Wh9I6j2jLhNFq6fmXydIpqD1WyQLyTfSxjW9B+PXSnPyk3jtQW8AKQur7p97rO8LAUzVI0bv8kb3ZzDEVbquIg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.723.0", + "@smithy/types": "^4.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.726.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.726.0.tgz", + "integrity": "sha512-iEj6KX9o6IQf23oziorveRqyzyclWai95oZHDJtYav3fvLJKStwSjygO4xSF7ycHcTYeCHSLO1FFOHgGVs4Viw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/types": "3.723.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@aws-sdk/xml-builder": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.723.0.tgz", + "integrity": "sha512-5xK2SqGU1mzzsOeemy7cy3fGKxR1sEpUs4pEiIjaT0OIvU+fZaDVUEYWOqsgns6wI90XZEQJlXtI8uAHX/do5Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@smithy/service-error-classification": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz", + "integrity": "sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^2.12.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/@smithy/service-error-classification/node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/aws-xray-sdk/-/aws-xray-sdk-3.10.2.tgz", + "integrity": "sha512-T9Qwq65hUQo4GtZ7WPAzpLGd7y8bDKODlJkKAYsQKMcUIIpMPYWsSxd38ZLy3uwTY0ErkrG6Pqmc5Zs1p0BmZg==", + "license": "Apache-2.0", + "dependencies": { + "aws-xray-sdk-core": "3.10.2", + "aws-xray-sdk-express": "3.10.2", + "aws-xray-sdk-mysql": "3.10.2", + "aws-xray-sdk-postgres": "3.10.2" + }, + "engines": { + "node": ">= 14.x" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-core": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/aws-xray-sdk-core/-/aws-xray-sdk-core-3.10.2.tgz", + "integrity": "sha512-hAFEB+Stqm4FoQmIuyw5AzGVJh3BSfvLjK7IK4YYRXXLt1Oq9KS6pv2samYgRTTTXsxhmVpDjiYF3Xo/gfXIXA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.4.1", + "@smithy/service-error-classification": "^2.0.4", + "@types/cls-hooked": "^4.3.3", + "atomic-batcher": "^1.0.2", + "cls-hooked": "^4.2.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">= 14.x" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-express": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/aws-xray-sdk-express/-/aws-xray-sdk-express-3.10.2.tgz", + "integrity": "sha512-1NJnQNTmRcQSl0hdwIdQ+3UXhzeXTYR+yyY87bmzDDjHer1GPGQYeYRhkpCGLx8bRF7JpYlHoclA1RVhH3pWMw==", + "license": "Apache-2.0", + "dependencies": { + "@types/express": "*" + }, + "engines": { + "node": ">= 14.x" + }, + "peerDependencies": { + "aws-xray-sdk-core": "^3.10.2" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-mysql": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/aws-xray-sdk-mysql/-/aws-xray-sdk-mysql-3.10.2.tgz", + "integrity": "sha512-TybN+z0XIWbputEy57T+jQEp5OKFs0daRrQ0t8aU+jAJfpuVgN69WoQrV/LFj2HITVL+ISMQsaUR5dvxWY+ZYQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/mysql": "*" + }, + "engines": { + "node": ">= 14.x" + }, + "peerDependencies": { + "aws-xray-sdk-core": "^3.10.2" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/aws-xray-sdk-postgres": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/aws-xray-sdk-postgres/-/aws-xray-sdk-postgres-3.10.2.tgz", + "integrity": "sha512-ku17VjrT25BpCYUb5Vqcfh8pkc62SaVIeritCH2No85LOzU9jl0oPUhlRG4NzHkdmIJuUtLP1IxQlwIGAQgreg==", + "license": "Apache-2.0", + "dependencies": { + "@types/pg": "*" + }, + "engines": { + "node": ">= 14.x" + }, + "peerDependencies": { + "aws-xray-sdk-core": "^3.10.2" + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/@adobe/spacecat-shared-slack-client/node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@adobe/spacecat-shared-utils": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-utils/-/spacecat-shared-utils-1.48.0.tgz", + "integrity": "sha512-SRt7/2Tu6mdrPWOiSbyHsbIJ3Qik7xeWQocLXg9Bo2Vn6mikHBKA6FoWYebjH317JDiqthehgS+3yHuoejSxKQ==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/fetch": "4.2.2", + "@adobe/spacecat-shared-data-access": "2.45.0", + "@adobe/spacecat-shared-ims-client": "1.8.3", + "@aws-sdk/client-s3": "3.864.0", + "@aws-sdk/client-secrets-manager": "3.864.0", + "@aws-sdk/client-sqs": "3.864.0", + "@json2csv/plainjs": "7.0.6", + "aws-xray-sdk": "3.10.3", + "date-fns": "2.30.0", + "uuid": "11.1.0" + }, + "engines": { + "node": ">=22.0.0 <23.0.0", + "npm": ">=10.9.0 <12.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-data-access": { + "version": "2.45.0", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-data-access/-/spacecat-shared-data-access-2.45.0.tgz", + "integrity": "sha512-ctvtTNdufP5g51lpfy2MoNrd1J/z/zWucOxAnEKDJl1k+S5+OEQL3cZXK8EcDwMyMr88h8ai3rXE2UvGdjWX9g==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/spacecat-shared-utils": "1.39.1", + "@aws-sdk/client-dynamodb": "3.859.0", + "@aws-sdk/lib-dynamodb": "3.859.0", + "@types/joi": "17.2.3", + "aws-xray-sdk": "3.10.3", + "electrodb": "3.4.3", + "joi": "17.13.3", + "pluralize": "8.0.0", + "uuid": "11.1.0" + }, + "engines": { + "node": ">=22.0.0 <23.0.0", + "npm": ">=10.9.0 <12.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-ims-client/-/spacecat-shared-ims-client-1.8.3.tgz", + "integrity": "sha512-G1E8whUWr1dFzWdzq/iacODwmNuYlUY8V2l4Y2TWzymjpOzsj42f/Xbjh5EAOxGQlbUIhf6aEO7QnZJEdcugyA==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/fetch": "4.2.2", + "@adobe/helix-universal": "5.2.2", + "@adobe/spacecat-shared-utils": "1.26.4" + }, + "engines": { + "node": ">=22.0.0 <23.0.0", + "npm": ">=10.9.0 <12.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@adobe/spacecat-shared-utils": { + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@adobe/spacecat-shared-utils/-/spacecat-shared-utils-1.26.4.tgz", + "integrity": "sha512-d/GZ6j//dXW9+YjgRO0PhZcvhXMlhfUHrPxcG/2OMD5gkd8fOd39+Y1JMu/6fgpNVOR7iQogb/5d5UXaHEWygg==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/fetch": "4.1.11", + "@aws-sdk/client-s3": "3.726.1", + "@aws-sdk/client-secrets-manager": "3.726.1", + "@aws-sdk/client-sqs": "3.726.1", + "@json2csv/plainjs": "7.0.6", + "aws-xray-sdk": "3.10.2", + "uuid": "11.0.5" + }, + "engines": { + "node": ">=22.0.0 <23.0.0", + "npm": ">=10.9.0 <12.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/fetch": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.11.tgz", + "integrity": "sha512-Zak2kPJuIdg9UQQfUgNm848vRAg2pdOqYYU+7DkCYWO+SgZiMV+qy99BpO1geDiP2rQ2M7JH5oNXRTEvEWglRQ==", + "license": "Apache-2.0", + "dependencies": { + "debug": "4.4.0", + "http-cache-semantics": "4.1.1", + "lru-cache": "7.18.3" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-s3": { + "version": "3.726.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.726.1.tgz", + "integrity": "sha512-UpOGcob87DiuS2d3fW6vDZg94g57mNiOSkzvR/6GOdvBSlUgk8LLwVzGASB71FdKMl1EGEr4MeD5uKH9JsG+dw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.726.0", + "@aws-sdk/client-sts": "3.726.1", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/credential-provider-node": "3.726.0", + "@aws-sdk/middleware-bucket-endpoint": "3.726.0", + "@aws-sdk/middleware-expect-continue": "3.723.0", + "@aws-sdk/middleware-flexible-checksums": "3.723.0", + "@aws-sdk/middleware-host-header": "3.723.0", + "@aws-sdk/middleware-location-constraint": "3.723.0", + "@aws-sdk/middleware-logger": "3.723.0", + "@aws-sdk/middleware-recursion-detection": "3.723.0", + "@aws-sdk/middleware-sdk-s3": "3.723.0", + "@aws-sdk/middleware-ssec": "3.723.0", + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/region-config-resolver": "3.723.0", + "@aws-sdk/signature-v4-multi-region": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@aws-sdk/util-user-agent-browser": "3.723.0", + "@aws-sdk/util-user-agent-node": "3.726.0", + "@aws-sdk/xml-builder": "3.723.0", + "@smithy/config-resolver": "^4.0.0", + "@smithy/core": "^3.0.0", + "@smithy/eventstream-serde-browser": "^4.0.0", + "@smithy/eventstream-serde-config-resolver": "^4.0.0", + "@smithy/eventstream-serde-node": "^4.0.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/hash-blob-browser": "^4.0.0", + "@smithy/hash-node": "^4.0.0", + "@smithy/hash-stream-node": "^4.0.0", + "@smithy/invalid-dependency": "^4.0.0", + "@smithy/md5-js": "^4.0.0", + "@smithy/middleware-content-length": "^4.0.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/middleware-retry": "^4.0.0", + "@smithy/middleware-serde": "^4.0.0", + "@smithy/middleware-stack": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/url-parser": "^4.0.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.0", + "@smithy/util-defaults-mode-node": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-retry": "^4.0.0", + "@smithy/util-stream": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "@smithy/util-waiter": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-secrets-manager": { + "version": "3.726.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.726.1.tgz", + "integrity": "sha512-eO9WpE8IyQrs2xWhfQCdHcVTHQTwJ56JGx3FhwhtFWWYHIS0c1bTIAvP5E3jSWAZNaK1iWdVexz3yGi3aAnGzA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.726.0", + "@aws-sdk/client-sts": "3.726.1", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/credential-provider-node": "3.726.0", + "@aws-sdk/middleware-host-header": "3.723.0", + "@aws-sdk/middleware-logger": "3.723.0", + "@aws-sdk/middleware-recursion-detection": "3.723.0", + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/region-config-resolver": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@aws-sdk/util-user-agent-browser": "3.723.0", + "@aws-sdk/util-user-agent-node": "3.726.0", + "@smithy/config-resolver": "^4.0.0", + "@smithy/core": "^3.0.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/hash-node": "^4.0.0", + "@smithy/invalid-dependency": "^4.0.0", + "@smithy/middleware-content-length": "^4.0.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/middleware-retry": "^4.0.0", + "@smithy/middleware-serde": "^4.0.0", + "@smithy/middleware-stack": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/url-parser": "^4.0.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.0", + "@smithy/util-defaults-mode-node": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-retry": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/client-sqs": { + "version": "3.726.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.726.1.tgz", + "integrity": "sha512-QSsmlMNVgKUzDpDC3Ya1i0tvFjVcvTBoJfSh7LBkuMJiboY2j2aeD74OX7xGkxu+QLc8wWUjT//KYDm6KwHk7w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.726.0", + "@aws-sdk/client-sts": "3.726.1", + "@aws-sdk/core": "3.723.0", + "@aws-sdk/credential-provider-node": "3.726.0", + "@aws-sdk/middleware-host-header": "3.723.0", + "@aws-sdk/middleware-logger": "3.723.0", + "@aws-sdk/middleware-recursion-detection": "3.723.0", + "@aws-sdk/middleware-sdk-sqs": "3.723.0", + "@aws-sdk/middleware-user-agent": "3.726.0", + "@aws-sdk/region-config-resolver": "3.723.0", + "@aws-sdk/types": "3.723.0", + "@aws-sdk/util-endpoints": "3.726.0", + "@aws-sdk/util-user-agent-browser": "3.723.0", + "@aws-sdk/util-user-agent-node": "3.726.0", + "@smithy/config-resolver": "^4.0.0", + "@smithy/core": "^3.0.0", + "@smithy/fetch-http-handler": "^5.0.0", + "@smithy/hash-node": "^4.0.0", + "@smithy/invalid-dependency": "^4.0.0", + "@smithy/md5-js": "^4.0.0", + "@smithy/middleware-content-length": "^4.0.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/middleware-retry": "^4.0.0", + "@smithy/middleware-serde": "^4.0.0", + "@smithy/middleware-stack": "^4.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/node-http-handler": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/url-parser": "^4.0.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.0", + "@smithy/util-defaults-mode-node": "^4.0.0", + "@smithy/util-endpoints": "^3.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-retry": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@adobe/spacecat-shared-utils/node_modules/@adobe/spacecat-shared-ims-client/node_modules/@aws-sdk/core": { "version": "3.723.0", "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.723.0.tgz", "integrity": "sha512-UraXNmvqj3vScSsTkjMwQkhei30BhXlW5WxX6JacMKVtl95c7z0qOXquTWeTalYkFfulfdirUhvSZrl+hcyqTw==", @@ -33408,17 +34376,24 @@ "license": "ISC" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shallowequal": { @@ -34924,6 +35899,21 @@ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "license": "MIT" }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index 8f20b49..c1f25a5 100755 --- a/package.json +++ b/package.json @@ -65,9 +65,10 @@ "@adobe/helix-status": "10.1.5", "@adobe/helix-universal": "5.2.2", "@adobe/helix-universal-logger": "3.0.27", - "@adobe/spacecat-shared-ims-client": "1.8.8", "@adobe/spacecat-shared-data-access": "2.54.0", "@adobe/spacecat-shared-http-utils": "1.15.2", + "@adobe/spacecat-shared-ims-client": "1.8.8", + "@adobe/spacecat-shared-rum-api-client": "^2.36.4", "@adobe/spacecat-shared-slack-client": "^1.3.12", "@adobe/spacecat-shared-utils": "1.48.0", "@aws-sdk/client-lambda": "3.865.0", diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 52e3c81..405f2d2 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -11,10 +11,34 @@ */ import { ok } from '@adobe/spacecat-shared-http-utils'; +import RUMAPIClient from '@adobe/spacecat-shared-rum-api-client'; import { say } from '../../utils/slack-utils.js'; const TASK_TYPE = 'opportunity-status-processor'; +/** + * Checks if RUM is available for a domain by attempting to get a domainkey + * @param {string} domain - The domain to check + * @param {object} context - The context object with env and log + * @returns {Promise} True if RUM is available, false otherwise + */ +async function isRUMAvailable(domain, context) { + const { log } = context; + + try { + const rumClient = RUMAPIClient.createFrom(context); + + // Attempt to get domainkey - if this succeeds, RUM is available + await rumClient.retrieveDomainkey(domain); + + log.info(`RUM is available for domain: ${domain}`); + return true; + } catch (error) { + log.info(`RUM is not available for domain: ${domain}. Reason: ${error.message}`); + return false; + } +} + /** * Gets the opportunity title from the opportunity type * @param {string} opportunityType - The opportunity type @@ -73,8 +97,19 @@ export async function runOpportunityStatusProcessor(message, context) { return ok({ message: 'Site not found' }); } + let rumAvailable = false; + if (siteUrl) { + try { + const domain = new URL(siteUrl).hostname; + rumAvailable = await isRUMAvailable(domain, context); + } catch (error) { + log.warn(`Could not parse siteUrl for RUM check: ${siteUrl}`, error); + rumAvailable = false; + } + } + const opportunities = await site.getOpportunities(); - log.info(`Found ${opportunities.length} opportunities for site ${siteId}`); + log.info(`Found ${opportunities.length} opportunities for site ${siteId}. RUM available: ${rumAvailable}`); // Track processed opportunity types to avoid duplicates const processedTypes = new Set(); @@ -95,22 +130,38 @@ export async function runOpportunityStatusProcessor(message, context) { const opportunityTitle = getOpportunityTitle(opportunityType); const hasSuggestions = suggestions && suggestions.length > 0; const status = hasSuggestions ? ':white_check_mark:' : ':cross-x:'; - statusMessages.push(`${opportunityTitle} ${status}`); + + // Add RUM availability indicator for CWV opportunities + let statusMessage = `${opportunityTitle} ${status}`; + if (opportunityType === 'cwv') { + const rumIndicator = rumAvailable ? ':chart_with_upwards_trend:' : ':no_entry_sign:'; + statusMessage += ` (RUM: ${rumIndicator})`; + } + + statusMessages.push(statusMessage); } - // send status messages to slack - if (statusMessages.length > 0) { - const slackMessage = `:white_check_mark: *Opportunities status for site ${siteUrl}*:`; - const combinedMessage = statusMessages.join('\n'); + // Send status message to Slack if context is available + if (slackContext && statusMessages.length > 0) { + const slackMessage = `:clipboard: **Opportunity Status for ${siteUrl || siteId}**\n\n${statusMessages.join('\n')}`; await say(env, log, slackContext, slackMessage); - await say(env, log, slackContext, combinedMessage); } + + log.info(`Processed ${opportunities.length} opportunities for site ${siteId}`); + + return ok({ + message: `Opportunity status processor completed for ${opportunities.length} opportunities`, + opportunitiesProcessed: opportunities.length, + rumAvailable, + }); } catch (error) { log.error('Error in opportunity status processor:', error); - await say(env, log, slackContext, `:x: Error checking site opportunities status: ${error.message}`); + await say(env, log, slackContext, `:x: Error processing opportunities for site ${siteId}: ${error.message}`); + return ok({ + message: 'Opportunity status processor completed with errors', + error: error.message, + }); } - - return ok({ message: 'Opportunity status processor completed' }); } export default runOpportunityStatusProcessor; diff --git a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js index e4b2e01..cc06385 100644 --- a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js +++ b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js @@ -93,7 +93,7 @@ describe('Opportunity Status Processor', () => { expect(context.dataAccess.Site.findById.calledWith('test-site-id')).to.be.true; expect(mockSite.getOpportunities.called).to.be.true; - expect(context.log.info.calledWith('Found 2 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 2 opportunities for site test-site-id. RUM available: false')).to.be.true; }); it('should handle site not found error', async () => { @@ -131,7 +131,7 @@ describe('Opportunity Status Processor', () => { await runOpportunityStatusProcessor(message, context); // Should complete without error - expect(context.log.info.calledWith('Found 2 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 2 opportunities for site test-site-id. RUM available: false')).to.be.true; }); it('should handle opportunities with different statuses', async () => { @@ -154,7 +154,7 @@ describe('Opportunity Status Processor', () => { await runOpportunityStatusProcessor(message, context); - expect(context.log.info.calledWith('Found 3 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 3 opportunities for site test-site-id. RUM available: false')).to.be.true; }); it('should handle empty opportunities array', async () => { @@ -162,7 +162,7 @@ describe('Opportunity Status Processor', () => { await runOpportunityStatusProcessor(message, context); - expect(context.log.info.calledWith('Found 0 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; }); it('should handle getSuggestions errors', async () => { @@ -190,7 +190,7 @@ describe('Opportunity Status Processor', () => { mockSite.getOpportunities.resolves(mockOpportunities); await runOpportunityStatusProcessor(message, context); - expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; }); it('should deduplicate opportunity types and skip duplicates', async () => { @@ -218,7 +218,7 @@ describe('Opportunity Status Processor', () => { await runOpportunityStatusProcessor(message, context); // Should only process unique types (2 unique types, not 4 total opportunities) - expect(context.log.info.calledWith('Found 4 opportunities for site test-site-id')).to.be.true; + expect(context.log.info.calledWith('Found 4 opportunities for site test-site-id. RUM available: false')).to.be.true; // Verify that getSuggestions was only called for unique types (2 times, not 4) expect(mockOpportunities[0].getSuggestions.called).to.be.true; @@ -226,5 +226,259 @@ describe('Opportunity Status Processor', () => { expect(mockOpportunities[2].getSuggestions.called).to.be.true; expect(mockOpportunities[3].getSuggestions.called).to.be.false; // Should be skipped }); + + it('should handle RUM availability scenarios', async () => { + // Test RUM availability check when no siteUrl is provided + const mockOpportunities = [ + { + getType: () => 'cwv', + getSuggestions: sinon.stub().resolves(['suggestion1']), + }, + ]; + mockSite.getOpportunities.resolves(mockOpportunities); + + await runOpportunityStatusProcessor(message, context); + expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; + }); + + it('should handle invalid siteUrl gracefully', async () => { + message.siteUrl = 'invalid-url'; + const mockOpportunities = [ + { + getType: () => 'cwv', + getSuggestions: sinon.stub().resolves(['suggestion1']), + }, + ]; + mockSite.getOpportunities.resolves(mockOpportunities); + await runOpportunityStatusProcessor(message, context); + expect(context.log.warn.calledWith('Could not parse siteUrl for RUM check: invalid-url', sinon.match.any)).to.be.true; + expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; + }); + }); + + describe('isRUMAvailable', () => { + let mockContext; + let mockRUMClient; + + beforeEach(async () => { + mockContext = { + log: { + info: sinon.stub(), + error: sinon.stub(), + warn: sinon.stub(), + }, + env: { + RUM_ADMIN_KEY: 'test-admin-key', + }, + }; + + mockRUMClient = { + retrieveDomainkey: sinon.stub(), + }; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should handle RUM availability scenarios', async () => { + // Test RUM available (success case) + mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); + + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'https://example.com', + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, + }, + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves([]), + }), + }, + }, + }; + + await runOpportunityStatusProcessor(testMessage, testContext); + expect(createFromStub.calledWith(testContext)).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; + expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: true')).to.be.true; + + createFromStub.restore(); + }); + + it('should handle RUM unavailability scenarios', async () => { + // Test RUM unavailable (failure case) + mockRUMClient.retrieveDomainkey.rejects(new Error('Domain not found')); + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); + + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'https://unavailable.com', + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, + }, + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves([]), + }), + }, + }, + }; + + await runOpportunityStatusProcessor(testMessage, testContext); + expect(createFromStub.calledWith(testContext)).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('unavailable.com')).to.be.true; + expect(testContext.log.info.calledWith('RUM is not available for domain: unavailable.com. Reason: Domain not found')).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + + createFromStub.restore(); + }); + + it('should handle RUM client creation errors', async () => { + // Test RUM client creation failure + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').throws(new Error('RUM client creation failed')); + + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'https://error.com', + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, + }, + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves([]), + }), + }, + }, + }; + + await runOpportunityStatusProcessor(testMessage, testContext); + expect(createFromStub.calledWith(testContext)).to.be.true; + expect(testContext.log.info.calledWith('RUM is not available for domain: error.com. Reason: RUM client creation failed')).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + + createFromStub.restore(); + }); + + it('should handle CWV opportunities with RUM indicators', async () => { + // Test CWV opportunities with RUM available + const mockOpportunities = [ + { + getType: () => 'cwv', + getSuggestions: sinon.stub().resolves(['suggestion1']), + }, + ]; + + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'https://example.com', + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, + }, + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves(mockOpportunities), + }), + }, + }, + }; + + // Test RUM available case + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); + mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + + await runOpportunityStatusProcessor(testMessage, testContext); + expect(createFromStub.calledWith(testContext)).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; + expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; + expect(testContext.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: true')).to.be.true; + + createFromStub.restore(); + }); + + it('should handle non-CWV opportunities without RUM indicators', async () => { + // Test non-CWV opportunities (no RUM indicator added) + const mockOpportunities = [ + { + getType: () => 'meta-tags', + getSuggestions: sinon.stub().resolves(['suggestion1']), + }, + { + getType: () => 'broken-links', + getSuggestions: sinon.stub().resolves([]), + }, + ]; + + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'https://example.com', + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['meta-tags', 'broken-links'], + slackContext: null, + }, + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves(mockOpportunities), + }), + }, + }, + }; + + // Mock RUM client to return success + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); + mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + + await runOpportunityStatusProcessor(testMessage, testContext); + + // Verify RUM was checked but no RUM indicator was added to non-CWV opportunities + expect(createFromStub.calledWith(testContext)).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; + expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; + expect(testContext.log.info.calledWith('Found 2 opportunities for site test-site-id. RUM available: true')).to.be.true; + + createFromStub.restore(); + }); }); }); From 0a27cb35404fb4657aa5c37b5e88f46901fbcae6 Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Fri, 22 Aug 2025 12:03:08 -0500 Subject: [PATCH 2/7] seperate RUM status --- .../opportunity-status-processor/handler.js | 25 ++++--------------- .../opportunity-status-processor.test.js | 10 ++++---- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 405f2d2..5baf956 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -104,46 +104,31 @@ export async function runOpportunityStatusProcessor(message, context) { rumAvailable = await isRUMAvailable(domain, context); } catch (error) { log.warn(`Could not parse siteUrl for RUM check: ${siteUrl}`, error); - rumAvailable = false; } } const opportunities = await site.getOpportunities(); log.info(`Found ${opportunities.length} opportunities for site ${siteId}. RUM available: ${rumAvailable}`); - // Track processed opportunity types to avoid duplicates - const processedTypes = new Set(); const statusMessages = []; + const rumStatus = rumAvailable ? ':white_check_mark:' : ':cross-x:'; + statusMessages.push(`RUM ${rumStatus}`); for (const opportunity of opportunities) { - const opportunityType = opportunity.getType(); - if (processedTypes.has(opportunityType)) { - // eslint-disable-next-line no-continue - continue; - } - processedTypes.add(opportunityType); - // eslint-disable-next-line no-await-in-loop const suggestions = await opportunity.getSuggestions(); - // Get the opportunity title + const opportunityType = opportunity.getType(); const opportunityTitle = getOpportunityTitle(opportunityType); const hasSuggestions = suggestions && suggestions.length > 0; const status = hasSuggestions ? ':white_check_mark:' : ':cross-x:'; - // Add RUM availability indicator for CWV opportunities - let statusMessage = `${opportunityTitle} ${status}`; - if (opportunityType === 'cwv') { - const rumIndicator = rumAvailable ? ':chart_with_upwards_trend:' : ':no_entry_sign:'; - statusMessage += ` (RUM: ${rumIndicator})`; - } - + const statusMessage = `${opportunityTitle} ${status}`; statusMessages.push(statusMessage); } - // Send status message to Slack if context is available if (slackContext && statusMessages.length > 0) { - const slackMessage = `:clipboard: **Opportunity Status for ${siteUrl || siteId}**\n\n${statusMessages.join('\n')}`; + const slackMessage = `:clipboard: **Opportunity Status for ${siteUrl}**\n\n${statusMessages.join('\n')}`; await say(env, log, slackContext, slackMessage); } diff --git a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js index cc06385..0f9bc07 100644 --- a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js +++ b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js @@ -193,7 +193,7 @@ describe('Opportunity Status Processor', () => { expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; }); - it('should deduplicate opportunity types and skip duplicates', async () => { + it('should process all opportunities including duplicates', async () => { // Mock opportunities with duplicate types const mockOpportunities = [ { @@ -217,14 +217,14 @@ describe('Opportunity Status Processor', () => { await runOpportunityStatusProcessor(message, context); - // Should only process unique types (2 unique types, not 4 total opportunities) + // Should process all opportunities (4 total opportunities) expect(context.log.info.calledWith('Found 4 opportunities for site test-site-id. RUM available: false')).to.be.true; - // Verify that getSuggestions was only called for unique types (2 times, not 4) + // Verify that getSuggestions was called for all opportunities expect(mockOpportunities[0].getSuggestions.called).to.be.true; - expect(mockOpportunities[1].getSuggestions.called).to.be.false; // Should be skipped + expect(mockOpportunities[1].getSuggestions.called).to.be.true; expect(mockOpportunities[2].getSuggestions.called).to.be.true; - expect(mockOpportunities[3].getSuggestions.called).to.be.false; // Should be skipped + expect(mockOpportunities[3].getSuggestions.called).to.be.true; }); it('should handle RUM availability scenarios', async () => { From 62d7207feac6c0f6a6fd1bf47b5079d706bee845 Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Fri, 22 Aug 2025 20:44:49 -0500 Subject: [PATCH 3/7] use canonical url to check RUM availability --- .../opportunity-status-processor/handler.js | 6 +- .../opportunity-status-processor.test.js | 210 +++++++++--------- 2 files changed, 112 insertions(+), 104 deletions(-) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 5baf956..6ab98e2 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -12,6 +12,7 @@ import { ok } from '@adobe/spacecat-shared-http-utils'; import RUMAPIClient from '@adobe/spacecat-shared-rum-api-client'; +import { resolveCanonicalUrl } from '@adobe/spacecat-shared-utils'; import { say } from '../../utils/slack-utils.js'; const TASK_TYPE = 'opportunity-status-processor'; @@ -100,10 +101,11 @@ export async function runOpportunityStatusProcessor(message, context) { let rumAvailable = false; if (siteUrl) { try { - const domain = new URL(siteUrl).hostname; + const resolvedUrl = await resolveCanonicalUrl(siteUrl); + const domain = new URL(resolvedUrl).hostname; rumAvailable = await isRUMAvailable(domain, context); } catch (error) { - log.warn(`Could not parse siteUrl for RUM check: ${siteUrl}`, error); + log.warn(`Could not resolve canonical URL or parse siteUrl for RUM check: ${siteUrl}`, error); } } diff --git a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js index 0f9bc07..c0424e6 100644 --- a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js +++ b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js @@ -227,7 +227,7 @@ describe('Opportunity Status Processor', () => { expect(mockOpportunities[3].getSuggestions.called).to.be.true; }); - it('should handle RUM availability scenarios', async () => { + it('should handle RUM availability check when no siteUrl is provided', async () => { // Test RUM availability check when no siteUrl is provided const mockOpportunities = [ { @@ -250,8 +250,11 @@ describe('Opportunity Status Processor', () => { }, ]; mockSite.getOpportunities.resolves(mockOpportunities); + + // For this test, we'll just verify that the error is handled gracefully + // The actual resolveCanonicalUrl function will throw an error for invalid URLs await runOpportunityStatusProcessor(message, context); - expect(context.log.warn.calledWith('Could not parse siteUrl for RUM check: invalid-url', sinon.match.any)).to.be.true; + expect(context.log.warn.calledWith('Could not resolve canonical URL or parse siteUrl for RUM check: invalid-url', sinon.match.any)).to.be.true; expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; }); }); @@ -261,6 +264,8 @@ describe('Opportunity Status Processor', () => { let mockRUMClient; beforeEach(async () => { + // Setup mock context and RUM client for testing + mockContext = { log: { info: sinon.stub(), @@ -281,15 +286,15 @@ describe('Opportunity Status Processor', () => { sinon.restore(); }); - it('should handle RUM availability scenarios', async () => { - // Test RUM available (success case) - mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + it('should log RUM unavailability when retrieveDomainkey fails', async () => { + // Test the specific error path in isRUMAvailable function (lines 38-40) + mockRUMClient.retrieveDomainkey.rejects(new Error('Domain key not found')); const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); const testMessage = { siteId: 'test-site-id', - siteUrl: 'https://example.com', + siteUrl: 'http://localhost:3000', organizationId: 'test-org-id', taskContext: { auditTypes: ['cwv'], @@ -309,58 +314,62 @@ describe('Opportunity Status Processor', () => { }; await runOpportunityStatusProcessor(testMessage, testContext); - expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; - expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; - expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: true')).to.be.true; + + // Since resolveCanonicalUrl may fail for localhost, verify error handling + expect(testContext.log.warn.calledWith('Could not resolve canonical URL or parse siteUrl for RUM check: http://localhost:3000', sinon.match.any)).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; createFromStub.restore(); }); - it('should handle RUM unavailability scenarios', async () => { - // Test RUM unavailable (failure case) - mockRUMClient.retrieveDomainkey.rejects(new Error('Domain not found')); - const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); - const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); - - const testMessage = { - siteId: 'test-site-id', - siteUrl: 'https://unavailable.com', - organizationId: 'test-org-id', - taskContext: { - auditTypes: ['cwv'], - slackContext: null, - }, - }; + it('should handle localhost URL resolution failures', async () => { + // Test various localhost URL scenarios that fail resolveCanonicalUrl + const testCases = [ + { url: 'http://localhost:3001', description: 'localhost with port' }, + { url: 'http://test.localhost', description: 'localhost subdomain' }, + { url: 'http://localhost:3002', description: 'localhost with different port' }, + { url: 'http://localhost:3003', description: 'localhost with another port' }, + ]; - const testContext = { - ...mockContext, - dataAccess: { - Site: { - findById: sinon.stub().resolves({ - getOpportunities: sinon.stub().resolves([]), - }), + await Promise.all(testCases.map(async (testCase) => { + const testMessage = { + siteId: 'test-site-id', + siteUrl: testCase.url, + organizationId: 'test-org-id', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, }, - }, - }; + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves([]), + }), + }, + }, + }; - await runOpportunityStatusProcessor(testMessage, testContext); - expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('unavailable.com')).to.be.true; - expect(testContext.log.info.calledWith('RUM is not available for domain: unavailable.com. Reason: Domain not found')).to.be.true; - expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + await runOpportunityStatusProcessor(testMessage, testContext); - createFromStub.restore(); + // Verify error handling for localhost URLs + expect(testContext.log.warn.calledWith(`Could not resolve canonical URL or parse siteUrl for RUM check: ${testCase.url}`, sinon.match.any)).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + })); }); - it('should handle RUM client creation errors', async () => { - // Test RUM client creation failure + it('should handle RUM unavailability when retrieveDomainkey fails', async () => { + // Test RUM unavailable (failure case) - use a working domain to cover lines 38-40 + mockRUMClient.retrieveDomainkey.rejects(new Error('Domain key not found')); const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); - const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').throws(new Error('RUM client creation failed')); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); const testMessage = { siteId: 'test-site-id', - siteUrl: 'https://error.com', + siteUrl: 'https://httpbin.org', // Use a working domain to cover the RUM function organizationId: 'test-org-id', taskContext: { auditTypes: ['cwv'], @@ -380,25 +389,25 @@ describe('Opportunity Status Processor', () => { }; await runOpportunityStatusProcessor(testMessage, testContext); + + // Verify RUM was checked and failed - this should cover lines 38-40 expect(createFromStub.calledWith(testContext)).to.be.true; - expect(testContext.log.info.calledWith('RUM is not available for domain: error.com. Reason: RUM client creation failed')).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('httpbin.org')).to.be.true; + expect(testContext.log.info.calledWith('RUM is not available for domain: httpbin.org. Reason: Domain key not found')).to.be.true; expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; createFromStub.restore(); }); - it('should handle CWV opportunities with RUM indicators', async () => { - // Test CWV opportunities with RUM available - const mockOpportunities = [ - { - getType: () => 'cwv', - getSuggestions: sinon.stub().resolves(['suggestion1']), - }, - ]; + it('should handle RUM success scenarios', async () => { + // Test RUM available (success case) - use a working domain for coverage + mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); + const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); const testMessage = { siteId: 'test-site-id', - siteUrl: 'https://example.com', + siteUrl: 'https://httpbin.org', // Use a fast, reliable test service for coverage organizationId: 'test-org-id', taskContext: { auditTypes: ['cwv'], @@ -411,74 +420,71 @@ describe('Opportunity Status Processor', () => { dataAccess: { Site: { findById: sinon.stub().resolves({ - getOpportunities: sinon.stub().resolves(mockOpportunities), + getOpportunities: sinon.stub().resolves([]), }), }, }, }; - // Test RUM available case - const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); - const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); - mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); - await runOpportunityStatusProcessor(testMessage, testContext); + + // Verify RUM was checked successfully - this should cover lines 26-37 expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; - expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; - expect(testContext.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: true')).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('httpbin.org')).to.be.true; + expect(testContext.log.info.calledWith('RUM is available for domain: httpbin.org')).to.be.true; + expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: true')).to.be.true; createFromStub.restore(); }); - it('should handle non-CWV opportunities without RUM indicators', async () => { - // Test non-CWV opportunities (no RUM indicator added) - const mockOpportunities = [ + it('should handle opportunities with different types and localhost URLs', async () => { + // Test opportunities with different types when using localhost URLs + const testCases = [ { - getType: () => 'meta-tags', - getSuggestions: sinon.stub().resolves(['suggestion1']), + opportunities: [{ getType: () => 'cwv', getSuggestions: sinon.stub().resolves(['suggestion1']) }], + auditTypes: ['cwv'], + expectedCount: 1, + description: 'CWV opportunities', }, { - getType: () => 'broken-links', - getSuggestions: sinon.stub().resolves([]), - }, - ]; - - const testMessage = { - siteId: 'test-site-id', - siteUrl: 'https://example.com', - organizationId: 'test-org-id', - taskContext: { + opportunities: [ + { getType: () => 'meta-tags', getSuggestions: sinon.stub().resolves(['suggestion1']) }, + { getType: () => 'broken-links', getSuggestions: sinon.stub().resolves([]) }, + ], auditTypes: ['meta-tags', 'broken-links'], - slackContext: null, + expectedCount: 2, + description: 'Non-CWV opportunities', }, - }; + ]; - const testContext = { - ...mockContext, - dataAccess: { - Site: { - findById: sinon.stub().resolves({ - getOpportunities: sinon.stub().resolves(mockOpportunities), - }), + await Promise.all(testCases.map(async (testCase) => { + const testMessage = { + siteId: 'test-site-id', + siteUrl: 'http://localhost:3001', + organizationId: 'test-org-id', + taskContext: { + auditTypes: testCase.auditTypes, + slackContext: null, }, - }, - }; - - // Mock RUM client to return success - const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); - const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); - mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); + }; + + const testContext = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves(testCase.opportunities), + }), + }, + }, + }; - await runOpportunityStatusProcessor(testMessage, testContext); + await runOpportunityStatusProcessor(testMessage, testContext); - // Verify RUM was checked but no RUM indicator was added to non-CWV opportunities - expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; - expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; - expect(testContext.log.info.calledWith('Found 2 opportunities for site test-site-id. RUM available: true')).to.be.true; - - createFromStub.restore(); + // Verify error handling for localhost URLs + expect(testContext.log.warn.calledWith('Could not resolve canonical URL or parse siteUrl for RUM check: http://localhost:3001', sinon.match.any)).to.be.true; + expect(testContext.log.info.calledWith(`Found ${testCase.expectedCount} opportunities for site test-site-id. RUM available: false`)).to.be.true; + })); }); }); }); From 430f8054d4d0a076d135c2230e5626e3a5beedce Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Fri, 22 Aug 2025 21:09:05 -0500 Subject: [PATCH 4/7] add log --- src/tasks/opportunity-status-processor/handler.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 6ab98e2..80859b5 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -102,6 +102,7 @@ export async function runOpportunityStatusProcessor(message, context) { if (siteUrl) { try { const resolvedUrl = await resolveCanonicalUrl(siteUrl); + log.info(`Resolved URL: ${resolvedUrl}`); const domain = new URL(resolvedUrl).hostname; rumAvailable = await isRUMAvailable(domain, context); } catch (error) { From 65c3311aae28c6228095f3bc93f8e5fd32a961bd Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Fri, 22 Aug 2025 21:42:25 -0500 Subject: [PATCH 5/7] use one opportunity tik for one type --- .../opportunity-status-processor/handler.js | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 80859b5..f923203 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -117,6 +117,9 @@ export async function runOpportunityStatusProcessor(message, context) { const rumStatus = rumAvailable ? ':white_check_mark:' : ':cross-x:'; statusMessages.push(`RUM ${rumStatus}`); + // Group opportunities by type to avoid duplicates + const opportunityTypeMap = new Map(); + for (const opportunity of opportunities) { // eslint-disable-next-line no-await-in-loop const suggestions = await opportunity.getSuggestions(); @@ -126,7 +129,22 @@ export async function runOpportunityStatusProcessor(message, context) { const hasSuggestions = suggestions && suggestions.length > 0; const status = hasSuggestions ? ':white_check_mark:' : ':cross-x:'; - const statusMessage = `${opportunityTitle} ${status}`; + // If we already have this opportunity type, check if we need to update the status + if (opportunityTypeMap.has(opportunityType)) { + const existingStatus = opportunityTypeMap.get(opportunityType); + // If existing status is already a checkmark, keep it; + // otherwise update if this one has suggestions + if (existingStatus.includes(':cross-x:') && hasSuggestions) { + opportunityTypeMap.set(opportunityType, `${opportunityTitle} ${status}`); + } + } else { + // First time seeing this opportunity type + opportunityTypeMap.set(opportunityType, `${opportunityTitle} ${status}`); + } + } + + // Add all unique opportunity types to status messages + for (const statusMessage of opportunityTypeMap.values()) { statusMessages.push(statusMessage); } From 794b8144fecb40a045bf23d8637b5f31ac79be09 Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Mon, 25 Aug 2025 11:39:06 -0500 Subject: [PATCH 6/7] simplify logic --- .../opportunity-status-processor/handler.js | 31 ++---- .../opportunity-status-processor.test.js | 96 +++++++++---------- 2 files changed, 57 insertions(+), 70 deletions(-) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index f923203..971a588 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -117,35 +117,24 @@ export async function runOpportunityStatusProcessor(message, context) { const rumStatus = rumAvailable ? ':white_check_mark:' : ':cross-x:'; statusMessages.push(`RUM ${rumStatus}`); - // Group opportunities by type to avoid duplicates - const opportunityTypeMap = new Map(); + // Process opportunities by type to avoid duplicates + const processedTypes = new Set(); for (const opportunity of opportunities) { + const opportunityType = opportunity.getType(); + if (processedTypes.has(opportunityType)) { + // eslint-disable-next-line no-continue + continue; + } + processedTypes.add(opportunityType); + // eslint-disable-next-line no-await-in-loop const suggestions = await opportunity.getSuggestions(); - const opportunityType = opportunity.getType(); const opportunityTitle = getOpportunityTitle(opportunityType); const hasSuggestions = suggestions && suggestions.length > 0; const status = hasSuggestions ? ':white_check_mark:' : ':cross-x:'; - - // If we already have this opportunity type, check if we need to update the status - if (opportunityTypeMap.has(opportunityType)) { - const existingStatus = opportunityTypeMap.get(opportunityType); - // If existing status is already a checkmark, keep it; - // otherwise update if this one has suggestions - if (existingStatus.includes(':cross-x:') && hasSuggestions) { - opportunityTypeMap.set(opportunityType, `${opportunityTitle} ${status}`); - } - } else { - // First time seeing this opportunity type - opportunityTypeMap.set(opportunityType, `${opportunityTitle} ${status}`); - } - } - - // Add all unique opportunity types to status messages - for (const statusMessage of opportunityTypeMap.values()) { - statusMessages.push(statusMessage); + statusMessages.push(`${opportunityTitle} ${status}`); } if (slackContext && statusMessages.length > 0) { diff --git a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js index c0424e6..336fb1d 100644 --- a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js +++ b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js @@ -193,7 +193,7 @@ describe('Opportunity Status Processor', () => { expect(context.log.info.calledWith('Found 1 opportunities for site test-site-id. RUM available: false')).to.be.true; }); - it('should process all opportunities including duplicates', async () => { + it('should process opportunities by type avoiding duplicates', async () => { // Mock opportunities with duplicate types const mockOpportunities = [ { @@ -201,7 +201,7 @@ describe('Opportunity Status Processor', () => { getSuggestions: sinon.stub().resolves(['suggestion1']), }, { - getType: () => 'cwv', // Duplicate type + getType: () => 'cwv', // Duplicate type - should be skipped getSuggestions: sinon.stub().resolves(['suggestion2']), }, { @@ -209,7 +209,7 @@ describe('Opportunity Status Processor', () => { getSuggestions: sinon.stub().resolves([]), }, { - getType: () => 'broken-links', // Another duplicate type + getType: () => 'broken-links', // Another duplicate type - should be skipped getSuggestions: sinon.stub().resolves(['suggestion3']), }, ]; @@ -220,11 +220,15 @@ describe('Opportunity Status Processor', () => { // Should process all opportunities (4 total opportunities) expect(context.log.info.calledWith('Found 4 opportunities for site test-site-id. RUM available: false')).to.be.true; - // Verify that getSuggestions was called for all opportunities + // With the new logic, getSuggestions should only be called for unique opportunity types + // First occurrence of 'cwv' should be processed expect(mockOpportunities[0].getSuggestions.called).to.be.true; - expect(mockOpportunities[1].getSuggestions.called).to.be.true; + // Second occurrence of 'cwv' should be skipped (duplicate) + expect(mockOpportunities[1].getSuggestions.called).to.be.false; + // First occurrence of 'broken-links' should be processed expect(mockOpportunities[2].getSuggestions.called).to.be.true; - expect(mockOpportunities[3].getSuggestions.called).to.be.true; + // Second occurrence of 'broken-links' should be skipped (duplicate) + expect(mockOpportunities[3].getSuggestions.called).to.be.false; }); it('should handle RUM availability check when no siteUrl is provided', async () => { @@ -292,7 +296,8 @@ describe('Opportunity Status Processor', () => { const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); - const testMessage = { + // First test: localhost URL that fails URL resolution + const testMessage1 = { siteId: 'test-site-id', siteUrl: 'http://localhost:3000', organizationId: 'test-org-id', @@ -302,7 +307,7 @@ describe('Opportunity Status Processor', () => { }, }; - const testContext = { + const testContext1 = { ...mockContext, dataAccess: { Site: { @@ -313,11 +318,42 @@ describe('Opportunity Status Processor', () => { }, }; - await runOpportunityStatusProcessor(testMessage, testContext); + await runOpportunityStatusProcessor(testMessage1, testContext1); // Since resolveCanonicalUrl may fail for localhost, verify error handling - expect(testContext.log.warn.calledWith('Could not resolve canonical URL or parse siteUrl for RUM check: http://localhost:3000', sinon.match.any)).to.be.true; - expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + expect(testContext1.log.warn.calledWith('Could not resolve canonical URL or parse siteUrl for RUM check: http://localhost:3000', sinon.match.any)).to.be.true; + expect(testContext1.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; + + // Second test: valid URL that succeeds URL resolution but fails RUM check + // This covers lines 38-40 in isRUMAvailable function + const testMessage2 = { + siteId: 'test-site-id-2', + siteUrl: 'https://example.com', + organizationId: 'test-org-id-2', + taskContext: { + auditTypes: ['cwv'], + slackContext: null, + }, + }; + + const testContext2 = { + ...mockContext, + dataAccess: { + Site: { + findById: sinon.stub().resolves({ + getOpportunities: sinon.stub().resolves([]), + }), + }, + }, + }; + + await runOpportunityStatusProcessor(testMessage2, testContext2); + + // Verify RUM was checked and failed - this should cover lines 38-40 + expect(createFromStub.calledWith(testContext2)).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; + expect(testContext2.log.info.calledWith('RUM is not available for domain: example.com. Reason: Domain key not found')).to.be.true; + expect(testContext2.log.info.calledWith('Found 0 opportunities for site test-site-id-2. RUM available: false')).to.be.true; createFromStub.restore(); }); @@ -361,44 +397,6 @@ describe('Opportunity Status Processor', () => { })); }); - it('should handle RUM unavailability when retrieveDomainkey fails', async () => { - // Test RUM unavailable (failure case) - use a working domain to cover lines 38-40 - mockRUMClient.retrieveDomainkey.rejects(new Error('Domain key not found')); - const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); - const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); - - const testMessage = { - siteId: 'test-site-id', - siteUrl: 'https://httpbin.org', // Use a working domain to cover the RUM function - organizationId: 'test-org-id', - taskContext: { - auditTypes: ['cwv'], - slackContext: null, - }, - }; - - const testContext = { - ...mockContext, - dataAccess: { - Site: { - findById: sinon.stub().resolves({ - getOpportunities: sinon.stub().resolves([]), - }), - }, - }, - }; - - await runOpportunityStatusProcessor(testMessage, testContext); - - // Verify RUM was checked and failed - this should cover lines 38-40 - expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('httpbin.org')).to.be.true; - expect(testContext.log.info.calledWith('RUM is not available for domain: httpbin.org. Reason: Domain key not found')).to.be.true; - expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: false')).to.be.true; - - createFromStub.restore(); - }); - it('should handle RUM success scenarios', async () => { // Test RUM available (success case) - use a working domain for coverage mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); From 0488903f04faeedb7daecb31ddf8cd99d59142d6 Mon Sep 17 00:00:00 2001 From: Tej Kotthakota Date: Mon, 25 Aug 2025 15:22:12 -0500 Subject: [PATCH 7/7] revert slack message --- src/tasks/opportunity-status-processor/handler.js | 4 +++- .../opportunity-status-processor.test.js | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tasks/opportunity-status-processor/handler.js b/src/tasks/opportunity-status-processor/handler.js index 971a588..c88ed00 100644 --- a/src/tasks/opportunity-status-processor/handler.js +++ b/src/tasks/opportunity-status-processor/handler.js @@ -138,8 +138,10 @@ export async function runOpportunityStatusProcessor(message, context) { } if (slackContext && statusMessages.length > 0) { - const slackMessage = `:clipboard: **Opportunity Status for ${siteUrl}**\n\n${statusMessages.join('\n')}`; + const slackMessage = `:white_check_mark: *Opportunities status for site ${siteUrl}*:`; + const combinedMessage = statusMessages.join('\n'); await say(env, log, slackContext, slackMessage); + await say(env, log, slackContext, combinedMessage); } log.info(`Processed ${opportunities.length} opportunities for site ${siteId}`); diff --git a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js index 336fb1d..a6ca9d3 100644 --- a/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js +++ b/test/tasks/opportunity-status-processor/opportunity-status-processor.test.js @@ -398,14 +398,14 @@ describe('Opportunity Status Processor', () => { }); it('should handle RUM success scenarios', async () => { - // Test RUM available (success case) - use a working domain for coverage + // Test RUM available (success case) - use a simple URL that should resolve quickly mockRUMClient.retrieveDomainkey.resolves('test-domain-key'); const RUMAPIClient = await import('@adobe/spacecat-shared-rum-api-client'); const createFromStub = sinon.stub(RUMAPIClient.default, 'createFrom').returns(mockRUMClient); const testMessage = { siteId: 'test-site-id', - siteUrl: 'https://httpbin.org', // Use a fast, reliable test service for coverage + siteUrl: 'https://example.com', organizationId: 'test-org-id', taskContext: { auditTypes: ['cwv'], @@ -428,8 +428,8 @@ describe('Opportunity Status Processor', () => { // Verify RUM was checked successfully - this should cover lines 26-37 expect(createFromStub.calledWith(testContext)).to.be.true; - expect(mockRUMClient.retrieveDomainkey.calledWith('httpbin.org')).to.be.true; - expect(testContext.log.info.calledWith('RUM is available for domain: httpbin.org')).to.be.true; + expect(mockRUMClient.retrieveDomainkey.calledWith('example.com')).to.be.true; + expect(testContext.log.info.calledWith('RUM is available for domain: example.com')).to.be.true; expect(testContext.log.info.calledWith('Found 0 opportunities for site test-site-id. RUM available: true')).to.be.true; createFromStub.restore();