diff --git a/packages/server/__tests__/arpa_reporter/server/lib/audit-report.spec.js b/packages/server/__tests__/arpa_reporter/server/lib/audit-report.spec.js index 2cc5d8ba4..b60412126 100644 --- a/packages/server/__tests__/arpa_reporter/server/lib/audit-report.spec.js +++ b/packages/server/__tests__/arpa_reporter/server/lib/audit-report.spec.js @@ -157,7 +157,20 @@ describe('audit report generation', () => { 'Project Expenditure Category Group': '2-Negative Economic Impacts', 'Project ID': '4', }]; - const headers = audit_report.createHeadersProjectSummariesV2(projects); + const headers = audit_report.sortHeadersWithDates(projects, + [ + 'Capital Expenditure Amount', + 'Project Description', + 'Project Expenditure Category', + 'Project Expenditure Category Group', + 'Project ID', + ], + [ + 'Total Aggregate Expenditures', + 'Total Aggregate Obligations', + 'Total Expenditures for Awards Greater or Equal to $50k', + 'Total Obligations for Awards Greater or Equal to $50k', + ]); const headersExpected = [ 'Project ID', 'Project Description', diff --git a/packages/server/__tests__/email/email.test.js b/packages/server/__tests__/email/email.test.js index 5d4e5f3d4..70663c86b 100644 --- a/packages/server/__tests__/email/email.test.js +++ b/packages/server/__tests__/email/email.test.js @@ -194,6 +194,7 @@ describe('Email sender', () => { sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendFake })); email.deliverEmail({ + fromName: 'Foo', toAddress: 'foo@bar.com', ccAddress: 'cc@example.com', emailHTML: '

foo

', @@ -203,6 +204,7 @@ describe('Email sender', () => { expect(sendFake.calledOnce).to.equal(true); expect(sendFake.firstCall.args).to.deep.equal([{ + fromName: 'Foo', toAddress: 'foo@bar.com', ccAddress: 'cc@example.com', subject: 'test foo email', diff --git a/packages/server/src/arpa_reporter/lib/audit-report.js b/packages/server/src/arpa_reporter/lib/audit-report.js index 7f9e2fa32..483c496b8 100644 --- a/packages/server/src/arpa_reporter/lib/audit-report.js +++ b/packages/server/src/arpa_reporter/lib/audit-report.js @@ -398,16 +398,16 @@ async function createReportsGroupedBySubAward(periodId, tenantId, dateFormat = R // - the initial value for each column in this row is zero subAwardReportingPeriodIds.forEach((id) => { const endDate = endDatesByReportingPeriodId[id]; - row[`${endDate} Awards > 50000 SubAward Amount`] = 0; - row[`${endDate} Awards > 50000 SubAward Expenditure`] = 0; + row[`${endDate} Awards > 50000 SubAward Amount (Obligation)`] = 0; + row[`${endDate} Awards > 50000 SubAward Current Expenditure Amount`] = 0; }); // Sum the total value of each initialized column from the corresponding subtotal // provided by each subAward record subAwardRecords.forEach((record) => { const endDate = endDatesByReportingPeriodId[record.upload.reporting_period_id]; - row[`${endDate} Awards > 50000 SubAward Amount`] += (record.content.Award_Amount__c || 0); - row[`${endDate} Awards > 50000 SubAward Expenditure`] += (record.content.Expenditure_Amount__c || 0); + row[`${endDate} Awards > 50000 SubAward Amount (Obligation)`] += (record.content.Award_Amount__c || 0); + row[`${endDate} Awards > 50000 SubAward Current Expenditure Amount`] += (record.content.Expenditure_Amount__c || 0); }); subAwardLogger.fields.subAward.totalColumns = Object.keys(row).length; @@ -465,8 +465,8 @@ async function createKpiDataGroupedByProject(periodId, tenantId, logger = log) { * The headers are split into the date and non-date headers. * The non-date headers come first with an ordering, then the date headers. */ -function createHeadersProjectSummariesV2(projectSummaryGroupedByProject) { - const keys = Array.from(new Set(projectSummaryGroupedByProject.map(Object.keys).flat())); +function sortHeadersWithDates(data, expectedOrderWithoutDate, expectedOrderWithDate) { + const keys = Array.from(new Set(data.map(Object.keys).flat())); // split up by date and not date const withDate = keys.filter((x) => REPORTING_DATE_REGEX.exec(x)); const withoutDate = keys.filter((x) => REPORTING_DATE_REGEX.exec(x) == null); @@ -486,23 +486,6 @@ function createHeadersProjectSummariesV2(projectSummaryGroupedByProject) { return x; }, {}); - const expectedOrderWithoutDate = [ - 'Project ID', - 'Project Description', - 'Project Expenditure Category Group', - 'Project Expenditure Category', - 'Capital Expenditure Amount', - ]; - - const expectedOrderWithDate = [ - 'Total Aggregate Obligations', - 'Total Aggregate Expenditures', - 'Total Obligations for Awards Greater or Equal to $50k', - 'Total Expenditures for Awards Greater or Equal to $50k', - 'Total Obligations for Aggregate Awards < $50k', - 'Total Expenditures for Aggregate Awards < $50k', - ]; - // first add the properly ordered non-date headers, // then add the headers sorted by the header group then the date const headers = [ @@ -514,6 +497,7 @@ function createHeadersProjectSummariesV2(projectSummaryGroupedByProject) { .map((date) => `${date.format(REPORTING_DATE_FORMAT)} ${x[0]}`)).flat(), ]; + debugger; return headers; } @@ -579,10 +563,36 @@ async function generate(requestHost, tenantId, periodId) { const sheet1 = jsonToSheet(obligations, 'Obligations & Expenditures'); const sheet2 = jsonToSheet(projectSummaries, 'Project Summaries'); const sheet3 = jsonToSheet(projectSummaryGroupedByProject, 'Project Summaries V2', { - header: createHeadersProjectSummariesV2(projectSummaryGroupedByProject), + header: sortHeadersWithDates( + projectSummaryGroupedByProject, + [ + 'Project ID', + 'Project Description', + 'Project Expenditure Category Group', + 'Project Expenditure Category', + 'Capital Expenditure Amount', + ], + [ + 'Total Aggregate Obligations', + 'Total Aggregate Expenditures', + 'Total Obligations for Awards Greater or Equal to $50k', + 'Total Expenditures for Awards Greater or Equal to $50k', + 'Total Obligations for Aggregate Awards < $50k', + 'Total Expenditures for Aggregate Awards < $50k', + ], + ), }); // FIXME need to sort - const sheet4 = jsonToSheet(projectSummaryGroupedBySubAward, 'SubAward Summaries'); + const sheet4 = jsonToSheet(projectSummaryGroupedBySubAward, 'SubAward Summaries', { + header: sortHeadersWithDates( + projectSummaryGroupedBySubAward, + ['SubAward ID'], + [ + 'Awards > 50000 SubAward Amount (Obligation)', + 'Awards > 50000 SubAward Current Expenditure Amount', + ], + ), + }); const sheet5 = jsonToSheet(KPIDataGroupedByProject, 'KPI'); log.info('finished building sheets from aggregated data'); @@ -704,7 +714,7 @@ module.exports = { generateAndSendEmail, processSQSMessageRequest, sendEmailWithLink, - createHeadersProjectSummariesV2, + sortHeadersWithDates, // export for testing getRecordsByProject, diff --git a/packages/server/src/lib/email.js b/packages/server/src/lib/email.js index 320611d3d..7676f34c8 100644 --- a/packages/server/src/lib/email.js +++ b/packages/server/src/lib/email.js @@ -18,6 +18,7 @@ const ASYNC_REPORT_TYPES = { const HELPDESK_EMAIL = 'grants-helpdesk@usdigitalresponse.org'; async function deliverEmail({ + fromName, toAddress, ccAddress, emailHTML, @@ -25,6 +26,7 @@ async function deliverEmail({ subject, }) { return emailService.getTransport().sendEmail({ + fromName, toAddress, ccAddress, subject, @@ -33,16 +35,38 @@ async function deliverEmail({ }); } +function buildBaseUrlSafe() { + const baseUrl = new URL(process.env.WEBSITE_DOMAIN); + baseUrl.searchParams.set('utm_source', 'usdr-grants'); + baseUrl.searchParams.set('utm_medium', 'email'); + return baseUrl.toString(); +} + +/** + * Adds the base email HTML around the email body HTML. Specifically, adds the USDR logo header, + * footer, title, preheader, etc. + * + * @param {string} emailHTML - Rendered email body HTML + * @param {object} brandDetails - Options to control how the base branding is rendered + * @param {string} brandDetails.tool_name - Name of the product triggering the email, rendered + * underneath the USDR logo + * @param {string} brandDetails.title - Rendered as the HTML (most email programs ignore) + * @param {string} brandDetails.preheader - Preview text for the email (most email programs + * render this, often truncated, after the subject line in your inbox) + * @param {string} brandDetails.notifications_url - URL where the user can manage notification settings + */ function addBaseBranding(emailHTML, brandDetails) { - const { tool_name, title, notifications_url } = brandDetails; + const { + tool_name, title, preheader, notifications_url, + } = brandDetails; const baseBrandedTemplate = fileSystem.readFileSync(path.join(__dirname, '../static/email_templates/base.html')); const brandedHTML = mustache.render(baseBrandedTemplate.toString(), { tool_name, title, webview_available: false, // Preheader and webview are not setup for Grant notification email. - // preheader: 'Test preheader', + preheader, // webview_url: 'http://localhost:8080', - usdr_url: 'http://usdigitalresponse.org', + base_url_safe: buildBaseUrlSafe(), usdr_logo_url: 'https://grants.usdigitalresponse.org/usdr_logo_transparent.png', notifications_url, }, { @@ -298,7 +322,7 @@ async function buildDigestBody({ name, openDate, matchedGrants }) { } async function sendGrantDigest({ - name, matchedGrants, recipients, openDate, + name, matchedGrants, matchedGrantsTotal, recipients, openDate, }) { console.log(`${name} is subscribed for notifications on ${openDate}`); @@ -313,10 +337,14 @@ async function sendGrantDigest({ } const formattedBody = await buildDigestBody({ name, openDate, matchedGrants }); + const preheader = typeof matchedGrantsTotal === 'number' && matchedGrantsTotal > 0 + ? `You have ${Intl.NumberFormat('en-US', { useGrouping: true }).format(matchedGrantsTotal)} new ${matchedGrantsTotal > 1 ? 'grants' : 'grant'} to review!` + : 'You have new grants to review!'; const emailHTML = module.exports.addBaseBranding(formattedBody, { tool_name: 'Federal Grant Finder', title: 'New Grants Digest', + preheader, notifications_url: (process.env.ENABLE_MY_PROFILE === 'true') ? `${process.env.WEBSITE_DOMAIN}/my-profile` : `${process.env.WEBSITE_DOMAIN}/grants?manageSettings=true`, }); @@ -327,10 +355,11 @@ async function sendGrantDigest({ recipients.forEach( (recipient) => inputs.push( { + fromName: 'USDR Federal Grant Finder', toAddress: recipient.trim(), emailHTML, emailPlain, - subject: `New Grants published for ${name}`, + subject: `New Grants Published for ${name}`, }, ), ); @@ -357,6 +386,7 @@ async function getAndSendGrantForSavedSearch({ return sendGrantDigest({ name: userSavedSearch.name, matchedGrants: response.data, + matchedGrantsTotal: response.pagination.total, recipients: [userSavedSearch.email], openDate, }); @@ -399,6 +429,7 @@ async function buildAndSendGrantDigest() { agencies.forEach((agency) => inputs.push({ name: agency.name, matchedGrants: agency.matched_grants, + matchedGrantsTotal: agency.matched_grants.length, recipients: agency.recipients, openDate, })); diff --git a/packages/server/src/lib/email/email-nodemailer.js b/packages/server/src/lib/email/email-nodemailer.js index a4bf7b0a8..f26382024 100644 --- a/packages/server/src/lib/email/email-nodemailer.js +++ b/packages/server/src/lib/email/email-nodemailer.js @@ -46,7 +46,10 @@ async function sendEmail(message) { const transport = createTransport(); const params = { - from: process.env.NODEMAILER_EMAIL, // sender address + from: { + name: message.fromName, // If not provided, undefined value is ignored just fine by nodemailer + address: process.env.NODEMAILER_EMAIL, + }, to: message.toAddress, // list of receivers e.g. 'a@aa.com, b@bb.com' subject: message.subject, // text: 'Hello world?', // plain text body diff --git a/packages/server/src/routes/agencies.js b/packages/server/src/routes/agencies.js index 6af176d99..9268f3842 100755 --- a/packages/server/src/routes/agencies.js +++ b/packages/server/src/routes/agencies.js @@ -41,6 +41,7 @@ router.get('/sendDigestEmail', requireUSDRSuperAdminUser, async (req, res) => { await email.sendGrantDigest({ name: agency[0].name, matchedGrants: agency[0].matched_grants, + matchedGrantsTotal: agency[0].matched_grants?.length, recipients: agency[0].recipients, }); } catch (e) { diff --git a/packages/server/src/static/email_templates/base.html b/packages/server/src/static/email_templates/base.html index 25266e183..04a29185a 100644 --- a/packages/server/src/static/email_templates/base.html +++ b/packages/server/src/static/email_templates/base.html @@ -312,6 +312,15 @@ <body style="width:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-family:'open sans', 'helvetica neue', helvetica, arial, sans-serif;padding:0;Margin:0"> + {{# preheader }} + <div style="display: none; max-height: 0px; overflow: hidden;"> + {{ preheader }} + </div> + <!-- Insert ͏‌  after hidden preview text to add space and avoid pulling in other email content --> + <div style="display: none; max-height: 0px; overflow: hidden;"> + ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ ͏ ‌     ­ + </div> + {{/ preheader }} <div class="es-wrapper-color" style="background-color:#F6F6F6"> <!--[if gte mso 9]> <v:background xmlns:v="urn:schemas-microsoft-com:vml" fill="t"> @@ -391,38 +400,27 @@ <td style="padding:0;Margin:0;background-size:cover;background-color:transparent" bgcolor="#DDEFFC" align="center"> <table class="es-header-body" - style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;margin-top:50px;background-color:#ddeffc;" + style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;margin-top:50px;background-color:#ddeffc;width:640px;" cellspacing="0" cellpadding="0" align="center"> <tr style="border-collapse:collapse"> - <td align="left" - style="Margin:0;padding-top:32px;padding-left:20px;padding-right:20px;padding-bottom:32px"> + <td style="Margin:0;padding-top:32px;padding-left:20px;padding-right:20px;padding-bottom:32px" align="center"> <table cellspacing="0" cellpadding="0" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px"> <tr style="border-collapse:collapse"> - <td valign="top" align="center" - style="padding:0;Margin:0;width:600px"> - <table width="100%" cellspacing="0" cellpadding="0" - role="presentation" - style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px"> - <tr style="border-collapse:collapse"> - <td align="center" - style="padding:0;Margin:0;font-size:0px"> - <a href="{{usdr_url}}" target="_blank" - style="-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;text-decoration:none;color:#B7BDC9;font-size:20px"><img - src="{{usdr_logo_url}}" - style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic" - alt="Logo" title="Logo" width="167"></a> - </td> - </tr> - <tr style="border-collapse:collapse"> - <td align="center" style="padding:0;Margin:0"> - <p - style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-family:arial, 'helvetica neue', helvetica, sans-serif;line-height:21px;color:#000000;font-size:14px"> - <strong>{{tool_name}}</strong> - </p> - </td> - </tr> - </table> + <td align="left" style="padding:0;Margin:0"> + <a href="{{& base_url_safe }}" target="_blank" style="-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;text-decoration:none;color:#B7BDC9;font-size:20px"> + <img + src="{{usdr_logo_url}}" + style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic" + alt="Logo" title="Logo" width="167"> + </a> + </td> + </tr> + <tr style="border-collapse:collapse"> + <td align="left" style="padding:0;Margin:0"> + <p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-family:arial, 'helvetica neue', helvetica, sans-serif;line-height:21px;color:#000000;font-size:14px"> + <strong>{{tool_name}}</strong> + </p> </td> </tr> </table> diff --git a/yarn.lock b/yarn.lock index 057395063..69fdffb4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -268,9 +268,9 @@ tslib "^2.6.2" "@aws-sdk/client-s3@^3.312.0": - version "3.536.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.536.0.tgz#15cf90a15e68229652227fbacfc90a8c2dc05f42" - integrity sha512-UM5txJxq8qKzLDVuW9c904bpb7+u1jOeyJITLz79WpyHSOP6ERHoTx/ltEuGJ4zQVazfkgthqR0lIn09sXEEuw== + version "3.537.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.537.0.tgz#887b2c743da49378104054b66aa135fae805263c" + integrity sha512-EMPN2toHz1QtSiDeLKS1zrazh+8J0g1Y5t5lCq25iTXqCSV9vB2jCKwG5+OB6L5tAKkwyl1uZofeWLmdFkztEg== dependencies: "@aws-crypto/sha1-browser" "3.0.0" "@aws-crypto/sha256-browser" "3.0.0" @@ -287,7 +287,7 @@ "@aws-sdk/middleware-recursion-detection" "3.535.0" "@aws-sdk/middleware-sdk-s3" "3.535.0" "@aws-sdk/middleware-signing" "3.535.0" - "@aws-sdk/middleware-ssec" "3.535.0" + "@aws-sdk/middleware-ssec" "3.537.0" "@aws-sdk/middleware-user-agent" "3.535.0" "@aws-sdk/region-config-resolver" "3.535.0" "@aws-sdk/signature-v4-multi-region" "3.535.0" @@ -814,10 +814,10 @@ "@smithy/util-middleware" "^2.2.0" tslib "^2.6.2" -"@aws-sdk/middleware-ssec@3.535.0": - version "3.535.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.535.0.tgz#d4f537d64651f330eada73a7890ff9975760ad0a" - integrity sha512-QAQ++9my7VZzusUPOFcUMdhTnjpGRyy/OvPC+jg9usdfcaSZeQbfzbdaVBalcm2Wt+1qxh3LZSTS+LxKikm02Q== +"@aws-sdk/middleware-ssec@3.537.0": + version "3.537.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.537.0.tgz#c64e4234e38f285e9e2bdf06fdbbb57f6bc848b2" + integrity sha512-2QWMrbwd5eBy5KCYn9a15JEWBgrK2qFEKQN2lqb/6z0bhtevIOxIRfC99tzvRuPt6nixFQ+ynKuBjcfT4ZFrdQ== dependencies: "@aws-sdk/types" "3.535.0" "@smithy/types" "^2.12.0" @@ -865,9 +865,9 @@ tslib "^2.6.2" "@aws-sdk/s3-request-presigner@^3.312.0": - version "3.536.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.536.0.tgz#ca1af127c44d0b962bc43626e0b3956c837bc24f" - integrity sha512-bMz7nxYfSjCkw72Hah40o0c9scwU2LQWoT3CkTcWs9OCrG4MCzMTBJNlzRUpxOpfGTZqVzrCaUGINIjh3jP/tQ== + version "3.537.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.537.0.tgz#4e57a4666adc6424c51165af2b1e299182467a83" + integrity sha512-jG3u9PTl9LpMFr+AY4jx4HvN3+qCFN5vy45U4E8zPagsQ4MbEseUcYpyyC9SHo+3DIgAJQLNV8Zv3LrtdiB5vQ== dependencies: "@aws-sdk/signature-v4-multi-region" "3.535.0" "@aws-sdk/types" "3.535.0" @@ -986,13 +986,13 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.3": version "7.19.3" @@ -1005,19 +1005,19 @@ integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@^7.1.6", "@babel/core@^7.10.3", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.18.13", "@babel/core@^7.7.5": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" - integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.1.tgz#b802f931b6498dcb8fed5a4710881a45abbc2784" + integrity sha512-F82udohVyIgGAY2VVj/g34TpFUG606rumIHjTfVbssPg2zTR7PuuEpZcX8JA6sgBfIYmJrFtWgPvHQuJamVqZQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.0" - "@babel/parser" "^7.24.0" + "@babel/helpers" "^7.24.1" + "@babel/parser" "^7.24.1" "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.0" + "@babel/traverse" "^7.24.1" "@babel/types" "^7.24.0" convert-source-map "^2.0.0" debug "^4.1.0" @@ -1025,14 +1025,14 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" + integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" + "@babel/types" "^7.24.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.18.6": @@ -1276,13 +1276,13 @@ "@babel/traverse" "^7.19.0" "@babel/types" "^7.19.0" -"@babel/helpers@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b" - integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA== +"@babel/helpers@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94" + integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg== dependencies: "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.0" + "@babel/traverse" "^7.24.1" "@babel/types" "^7.24.0" "@babel/highlight@^7.10.4": @@ -1294,19 +1294,20 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== dependencies: "@babel/helper-validator-identifier" "^7.22.20" chalk "^2.4.2" js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/parser@^7.1.6", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.18.4", "@babel/parser@^7.24.0", "@babel/parser@^7.7.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" - integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== +"@babel/parser@^7.1.6", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.18.4", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.7.0": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" + integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -2024,23 +2025,23 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.24.0", "@babel/traverse@^7.7.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" - integrity sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.24.1", "@babel/traverse@^7.7.0": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" + integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.0" + "@babel/parser" "^7.24.1" "@babel/types" "^7.24.0" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.12", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.12.12", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== @@ -2671,7 +2672,7 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.0": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== @@ -2680,7 +2681,16 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== @@ -2695,6 +2705,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + "@jridgewell/source-map@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" @@ -2711,7 +2726,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== @@ -2729,14 +2744,6 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.17": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - "@jridgewell/trace-mapping@^0.3.20": version "0.3.22" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" @@ -2745,6 +2752,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"