diff --git a/apps/server/src/v1/statusReports/post.ts b/apps/server/src/v1/statusReports/post.ts index 32ad40330..5469b6a28 100644 --- a/apps/server/src/v1/statusReports/post.ts +++ b/apps/server/src/v1/statusReports/post.ts @@ -11,7 +11,7 @@ import { } from "@openstatus/db/src/schema"; import { getLimit } from "@openstatus/db/src/schema/plan/utils"; -import { sendEmailHtml } from "@openstatus/emails"; +import { sendBatchEmailHtml } from "@openstatus/emails/emails/send"; import { HTTPException } from "hono/http-exception"; import { openApiErrorResponses } from "../../libs/errors/openapi-error-responses"; import { isoDate } from "../utils"; @@ -149,16 +149,16 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { .where(eq(page.id, _newStatusReport.pageId)) .get(); if (pageInfo) { - const subscribersEmails = subscribers.map( - (subscriber) => subscriber.email, - ); - await sendEmailHtml({ - to: subscribersEmails, - subject: `New status update for ${pageInfo.title}`, - html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${statusReportUpdate.status}

${statusReportUpdate.message}

Powered by OpenStatus

- `, - from: "Notification OpenStatus ", + const emails = subscribers.map((subscriber) => { + return { + to: subscriber.email, + subject: `New status update for ${pageInfo.title}`, + html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${statusReportUpdate.status}

${statusReportUpdate.message}

Powered by OpenStatus

+ `, + from: "Notification OpenStatus ", + }; }); + await sendBatchEmailHtml(emails); } } diff --git a/apps/server/src/v1/statusReports/update/post.ts b/apps/server/src/v1/statusReports/update/post.ts index 23d2bfd91..7528e7c7b 100644 --- a/apps/server/src/v1/statusReports/update/post.ts +++ b/apps/server/src/v1/statusReports/update/post.ts @@ -6,7 +6,8 @@ import { statusReport, statusReportUpdate, } from "@openstatus/db/src/schema"; -import { sendEmailHtml } from "@openstatus/emails"; +import { getLimit } from "@openstatus/db/src/schema/plan/utils"; +import { sendBatchEmailHtml } from "@openstatus/emails/emails/send"; import { HTTPException } from "hono/http-exception"; import { openApiErrorResponses } from "../../../libs/errors/openapi-error-responses"; import { StatusReportUpdateSchema } from "../../statusReportUpdates/schema"; @@ -48,7 +49,7 @@ export function registerStatusReportUpdateRoutes(api: typeof statusReportsApi) { const input = c.req.valid("json"); const { id } = c.req.valid("param"); const workspaceId = c.get("workspaceId"); - const workspacePlan = c.get("workspacePlan"); + const limits = c.get("limits"); const _statusReport = await db .update(statusReport) @@ -76,7 +77,7 @@ export function registerStatusReportUpdateRoutes(api: typeof statusReportsApi) { .returning() .get(); - if (workspacePlan.limits.notifications && _statusReport.pageId) { + if (getLimit(limits, "notifications") && _statusReport.pageId) { const subscribers = await db .select() .from(pageSubscriber) @@ -93,16 +94,16 @@ export function registerStatusReportUpdateRoutes(api: typeof statusReportsApi) { .where(eq(page.id, _statusReport.pageId)) .get(); if (pageInfo) { - const subscribersEmails = subscribers.map( - (subscriber) => subscriber.email, - ); - await sendEmailHtml({ - to: subscribersEmails, - subject: `New status update for ${pageInfo.title}`, - html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${statusReportUpdate.status}

${statusReportUpdate.message}

Powered by OpenStatus

- `, - from: "Notification OpenStatus ", + const subscribersEmails = subscribers.map((subscriber) => { + return { + to: subscriber.email, + subject: `New status update for ${pageInfo.title}`, + html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${statusReportUpdate.status}

${statusReportUpdate.message}

Powered by OpenStatus

+ `, + from: "Notification OpenStatus ", + }; }); + await sendBatchEmailHtml(subscribersEmails); } } diff --git a/apps/web/package.json b/apps/web/package.json index f728605ba..f6e5db902 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -80,7 +80,7 @@ "rehype-react": "7.2.0", "remark-parse": "10.0.2", "remark-rehype": "10.1.0", - "resend": "1.1.0", + "resend": "4.0.0", "rss": "1.2.2", "shiki": "0.14.4", "sonner": "1.3.1", diff --git a/packages/api/src/router/statusReport.ts b/packages/api/src/router/statusReport.ts index bef92291c..04a0199a6 100644 --- a/packages/api/src/router/statusReport.ts +++ b/packages/api/src/router/statusReport.ts @@ -16,7 +16,7 @@ import { statusReportUpdate, workspace, } from "@openstatus/db/src/schema"; -import { sendEmailHtml } from "@openstatus/emails/emails/send"; +import { sendBatchEmailHtml } from "@openstatus/emails/emails/send"; import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; @@ -99,16 +99,19 @@ export const statusReportRouter = createTRPCRouter({ .where(eq(page.id, _statusReport.pageId)) .get(); if (pageInfo) { - const subscribersEmails = subscribers.map( - (subscriber) => subscriber.email, - ); - await sendEmailHtml({ - to: subscribersEmails, - subject: `New status update for ${pageInfo.title}`, - html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${updatedValue.status}

${updatedValue.message}

Powered by OpenStatus

+ const emails = subscribers.map((subscriber) => { + return { + to: subscriber.email, + + subject: `New status update for ${pageInfo.title}`, + html: `

Hi,

${pageInfo.title} just posted an update on their status page:

New Status : ${updatedValue.status}

${updatedValue.message}

Powered by OpenStatus

`, - from: "Notification OpenStatus ", + from: "Notification OpenStatus ", + }; }); + if (emails.length > 0) { + await sendBatchEmailHtml(emails); + } } } return updatedValue; diff --git a/packages/emails/emails/send.ts b/packages/emails/emails/send.ts index 7f92a7098..c346d2f48 100644 --- a/packages/emails/emails/send.ts +++ b/packages/emails/emails/send.ts @@ -15,15 +15,19 @@ export interface Emails { export type EmailHtml = { html: string; subject: string; - to: string[]; + to: string; from: string; }; export const sendEmail = async (email: Emails) => { await resend.emails.send(email); }; +export const sendBatchEmailHtml = async (emails: EmailHtml[]) => { + await resend.batch.send(emails); +}; + export const sendEmailHtml = async (email: EmailHtml) => { - await fetch("https://api.resend.com/emails", { + await fetch("https://api.resend.com/emails/batch", { method: "POST", headers: { "Content-Type": "application/json", diff --git a/packages/emails/package.json b/packages/emails/package.json index 5457e3314..bcad95d64 100644 --- a/packages/emails/package.json +++ b/packages/emails/package.json @@ -17,7 +17,7 @@ "@react-email/tailwind": "0.0.9", "@t3-oss/env-core": "0.7.0", "react-email": "1.10.0", - "resend": "2.0.0", + "resend": "4.0.0", "zod": "3.23.8" }, "devDependencies": { diff --git a/packages/notifications/email/package.json b/packages/notifications/email/package.json index 33ff31aa4..92431cfd9 100644 --- a/packages/notifications/email/package.json +++ b/packages/notifications/email/package.json @@ -10,7 +10,7 @@ "@react-email/components": "0.0.7", "@react-email/render": "0.0.7", "@t3-oss/env-core": "0.7.0", - "resend": "1.1.0", + "resend": "4.0.0", "zod": "3.23.8" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b52f63023..9ca19a8a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -192,7 +192,7 @@ importers: version: link:../../packages/utils '@scalar/hono-api-reference': specifier: 0.5.131 - version: 0.5.131(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2) + version: 0.5.131(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2) '@t3-oss/env-core': specifier: 0.7.1 version: 0.7.1(typescript@5.5.2)(zod@3.23.8) @@ -444,8 +444,8 @@ importers: specifier: 10.1.0 version: 10.1.0 resend: - specifier: 1.1.0 - version: 1.1.0 + specifier: 4.0.0 + version: 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rss: specifier: 1.2.2 version: 1.2.2 @@ -685,8 +685,8 @@ importers: specifier: 1.10.0 version: 1.10.0(encoding@0.1.13) resend: - specifier: 2.0.0 - version: 2.0.0 + specifier: 4.0.0 + version: 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) zod: specifier: 3.23.8 version: 3.23.8 @@ -775,8 +775,8 @@ importers: specifier: 0.7.0 version: 0.7.0(typescript@5.5.2)(zod@3.23.8) resend: - specifier: 1.1.0 - version: 1.1.0 + specifier: 4.0.0 + version: 4.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0) zod: specifier: 3.23.8 version: 3.23.8 @@ -4454,14 +4454,17 @@ packages: resolution: {integrity: sha512-FdLhg/E5PH5qZU/jf9NbvRi5v5134kbX7o8zIhOJIk/TALxB18ggprnH5tQX96dGQFqlLob8OLReaRwrpEF7YA==} engines: {node: '>=18.0.0'} + '@react-email/render@0.0.17': + resolution: {integrity: sha512-xBQ+/73+WsGuXKY7r1U73zMBNV28xdV0cp9cFjhNYipBReDHhV97IpA6v7Hl0dDtDzt+yS/72dY5vYXrF1v8NA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.2.0 + react-dom: ^18.2.0 + '@react-email/render@0.0.7': resolution: {integrity: sha512-hMMhxk6TpOcDC5qnKzXPVJoVGEwfm+U5bGOPH+MyTTlx0F02RLQygcATBKsbP7aI/mvkmBAZoFbgPIHop7ovug==} engines: {node: '>=16.0.0'} - '@react-email/render@0.0.9': - resolution: {integrity: sha512-nrim7wiACnaXsGtL7GF6jp3Qmml8J6vAjAH88jkC8lIbfNZaCyuPQHANjyYIXlvQeAbsWADQJFZgOHUqFqjh/A==} - engines: {node: '>=18.0.0'} - '@react-email/row@0.0.5': resolution: {integrity: sha512-dir5l1M7Z/1BQqQkUrKUPIIDPt6ueEf6ScMGoBOcUh+VNNqmnqJE2Q2CH5X3w2uo6a5X7tnVhoJHGa2KTKe8Sw==} engines: {node: '>=16.0.0'} @@ -5389,6 +5392,10 @@ packages: abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -6580,6 +6587,9 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-deep-equal@2.0.1: + resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -7409,6 +7419,11 @@ packages: engines: {node: '>=12'} hasBin: true + js-beautify@1.15.1: + resolution: {integrity: sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==} + engines: {node: '>=14'} + hasBin: true + js-cookie@3.0.5: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} @@ -8282,6 +8297,11 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} hasBin: true + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -8837,6 +8857,9 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-promise-suspense@0.3.4: + resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==} + react-property@2.0.0: resolution: {integrity: sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==} @@ -9062,12 +9085,8 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - resend@1.1.0: - resolution: {integrity: sha512-it8TIDVT+/gAiJsUlv2tdHuvzwCCv4Zwu+udDqIm/dIuByQwe68TtFDcPccxqpSVVrNCBxxXLzsdT1tsV+P3GA==} - engines: {node: '>=18'} - - resend@2.0.0: - resolution: {integrity: sha512-jAh0DN84ZjjmzGM2vMjJ1hphPBg1mG98dzopF7kJzmin62v8ESg4og2iCKWdkAboGOT2SeO5exbr/8Xh8gLddw==} + resend@4.0.0: + resolution: {integrity: sha512-rDX0rspl/XcmC2JV2V5obQvRX2arzxXUvNFUDMOv5ObBLR68+7kigCOysb7+dlkb0JE3erhQG0nHrbBt/ZCWIg==} engines: {node: '>=18'} resolve-from@5.0.0: @@ -9759,10 +9778,6 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} - type-fest@3.13.0: - resolution: {integrity: sha512-Gur3yQGM9qiLNs0KPP7LPgeRbio2QTt4xXouobMCarR0/wyW3F+F/+OWwshg3NG0Adon7uQfSZBpB46NfhoF1A==} - engines: {node: '>=14.16'} - type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} @@ -12570,10 +12585,6 @@ snapshots: dependencies: tailwindcss: 3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)) - '@headlessui/tailwindcss@0.2.0(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))': - dependencies: - tailwindcss: 3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)) - '@headlessui/tailwindcss@0.2.1(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))': dependencies: tailwindcss: 3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)) @@ -14034,16 +14045,25 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@react-email/render@0.0.7': + '@react-email/render@0.0.17(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - html-to-text: 9.0.3 - pretty: 2.0.0 + html-to-text: 9.0.5 + js-beautify: 1.15.1 react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react-dom: 18.3.1(react@18.2.0) + react-promise-suspense: 0.3.4 - '@react-email/render@0.0.9': + '@react-email/render@0.0.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: html-to-text: 9.0.5 + js-beautify: 1.15.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-promise-suspense: 0.3.4 + + '@react-email/render@0.0.7': + dependencies: + html-to-text: 9.0.3 pretty: 2.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -14101,9 +14121,9 @@ snapshots: optionalDependencies: rollup: 2.78.0 - '@scalar/api-client@2.0.45(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2)': + '@scalar/api-client@2.0.45(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2)': dependencies: - '@headlessui/tailwindcss': 0.2.0(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2))) + '@headlessui/tailwindcss': 0.2.0(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2))) '@headlessui/vue': 1.7.22(vue@3.4.31(typescript@5.5.2)) '@scalar/components': 0.12.28(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.5.2) '@scalar/draggable': 0.1.4(typescript@5.5.2) @@ -14139,11 +14159,11 @@ snapshots: - typescript - vitest - '@scalar/api-reference@1.24.70(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2)': + '@scalar/api-reference@1.24.70(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2)': dependencies: '@floating-ui/vue': 1.1.1(vue@3.4.31(typescript@5.5.2)) '@headlessui/vue': 1.7.22(vue@3.4.31(typescript@5.5.2)) - '@scalar/api-client': 2.0.45(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2) + '@scalar/api-client': 2.0.45(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2) '@scalar/components': 0.12.28(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.5.2) '@scalar/oas-utils': 0.2.26(typescript@5.5.2) '@scalar/openapi-parser': 0.7.2 @@ -14228,9 +14248,9 @@ snapshots: transitivePeerDependencies: - typescript - '@scalar/hono-api-reference@0.5.131(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2)': + '@scalar/hono-api-reference@0.5.131(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2)': dependencies: - '@scalar/api-reference': 1.24.70(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.8.0)(typescript@5.5.2)))(typescript@5.5.2) + '@scalar/api-reference': 1.24.70(postcss@8.4.38)(storybook@8.2.1(@babel/preset-env@7.24.8(@babel/core@7.24.8))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2)))(typescript@5.5.2) hono: 4.5.3 transitivePeerDependencies: - '@jest/globals' @@ -15485,6 +15505,8 @@ snapshots: abbrev@1.1.1: {} + abbrev@2.0.0: {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -16766,6 +16788,8 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-deep-equal@2.0.1: {} + fast-deep-equal@3.1.3: {} fast-equals@5.0.1: {} @@ -17788,6 +17812,14 @@ snapshots: glob: 8.1.0 nopt: 6.0.0 + js-beautify@1.15.1: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.3.4 + js-cookie: 3.0.5 + nopt: 7.2.1 + js-cookie@3.0.5: {} js-tokens@4.0.0: {} @@ -19180,6 +19212,10 @@ snapshots: dependencies: abbrev: 1.1.1 + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -19799,6 +19835,10 @@ snapshots: react-is@18.3.1: {} + react-promise-suspense@0.3.4: + dependencies: + fast-deep-equal: 2.0.1 + react-property@2.0.0: {} react-remove-scroll-bar@2.3.4(@types/react@18.3.3)(react@18.3.1): @@ -20149,14 +20189,19 @@ snapshots: require-from-string@2.0.2: {} - resend@1.1.0: + resend@4.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0): dependencies: - '@react-email/render': 0.0.7 - type-fest: 3.13.0 + '@react-email/render': 0.0.17(react-dom@18.3.1(react@18.2.0))(react@18.2.0) + transitivePeerDependencies: + - react + - react-dom - resend@2.0.0: + resend@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@react-email/render': 0.0.9 + '@react-email/render': 0.0.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + transitivePeerDependencies: + - react + - react-dom resolve-from@5.0.0: {} @@ -20977,8 +21022,6 @@ snapshots: type-fest@2.19.0: {} - type-fest@3.13.0: {} - type-fest@3.13.1: {} type-is@1.6.18: