Compare commits
8 Commits
feature/se
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5362ff7599 | |||
| 21b3c3ba83 | |||
| 44b9793c60 | |||
| 35020f2499 | |||
| 20b09849bc | |||
| dc3850ac4d | |||
| e73262b3b3 | |||
| 7299a266f1 |
12
.env.example
@@ -1,6 +1,6 @@
|
||||
ADMIN_EMAIL=""
|
||||
CRON_SECRET=""
|
||||
HOME_URL=""
|
||||
NEXT_PUBLIC_HOME_URL=""
|
||||
OVHCLOUD_API_KEY=""
|
||||
MAINTENANCE_MODE="0"
|
||||
NEWS_LIMIT="50"
|
||||
@@ -8,12 +8,8 @@ NEWS_TO_USE="10"
|
||||
NEXT_PUBLIC_BRAND_COUNTRY=""
|
||||
NEXT_PUBLIC_BRAND_EMAIL=""
|
||||
NEXT_PUBLIC_BRAND_NAME=""
|
||||
NEXT_PUBLIC_BRAND_OWNER_NAME=""
|
||||
DATABASE_URL=""
|
||||
SWEEGO_API_KEY=""
|
||||
SWEEGO_FROM=""
|
||||
SECRET_HASH=""
|
||||
|
||||
EMAIL_HOST="postfix"
|
||||
EMAIL_PORT="25"
|
||||
EMAIL_FROM=""
|
||||
MAIL_DOMAIN=""
|
||||
MAIL_HOSTNAME=""
|
||||
DKIM_SELECTOR="mail"
|
||||
|
||||
@@ -36,6 +36,6 @@ jobs:
|
||||
ssh debian@51.210.247.57 << 'EOF'
|
||||
cd /home/debian/newsletter-hackernews
|
||||
git pull origin main
|
||||
cd /home/debian/gitea
|
||||
cd /home/debian/infrastructure
|
||||
docker compose up -d --build newsletter
|
||||
EOF
|
||||
|
||||
@@ -11,10 +11,14 @@ COPY . .
|
||||
ARG NEXT_PUBLIC_BRAND_NAME
|
||||
ARG NEXT_PUBLIC_BRAND_EMAIL
|
||||
ARG NEXT_PUBLIC_BRAND_COUNTRY
|
||||
ARG NEXT_PUBLIC_HOME_URL
|
||||
ARG NEXT_PUBLIC_BRAND_OWNER_NAME
|
||||
|
||||
ENV NEXT_PUBLIC_BRAND_NAME=$NEXT_PUBLIC_BRAND_NAME
|
||||
ENV NEXT_PUBLIC_BRAND_EMAIL=$NEXT_PUBLIC_BRAND_EMAIL
|
||||
ENV NEXT_PUBLIC_BRAND_COUNTRY=$NEXT_PUBLIC_BRAND_COUNTRY
|
||||
ENV NEXT_PUBLIC_HOME_URL=$NEXT_PUBLIC_HOME_URL
|
||||
ENV NEXT_PUBLIC_BRAND_OWNER_NAME=$NEXT_PUBLIC_BRAND_OWNER_NAME
|
||||
|
||||
RUN npm run build
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ export const dynamic = 'force-dynamic'; // defaults to force-static
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
if (!process.env.RESEND_KEY) {
|
||||
throw new Error('Resend variables not set');
|
||||
if (!process.env.SWEEGO_API_KEY) {
|
||||
throw new Error('SWEEGO_API_KEY is not set');
|
||||
}
|
||||
const body = await request.json();
|
||||
const validation = ConfirmationSchema.safeParse(body);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NewsletterTemplate } from '@components/email/Newsletter';
|
||||
import prisma from '@prisma/prisma';
|
||||
import { formatApiResponse } from '@utils/formatApiResponse';
|
||||
import { sender } from '@utils/mailer';
|
||||
import { sender } from '@utils/sweego';
|
||||
import {
|
||||
INTERNAL_SERVER_ERROR,
|
||||
STATUS_INTERNAL_SERVER_ERROR,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ConfirmationTemplate } from '@components/email/Confirmation';
|
||||
import prisma from '@prisma/prisma';
|
||||
import { formatApiResponse } from '@utils/formatApiResponse';
|
||||
import { sender } from '@utils/mailer';
|
||||
import { sender } from '@utils/sweego';
|
||||
import {
|
||||
BAD_REQUEST,
|
||||
INTERNAL_SERVER_ERROR,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UnsubscribeTemplate } from '@components/email/Unsubscribe';
|
||||
import prisma from '@prisma/prisma';
|
||||
import { formatApiResponse } from '@utils/formatApiResponse';
|
||||
import { sender } from '@utils/mailer';
|
||||
import { sender } from '@utils/sweego';
|
||||
import {
|
||||
BAD_REQUEST,
|
||||
INTERNAL_SERVER_ERROR,
|
||||
@@ -30,13 +30,10 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
});
|
||||
|
||||
if (user && !user.deleted) {
|
||||
await prisma.user.update({
|
||||
if (user) {
|
||||
await prisma.user.delete({
|
||||
where: {
|
||||
email
|
||||
},
|
||||
data: {
|
||||
deleted: true
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ const Confirmation = () => {
|
||||
'@type': 'WebSite',
|
||||
name: 'Hackernews Newsletter',
|
||||
title: 'Subscription Confirmation',
|
||||
url: `${process.env.HOME_URL}/confirmation`
|
||||
url: `${process.env.NEXT_PUBLIC_HOME_URL}/confirmation`
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Tiles } from '@components/tiles/Tiles';
|
||||
import { cn } from '@utils/cn';
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
import type { Metadata } from 'next';
|
||||
import { Inter as FontSans } from 'next/font/google';
|
||||
import Script from 'next/script';
|
||||
import './globals.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -34,8 +34,12 @@ export default function RootLayout({
|
||||
<Tiles>
|
||||
<div className='z-10'>{children}</div>
|
||||
</Tiles>
|
||||
<Analytics />
|
||||
</body>
|
||||
<Script
|
||||
defer
|
||||
src='https://analytics.frompixels.com/script.js'
|
||||
data-website-id='588e7b7d-e9cd-4b96-94bf-8269c499b0a2'
|
||||
/>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export const Home = () => {
|
||||
'@type': 'WebSite',
|
||||
name: 'Hackernews Newsletter',
|
||||
title: 'Home',
|
||||
url: process.env.HOME_URL
|
||||
url: process.env.NEXT_PUBLIC_HOME_URL
|
||||
};
|
||||
|
||||
const form = useForm<SubscribeFormType>({
|
||||
|
||||
@@ -2,458 +2,113 @@
|
||||
|
||||
import { CustomCard } from '@components/CustomCard';
|
||||
import { SchemaOrg } from '@components/SchemaOrg';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
const useObfuscatedEmail = () => {
|
||||
const [email, setEmail] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setEmail(process.env.NEXT_PUBLIC_BRAND_EMAIL || null);
|
||||
}, []);
|
||||
|
||||
return email;
|
||||
};
|
||||
|
||||
const Privacy = () => {
|
||||
const email = useObfuscatedEmail();
|
||||
|
||||
const schema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
name: 'Hackernews Newsletter',
|
||||
title: 'Privacy Policy',
|
||||
url: `${process.env.HOME_URL}/privacy`
|
||||
url: `${process.env.NEXT_PUBLIC_HOME_URL}/privacy`
|
||||
};
|
||||
|
||||
const body = (
|
||||
<div className='privacy-content my-2 max-h-[50vh] space-y-1 overflow-auto'>
|
||||
<h2>Who We Are</h2>
|
||||
<p className='leading-relaxed'>
|
||||
This Privacy Policy describes Our policies and procedures on the
|
||||
collection, use and disclosure of Your information when You use the
|
||||
Service and tells You about Your privacy rights and how the law protects
|
||||
You.
|
||||
Data controller: {process.env.NEXT_PUBLIC_BRAND_OWNER_NAME}, an
|
||||
individual based in {process.env.NEXT_PUBLIC_BRAND_COUNTRY}.
|
||||
</p>
|
||||
<p>
|
||||
We use Your Personal data to provide and improve the Service. By using
|
||||
the Service, You agree to the collection and use of information in
|
||||
accordance with this Privacy Policy.
|
||||
Contact:{' '}
|
||||
<a
|
||||
href={`mailto:${process.env.NEXT_PUBLIC_BRAND_EMAIL}`}
|
||||
className='text-purple-600 hover:text-purple-700'
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_BRAND_EMAIL}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h2>Interpretation and Definitions</h2>
|
||||
<h3>Interpretation</h3>
|
||||
<h2>What We Collect</h2>
|
||||
<p className='leading-relaxed'>
|
||||
The words of which the initial letter is capitalized have meanings
|
||||
defined under the following conditions. The following definitions shall
|
||||
have the same meaning regardless of whether they appear in singular or
|
||||
in plural.
|
||||
Your email address (required to send the newsletter).
|
||||
</p>
|
||||
|
||||
<h3>Definitions</h3>
|
||||
<h2>Why We Collect It</h2>
|
||||
<p className='leading-relaxed'>
|
||||
For the purposes of this Privacy Policy:
|
||||
To deliver the daily {process.env.NEXT_PUBLIC_BRAND_NAME}{' '}
|
||||
newsletter—a digest of top Hacker News stories with AI-generated
|
||||
commentary.
|
||||
</p>
|
||||
<p>
|
||||
We do not sell products, track your activity beyond essential delivery,
|
||||
or share your data for marketing.
|
||||
</p>
|
||||
|
||||
<h2>Legal Basis</h2>
|
||||
<p className='leading-relaxed'>
|
||||
Your explicit consent via double opt-in signup (you receive a
|
||||
confirmation email with an activation link).
|
||||
</p>
|
||||
|
||||
<h2>Third Parties</h2>
|
||||
<ul className='list-disc space-y-4 pl-6'>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Account</strong> means a unique account created for You to
|
||||
access our Service or parts of our Service.
|
||||
</p>
|
||||
<strong>Email delivery:</strong> Resend (US). GDPR-compliant email
|
||||
infrastructure.
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Affiliate</strong> means an entity that controls, is
|
||||
controlled by or is under common control with a party, where
|
||||
"control" means ownership of 50% or more of the shares,
|
||||
equity interest or other securities entitled to vote for election of
|
||||
directors or other managing authority.
|
||||
</p>
|
||||
<strong>Hosting & analytics:</strong> Vercel (US). Analytics are
|
||||
anonymized and aggregated—no personal data beyond your email is
|
||||
collected.
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Application</strong> refers to{' '}
|
||||
{process.env.NEXT_PUBLIC_BRAND_NAME}, the software program provided
|
||||
by the Company.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Company</strong> (referred to as either "the
|
||||
Company", "We", "Us" or "Our" in
|
||||
this Agreement) refers to {process.env.NEXT_PUBLIC_BRAND_NAME}.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Country</strong> refers to:{' '}
|
||||
{process.env.NEXT_PUBLIC_BRAND_COUNTRY}
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Device</strong> means any device that can access the Service
|
||||
such as a computer, a cellphone or a digital tablet.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Personal Data</strong> is any information that relates to an
|
||||
identified or identifiable individual.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Service</strong> refers to the Application.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Service Provider</strong> means any natural or legal person
|
||||
who processes the data on behalf of the Company. It refers to
|
||||
third-party companies or individuals employed by the Company to
|
||||
facilitate the Service, to provide the Service on behalf of the
|
||||
Company, to perform services related to the Service or to assist the
|
||||
Company in analyzing how the Service is used.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Usage Data</strong> refers to data collected automatically,
|
||||
either generated by the use of the Service or from the Service
|
||||
infrastructure itself (for example, the duration of a page visit).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>You</strong> means the individual accessing or using the
|
||||
Service, or the company, or other legal entity on behalf of which
|
||||
such individual is accessing or using the Service, as applicable.
|
||||
</p>
|
||||
<strong>Content source:</strong> Public Hacker News API (Y Combinator,
|
||||
US).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Data Collection and Usage</h2>
|
||||
<h3>Types of Data Collected</h3>
|
||||
|
||||
<h4>Personal Data</h4>
|
||||
<p className='leading-relaxed'>
|
||||
While using Our Service, We may ask You to provide Us with certain
|
||||
personally identifiable information that can be used to contact or
|
||||
identify You. Personally identifiable information may include, but is
|
||||
not limited to:
|
||||
</p>
|
||||
<h2>Your Rights</h2>
|
||||
<ul className='list-disc space-y-4 pl-6'>
|
||||
<li>Unsubscribe anytime via the link in every email</li>
|
||||
<li>
|
||||
<p>Email address</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Usage Data</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Usage Data</h4>
|
||||
<p className='leading-relaxed'>
|
||||
Usage Data is collected automatically when using the Service.
|
||||
</p>
|
||||
<p>
|
||||
Usage Data may include information such as Your Device's Internet
|
||||
Protocol address (e.g. IP address), browser type, browser version, the
|
||||
pages of our Service that You visit, the time and date of Your visit,
|
||||
the time spent on those pages, unique device identifiers and other
|
||||
diagnostic data.
|
||||
</p>
|
||||
<p>
|
||||
When You access the Service by or through a mobile device, We may
|
||||
collect certain information automatically, including, but not limited
|
||||
to, the type of mobile device You use, Your mobile device unique ID, the
|
||||
IP address of Your mobile device, Your mobile operating system, the type
|
||||
of mobile Internet browser You use, unique device identifiers and other
|
||||
diagnostic data.
|
||||
</p>
|
||||
<p>
|
||||
We may also collect information that Your browser sends whenever You
|
||||
visit our Service or when You access the Service by or through a mobile
|
||||
device.
|
||||
</p>
|
||||
|
||||
<h2>Use of Your Personal Data</h2>
|
||||
<p className='leading-relaxed'>
|
||||
The Company may use Personal Data for the following purposes:
|
||||
</p>
|
||||
<ul className='list-disc space-y-4 pl-6'>
|
||||
<li>
|
||||
<p>
|
||||
<strong>To provide and maintain our Service</strong>, including to
|
||||
monitor the usage of our Service.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>To manage Your Account:</strong> to manage Your registration
|
||||
as a user of the Service. The Personal Data You provide can give You
|
||||
access to different functionalities of the Service that are
|
||||
available to You as a registered user.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>For the performance of a contract:</strong> the development,
|
||||
compliance and undertaking of the purchase contract for the
|
||||
products, items or services You have purchased or of any other
|
||||
contract with Us through the Service.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>To contact You:</strong> To contact You by email, telephone
|
||||
calls, SMS, or other equivalent forms of electronic communication,
|
||||
such as a mobile application's push notifications regarding
|
||||
updates or informative communications related to the
|
||||
functionalities, products or contracted services, including the
|
||||
security updates, when necessary or reasonable for their
|
||||
implementation.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>To provide You</strong> with news, special offers and
|
||||
general information about other goods, services and events which we
|
||||
offer that are similar to those that you have already purchased or
|
||||
enquired about unless You have opted not to receive such
|
||||
information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>To manage Your requests:</strong> To attend and manage Your
|
||||
requests to Us.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>For business transfers:</strong> We may use Your information
|
||||
to evaluate or conduct a merger, divestiture, restructuring,
|
||||
reorganization, dissolution, or other sale or transfer of some or
|
||||
all of Our assets, whether as a going concern or as part of
|
||||
bankruptcy, liquidation, or similar proceeding, in which Personal
|
||||
Data held by Us about our Service users is among the assets
|
||||
transferred.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<strong>For other purposes</strong>: We may use Your information for
|
||||
other purposes, such as data analysis, identifying usage trends,
|
||||
determining the effectiveness of our promotional campaigns and to
|
||||
evaluate and improve our Service, products, services, marketing and
|
||||
your experience.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>We may share Your personal information in the following situations:</p>
|
||||
<ul className='list-disc space-y-4 pl-6'>
|
||||
<li>
|
||||
<strong>With Service Providers:</strong> We may share Your personal
|
||||
information with Service Providers to monitor and analyze the use of
|
||||
our Service, to contact You.
|
||||
</li>
|
||||
<li>
|
||||
<strong>For business transfers:</strong> We may share or transfer Your
|
||||
personal information in connection with, or during negotiations of,
|
||||
any merger, sale of Company assets, financing, or acquisition of all
|
||||
or a portion of Our business to another company.
|
||||
</li>
|
||||
<li>
|
||||
<strong>With Affiliates:</strong> We may share Your information with
|
||||
Our affiliates, in which case we will require those affiliates to
|
||||
honor this Privacy Policy. Affiliates include Our parent company and
|
||||
any other subsidiaries, joint venture partners or other companies that
|
||||
We control or that are under common control with Us.
|
||||
</li>
|
||||
<li>
|
||||
<strong>With business partners:</strong> We may share Your information
|
||||
with Our business partners to offer You certain products, services or
|
||||
promotions.
|
||||
</li>
|
||||
<li>
|
||||
<strong>With other users:</strong> when You share personal information
|
||||
or otherwise interact in the public areas with other users, such
|
||||
information may be viewed by all users and may be publicly distributed
|
||||
outside.
|
||||
</li>
|
||||
<li>
|
||||
<strong>With Your consent</strong>: We may disclose Your personal
|
||||
information for any other purpose with Your consent.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Data Handling and Security</h2>
|
||||
|
||||
<h3>Retention of Your Personal Data</h3>
|
||||
<p className='leading-relaxed'>
|
||||
The Company will retain Your Personal Data only for as long as is
|
||||
necessary for the purposes set out in this Privacy Policy. We will
|
||||
retain and use Your Personal Data to the extent necessary to comply with
|
||||
our legal obligations (for example, if we are required to retain your
|
||||
data to comply with applicable laws), resolve disputes, and enforce our
|
||||
legal agreements and policies.
|
||||
</p>
|
||||
<p>
|
||||
The Company will also retain Usage Data for internal analysis purposes.
|
||||
Usage Data is generally retained for a shorter period of time, except
|
||||
when this data is used to strengthen the security or to improve the
|
||||
functionality of Our Service, or We are legally obligated to retain this
|
||||
data for longer time periods.
|
||||
</p>
|
||||
|
||||
<h3>Transfer of Your Personal Data</h3>
|
||||
<p className='leading-relaxed'>
|
||||
Your information, including Personal Data, is processed at the
|
||||
Company's operating offices and in any other places where the
|
||||
parties involved in the processing are located. It means that this
|
||||
information may be transferred to — and maintained on — computers
|
||||
located outside of Your state, province, country or other governmental
|
||||
jurisdiction where the data protection laws may differ than those from
|
||||
Your jurisdiction.
|
||||
</p>
|
||||
|
||||
<h3>Security of Your Personal Data</h3>
|
||||
<p className='leading-relaxed'>
|
||||
Your consent to this Privacy Policy followed by Your submission of such
|
||||
information represents Your agreement to that transfer.
|
||||
</p>
|
||||
<p>
|
||||
The Company will take all steps reasonably necessary to ensure that Your
|
||||
data is treated securely and in accordance with this Privacy Policy and
|
||||
no transfer of Your Personal Data will take place to an organization or
|
||||
a country unless there are adequate controls in place including the
|
||||
security of Your data and other personal information.
|
||||
</p>
|
||||
|
||||
<h4 className='text-lg font-medium text-gray-800'>
|
||||
Delete Your Personal Data
|
||||
</h4>
|
||||
<p className='leading-relaxed'>
|
||||
You have the right to delete or request that We assist in deleting the
|
||||
Personal Data that We have collected about You.
|
||||
</p>
|
||||
<p>
|
||||
Our Service may give You the ability to delete certain information about
|
||||
You from within the Service.
|
||||
</p>
|
||||
<p>
|
||||
You may update, amend, or delete Your information at any time by signing
|
||||
in to Your Account, if you have one, and visiting the account settings
|
||||
section that allows you to manage Your personal information. You may
|
||||
also contact Us to request access to, correct, or delete any personal
|
||||
information that You have provided to Us.
|
||||
</p>
|
||||
<p>
|
||||
Please note, however, that We may need to retain certain information
|
||||
when we have a legal obligation or lawful basis to do so.
|
||||
</p>
|
||||
|
||||
<h2>Legal Disclosures</h2>
|
||||
|
||||
<h3>Business Transactions</h3>
|
||||
<p className='leading-relaxed'>
|
||||
If the Company is involved in a merger, acquisition or asset sale, Your
|
||||
Personal Data may be transferred. We will provide notice before Your
|
||||
Personal Data is transferred and becomes subject to a different Privacy
|
||||
Policy.
|
||||
</p>
|
||||
|
||||
<h3>Law Enforcement</h3>
|
||||
<p className='leading-relaxed'>
|
||||
Under certain circumstances, the Company may be required to disclose
|
||||
Your Personal Data if required to do so by law or in response to valid
|
||||
requests by public authorities (e.g. a court or a government agency).
|
||||
</p>
|
||||
|
||||
<h3>Other Legal Requirements</h3>
|
||||
<p className='leading-relaxed'>
|
||||
The Company may disclose Your Personal Data in the good faith belief
|
||||
that such action is necessary to:
|
||||
</p>
|
||||
<ul className='list-disc space-y-4 pl-6'>
|
||||
<li>Comply with a legal obligation</li>
|
||||
<li>Protect and defend the rights or property of the Company</li>
|
||||
<li>
|
||||
Prevent or investigate possible wrongdoing in connection with the
|
||||
Service
|
||||
</li>
|
||||
<li>
|
||||
Protect the personal safety of Users of the Service or the public
|
||||
</li>
|
||||
<li>Protect against legal liability</li>
|
||||
</ul>
|
||||
|
||||
<h2>Additional Information</h2>
|
||||
<p className='leading-relaxed'>
|
||||
The security of Your Personal Data is important to Us, but remember that
|
||||
no method of transmission over the Internet, or method of electronic
|
||||
storage is 100% secure. While We strive to use commercially acceptable
|
||||
means to protect Your Personal Data, We cannot guarantee its absolute
|
||||
security.
|
||||
</p>
|
||||
<h3>Children's Privacy</h3>
|
||||
<p className='leading-relaxed'>
|
||||
Our Service does not address anyone under the age of 13. We do not
|
||||
knowingly collect personally identifiable information from anyone under
|
||||
the age of 13. If You are a parent or guardian and You are aware that
|
||||
Your child has provided Us with Personal Data, please contact Us. If We
|
||||
become aware that We have collected Personal Data from anyone under the
|
||||
age of 13 without verification of parental consent, We take steps to
|
||||
remove that information from Our servers.
|
||||
</p>
|
||||
<p>
|
||||
If We need to rely on consent as a legal basis for processing Your
|
||||
information and Your country requires consent from a parent, We may
|
||||
require Your parent's consent before We collect and use that
|
||||
information.
|
||||
</p>
|
||||
|
||||
<h3>Links to Other Websites</h3>
|
||||
<p className='leading-relaxed'>
|
||||
Our Service may contain links to other websites that are not operated by
|
||||
Us. If You click on a third party link, You will be directed to that
|
||||
third party's site. We strongly advise You to review the Privacy
|
||||
Policy of every site You visit.
|
||||
</p>
|
||||
<p>
|
||||
We have no control over and assume no responsibility for the content,
|
||||
privacy policies or practices of any third party sites or services.
|
||||
</p>
|
||||
|
||||
<h3>Changes to this Privacy Policy</h3>
|
||||
<p className='leading-relaxed'>
|
||||
We may update Our Privacy Policy from time to time. We will notify You
|
||||
of any changes by posting the new Privacy Policy on this page.
|
||||
</p>
|
||||
<p>
|
||||
We will let You know via email and/or a prominent notice on Our Service,
|
||||
prior to the change becoming effective and update the "Last
|
||||
updated" date at the top of this Privacy Policy.
|
||||
</p>
|
||||
<p>
|
||||
You are advised to review this Privacy Policy periodically for any
|
||||
changes. Changes to this Privacy Policy are effective when they are
|
||||
posted on this page.
|
||||
</p>
|
||||
|
||||
<h2>Contact Information</h2>
|
||||
<p className='leading-relaxed'>
|
||||
If you have any questions about this Privacy Policy, You can contact us
|
||||
by writing to{' '}
|
||||
{email ? (
|
||||
Request deletion of your email by contacting{' '}
|
||||
<a
|
||||
href={`mailto:${email}`}
|
||||
href={`mailto:${process.env.NEXT_PUBLIC_BRAND_EMAIL}`}
|
||||
className='text-purple-600 hover:text-purple-700'
|
||||
>
|
||||
{email}
|
||||
{process.env.NEXT_PUBLIC_BRAND_EMAIL}
|
||||
</a>
|
||||
) : (
|
||||
<span className='text-gray-400'>loading...</span>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
Upon unsubscribe or deletion request, your email is permanently
|
||||
deleted from our database
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Data Retention</h2>
|
||||
<p className='leading-relaxed'>
|
||||
We retain your email address only until you unsubscribe.
|
||||
</p>
|
||||
|
||||
<h2>International Transfers</h2>
|
||||
<p className='leading-relaxed'>
|
||||
We rely on EU-approved safeguards including Standard Contractual Clauses
|
||||
to ensure adequate protection when using US-based services.
|
||||
</p>
|
||||
|
||||
<h2>Changes</h2>
|
||||
<p className='leading-relaxed'>
|
||||
We may update this policy occasionally. The latest version will always
|
||||
be available at{' '}
|
||||
<a
|
||||
href={`${process.env.NEXT_PUBLIC_HOME_URL}/privacy`}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='text-purple-600 hover:text-purple-700'
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_HOME_URL}/privacy
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
@@ -465,7 +120,7 @@ const Privacy = () => {
|
||||
<CustomCard
|
||||
className='max-90vh max-90vw'
|
||||
title='Privacy Policy'
|
||||
description='Last updated: November 23, 2024'
|
||||
description='Last updated: January 28, 2026'
|
||||
content={body}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -6,6 +6,6 @@ export default function robots(): MetadataRoute.Robots {
|
||||
userAgent: '*',
|
||||
disallow: ''
|
||||
},
|
||||
sitemap: `${process.env.HOME_URL!}/sitemap.xml`
|
||||
sitemap: `${process.env.NEXT_PUBLIC_HOME_URL!}/sitemap.xml`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,19 +3,19 @@ import { MetadataRoute } from 'next';
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
return [
|
||||
{
|
||||
url: process.env.HOME_URL!,
|
||||
url: process.env.NEXT_PUBLIC_HOME_URL!,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'yearly',
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
url: `${process.env.HOME_URL!}/privacy`,
|
||||
url: `${process.env.NEXT_PUBLIC_HOME_URL!}/privacy`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.5
|
||||
},
|
||||
{
|
||||
url: `${process.env.HOME_URL!}/unsubscribe`,
|
||||
url: `${process.env.NEXT_PUBLIC_HOME_URL!}/unsubscribe`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.2
|
||||
|
||||
@@ -33,7 +33,7 @@ const Unsubscribe = () => {
|
||||
'@type': 'WebSite',
|
||||
name: 'Hackernews Newsletter',
|
||||
title: 'Unsubscribe',
|
||||
url: `${process.env.HOME_URL}/unsubscribe`
|
||||
url: `${process.env.NEXT_PUBLIC_HOME_URL}/unsubscribe`
|
||||
};
|
||||
|
||||
const form = useForm<UnsubscribeFormType>({
|
||||
|
||||
@@ -22,7 +22,7 @@ export const ConfirmationTemplate = (code: string) => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href={`${process.env.HOME_URL}/confirmation?code=${code}`}
|
||||
href={`${process.env.NEXT_PUBLIC_HOME_URL}/confirmation?code=${code}`}
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
padding: '12px 24px',
|
||||
|
||||
@@ -22,7 +22,7 @@ export const UnsubscribeTemplate = () => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href={`${process.env.HOME_URL}/`}
|
||||
href={`${process.env.NEXT_PUBLIC_HOME_URL}/`}
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
padding: '12px 24px',
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
const iconStyle = {
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'middle'
|
||||
};
|
||||
|
||||
const Icon = ({ name, size = 16 }: { name: string; size?: number }) => (
|
||||
<img
|
||||
src={`${process.env.HOME_URL}/email-icons/${name}.png`}
|
||||
width={size}
|
||||
height={size}
|
||||
alt=""
|
||||
style={iconStyle}
|
||||
/>
|
||||
);
|
||||
import {
|
||||
User,
|
||||
Building2,
|
||||
Mail,
|
||||
LogOut,
|
||||
LayoutGrid,
|
||||
Shield,
|
||||
Home
|
||||
} from 'lucide-react';
|
||||
|
||||
export const Footer = () => {
|
||||
return (
|
||||
@@ -49,7 +44,7 @@ export const Footer = () => {
|
||||
letterSpacing: '0.05em'
|
||||
}}
|
||||
>
|
||||
<Icon name="user" size={16} />
|
||||
<User size={16} color='#386FA4' />
|
||||
Contact Us
|
||||
</h4>
|
||||
<p
|
||||
@@ -62,7 +57,7 @@ export const Footer = () => {
|
||||
color: '#4A5568'
|
||||
}}
|
||||
>
|
||||
<Icon name="building-2" size={14} />
|
||||
<Building2 size={14} color='#386FA4' />
|
||||
{process.env.NEXT_PUBLIC_BRAND_NAME}
|
||||
</p>
|
||||
<p
|
||||
@@ -75,7 +70,7 @@ export const Footer = () => {
|
||||
color: '#4A5568'
|
||||
}}
|
||||
>
|
||||
<Icon name="mail" size={14} />
|
||||
<Mail size={14} color='#386FA4' />
|
||||
<a
|
||||
href={`mailto:${process.env.NEXT_PUBLIC_BRAND_EMAIL}`}
|
||||
style={{ color: '#386FA4', textDecoration: 'none' }}
|
||||
@@ -93,11 +88,11 @@ export const Footer = () => {
|
||||
color: '#4A5568'
|
||||
}}
|
||||
>
|
||||
<Icon name="log-out" size={14} />
|
||||
<LogOut size={14} color='#386FA4' />
|
||||
<span>
|
||||
Click{' '}
|
||||
<a
|
||||
href={`${process.env.HOME_URL}/unsubscribe`}
|
||||
href={`${process.env.NEXT_PUBLIC_HOME_URL}/unsubscribe`}
|
||||
style={{ color: '#386FA4', textDecoration: 'none' }}
|
||||
>
|
||||
here
|
||||
@@ -129,7 +124,7 @@ export const Footer = () => {
|
||||
letterSpacing: '0.05em'
|
||||
}}
|
||||
>
|
||||
<Icon name="layout-grid" size={16} />
|
||||
<LayoutGrid size={16} color='#386FA4' />
|
||||
Quick Links
|
||||
</h4>
|
||||
<p
|
||||
@@ -142,9 +137,9 @@ export const Footer = () => {
|
||||
color: '#4A5568'
|
||||
}}
|
||||
>
|
||||
<Icon name="shield" size={14} />
|
||||
<Shield size={14} color='#386FA4' />
|
||||
<a
|
||||
href={`${process.env.HOME_URL}/privacy`}
|
||||
href={`${process.env.NEXT_PUBLIC_HOME_URL}/privacy`}
|
||||
style={{ color: '#386FA4', textDecoration: 'none' }}
|
||||
>
|
||||
Privacy Policy
|
||||
@@ -160,9 +155,9 @@ export const Footer = () => {
|
||||
color: '#4A5568'
|
||||
}}
|
||||
>
|
||||
<Icon name="house" size={14} />
|
||||
<Home size={14} color='#386FA4' />
|
||||
<a
|
||||
href={process.env.HOME_URL}
|
||||
href={process.env.NEXT_PUBLIC_HOME_URL}
|
||||
style={{ color: '#386FA4', textDecoration: 'none' }}
|
||||
>
|
||||
Visit Website
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
@@ -10,37 +11,6 @@ services:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U newsletter"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Postfix mail server with OpenDKIM for self-hosted email
|
||||
postfix:
|
||||
build: ./docker/postfix
|
||||
container_name: newsletter-postfix
|
||||
restart: always
|
||||
# dns: Uses VPS default DNS. If MX lookups fail, uncomment and set explicit DNS:
|
||||
# - 213.186.33.99 # OVH DNS
|
||||
environment:
|
||||
- MAIL_DOMAIN=${MAIL_DOMAIN:-example.com}
|
||||
- MAIL_HOSTNAME=${MAIL_HOSTNAME:-mail.example.com}
|
||||
- DKIM_SELECTOR=${DKIM_SELECTOR:-mail}
|
||||
volumes:
|
||||
# Persist DKIM keys across container rebuilds
|
||||
- postfix-dkim:/etc/opendkim/keys
|
||||
# Persist mail queue
|
||||
- postfix-spool:/var/spool/postfix
|
||||
# Port 25 not exposed to host - only accessible within Docker network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "echo 'QUIT' | nc -w 5 localhost 25 | grep -q '220' || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
start_period: 10s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
postfix-dkim:
|
||||
postfix-spool:
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# install oostfix and OpenDKIM
|
||||
RUN apt-get update && apt-get install -y \
|
||||
postfix \
|
||||
opendkim \
|
||||
opendkim-tools \
|
||||
mailutils \
|
||||
ca-certificates \
|
||||
netcat-openbsd \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# create OpenDKIM paths
|
||||
RUN mkdir -p /etc/opendkim/keys && \
|
||||
chown -R opendkim:opendkim /etc/opendkim && \
|
||||
chmod 700 /etc/opendkim/keys
|
||||
|
||||
# copy config
|
||||
COPY postfix-main.cf /etc/postfix/main.cf
|
||||
COPY opendkim.conf /etc/opendkim.conf
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
EXPOSE 25
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
||||
CMD echo "QUIT" | nc -w 5 localhost 25 | grep -q "220" || exit 1
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# environment variables
|
||||
MAIL_DOMAIN="${MAIL_DOMAIN:-example.com}"
|
||||
MAIL_HOSTNAME="${MAIL_HOSTNAME:-mail.example.com}"
|
||||
DKIM_SELECTOR="${DKIM_SELECTOR:-mail}"
|
||||
|
||||
echo "Setting up postfix for domain: ${MAIL_DOMAIN}"
|
||||
echo "Hostname: ${MAIL_HOSTNAME}"
|
||||
|
||||
# configure postfix domain
|
||||
postconf -e "myhostname=${MAIL_HOSTNAME}"
|
||||
postconf -e "mydomain=${MAIL_DOMAIN}"
|
||||
postconf -e "myorigin=\$mydomain"
|
||||
postconf -e "mydestination=\$myhostname, localhost.\$mydomain, localhost"
|
||||
|
||||
# create OpenDKIM key folder for domain
|
||||
DKIM_KEY_DIR="/etc/opendkim/keys/${MAIL_DOMAIN}"
|
||||
mkdir -p "${DKIM_KEY_DIR}"
|
||||
|
||||
# generate DKIM keys if they don't exist
|
||||
if [ ! -f "${DKIM_KEY_DIR}/${DKIM_SELECTOR}.private" ]; then
|
||||
echo "Generating DKIM keys for ${MAIL_DOMAIN}..."
|
||||
opendkim-genkey -b 2048 -d "${MAIL_DOMAIN}" -D "${DKIM_KEY_DIR}" -s "${DKIM_SELECTOR}" -v
|
||||
chown -R opendkim:opendkim "${DKIM_KEY_DIR}"
|
||||
chmod 600 "${DKIM_KEY_DIR}/${DKIM_SELECTOR}.private"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "DKIM PUBLIC KEY - ADD THIS TO YOUR DNS:"
|
||||
echo "============================================"
|
||||
echo "Record Type: TXT"
|
||||
echo "Name: ${DKIM_SELECTOR}._domainkey.${MAIL_DOMAIN}"
|
||||
echo ""
|
||||
cat "${DKIM_KEY_DIR}/${DKIM_SELECTOR}.txt"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo ""
|
||||
else
|
||||
echo "Using existing DKIM keys"
|
||||
fi
|
||||
|
||||
# configure OpenDKIM KeyTable
|
||||
cat > /etc/opendkim/KeyTable << EOF
|
||||
${DKIM_SELECTOR}._domainkey.${MAIL_DOMAIN} ${MAIL_DOMAIN}:${DKIM_SELECTOR}:${DKIM_KEY_DIR}/${DKIM_SELECTOR}.private
|
||||
EOF
|
||||
|
||||
# configure OpenDKIM SigningTable
|
||||
cat > /etc/opendkim/SigningTable << EOF
|
||||
*@${MAIL_DOMAIN} ${DKIM_SELECTOR}._domainkey.${MAIL_DOMAIN}
|
||||
EOF
|
||||
|
||||
# configure OpenDKIM TrustedHosts
|
||||
cat > /etc/opendkim/TrustedHosts << EOF
|
||||
127.0.0.1
|
||||
localhost
|
||||
${MAIL_DOMAIN}
|
||||
*.${MAIL_DOMAIN}
|
||||
172.16.0.0/12
|
||||
192.168.0.0/16
|
||||
10.0.0.0/8
|
||||
EOF
|
||||
|
||||
# set permissions
|
||||
chown -R opendkim:opendkim /etc/opendkim
|
||||
chmod 600 /etc/opendkim/KeyTable
|
||||
chmod 600 /etc/opendkim/SigningTable
|
||||
|
||||
# create postfix spool folders
|
||||
mkdir -p /var/spool/postfix/pid
|
||||
chown root:root /var/spool/postfix
|
||||
chown root:root /var/spool/postfix/pid
|
||||
|
||||
# start OpenDKIM in background
|
||||
echo "Starting OpenDKIM..."
|
||||
opendkim -f &
|
||||
|
||||
# wait for OpenDKIM to start
|
||||
sleep 2
|
||||
|
||||
# copy DNS config to postfix chroot
|
||||
mkdir -p /var/spool/postfix/etc
|
||||
cp /etc/resolv.conf /var/spool/postfix/etc/
|
||||
cp /etc/services /var/spool/postfix/etc/
|
||||
cp /etc/hosts /var/spool/postfix/etc/
|
||||
|
||||
# start postfix in foreground
|
||||
echo "Starting Postfix..."
|
||||
postfix start-fg
|
||||
@@ -1,30 +0,0 @@
|
||||
# OpenDKIM configuration for email signing
|
||||
|
||||
# log to syslog
|
||||
Syslog yes
|
||||
SyslogSuccess yes
|
||||
LogWhy yes
|
||||
|
||||
# required for verification
|
||||
Canonicalization relaxed/simple
|
||||
|
||||
# sign mode (s=sign, v=verify)
|
||||
Mode sv
|
||||
|
||||
# sign subdomains
|
||||
SubDomains no
|
||||
|
||||
# key configuration (will be set by entrypoint)
|
||||
KeyTable /etc/opendkim/KeyTable
|
||||
SigningTable refile:/etc/opendkim/SigningTable
|
||||
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
|
||||
InternalHosts refile:/etc/opendkim/TrustedHosts
|
||||
|
||||
# socket for postfix connection
|
||||
Socket inet:8891@localhost
|
||||
|
||||
# user
|
||||
UserID opendkim
|
||||
|
||||
# permissions
|
||||
RequireSafeKeys false
|
||||
@@ -1,50 +0,0 @@
|
||||
# Postfix main configuration for newsletter sending
|
||||
# Domain and hostname will be set by entrypoint script
|
||||
|
||||
smtpd_banner = $myhostname ESMTP
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
readme_directory = no
|
||||
|
||||
# TLS parameters (for outbound connections)
|
||||
smtp_tls_security_level = may
|
||||
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# Network settings
|
||||
inet_interfaces = all
|
||||
inet_protocols = ipv4
|
||||
|
||||
# Relay settings (don't relay for others)
|
||||
relayhost =
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8
|
||||
|
||||
# Message size limit (10MB)
|
||||
message_size_limit = 10240000
|
||||
|
||||
# Queue settings
|
||||
maximal_queue_lifetime = 5d
|
||||
bounce_queue_lifetime = 5d
|
||||
|
||||
# Security settings
|
||||
smtpd_helo_required = yes
|
||||
disable_vrfy_command = yes
|
||||
|
||||
smtpd_helo_restrictions =
|
||||
permit_mynetworks,
|
||||
reject_invalid_helo_hostname,
|
||||
reject_non_fqdn_helo_hostname,
|
||||
permit
|
||||
|
||||
smtpd_recipient_restrictions =
|
||||
permit_mynetworks,
|
||||
reject_unauth_destination,
|
||||
permit
|
||||
|
||||
# OpenDKIM integration
|
||||
milter_default_action = accept
|
||||
milter_protocol = 6
|
||||
smtpd_milters = inet:localhost:8891
|
||||
non_smtpd_milters = inet:localhost:8891
|
||||
|
||||
# Notify on bounces
|
||||
notify_classes = bounce, delay, resource, software
|
||||
1465
package-lock.json
generated
@@ -26,14 +26,12 @@
|
||||
"@prisma/client": "^5.6.0",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@vercel/analytics": "^1.1.1",
|
||||
"axios": "^1.12.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"isomorphic-dompurify": "^2.15.0",
|
||||
"lucide-react": "^0.460.0",
|
||||
"next": "^15.5.9",
|
||||
"nodemailer": "^7.0.12",
|
||||
"openai": "^4.77.0",
|
||||
"postcss-nesting": "^12.0.2",
|
||||
"react": "^18",
|
||||
@@ -47,7 +45,6 @@
|
||||
"@commitlint/cli": "^18.4.3",
|
||||
"@commitlint/config-conventional": "^18.4.3",
|
||||
"@types/node": "^20",
|
||||
"@types/nodemailer": "^7.0.5",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "email_logs" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"recipient" TEXT NOT NULL,
|
||||
"subject" TEXT,
|
||||
"message_id" TEXT,
|
||||
"status" TEXT NOT NULL,
|
||||
"sent_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"error_message" TEXT,
|
||||
"bounce_type" TEXT,
|
||||
"bounce_details" JSONB,
|
||||
|
||||
CONSTRAINT "email_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "email_logs_recipient_idx" ON "email_logs"("recipient");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "email_logs_status_idx" ON "email_logs"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "email_logs_sent_at_idx" ON "email_logs"("sent_at");
|
||||
@@ -32,20 +32,3 @@ model News {
|
||||
|
||||
@@map(name: "news")
|
||||
}
|
||||
|
||||
model EmailLog {
|
||||
id Int @id @default(autoincrement())
|
||||
recipient String
|
||||
subject String?
|
||||
messageId String? @map("message_id")
|
||||
status String // 'sent', 'failed', 'bounced'
|
||||
sentAt DateTime @default(now()) @map("sent_at")
|
||||
errorMessage String? @map("error_message")
|
||||
bounceType String? @map("bounce_type")
|
||||
bounceDetails Json? @map("bounce_details")
|
||||
|
||||
@@index([recipient])
|
||||
@@index([status])
|
||||
@@index([sentAt])
|
||||
@@map(name: "email_logs")
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 397 B |
|
Before Width: | Height: | Size: 416 B |
|
Before Width: | Height: | Size: 305 B |
|
Before Width: | Height: | Size: 328 B |
|
Before Width: | Height: | Size: 414 B |
|
Before Width: | Height: | Size: 480 B |
|
Before Width: | Height: | Size: 394 B |
213
utils/mailer.ts
@@ -1,213 +0,0 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
import prisma from '@prisma/prisma';
|
||||
|
||||
interface EmailTemplate {
|
||||
subject: string;
|
||||
template: JSX.Element;
|
||||
}
|
||||
|
||||
interface SendResult {
|
||||
success: boolean;
|
||||
messageId?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// Create nodemailer transporter for Postfix container
|
||||
const createTransporter = () => {
|
||||
// Default to 'postfix' for Docker networking (service name in docker-compose)
|
||||
// Override with EMAIL_HOST for different setups
|
||||
const host = process.env.EMAIL_HOST || 'postfix';
|
||||
const port = parseInt(process.env.EMAIL_PORT || '25', 10);
|
||||
|
||||
return nodemailer.createTransport({
|
||||
host,
|
||||
port,
|
||||
secure: false, // true for 465, false for other ports
|
||||
tls: {
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
// Connection pooling for better performance
|
||||
pool: true,
|
||||
maxConnections: 5,
|
||||
maxMessages: 100
|
||||
});
|
||||
};
|
||||
|
||||
// Render React component to HTML string using dynamic import
|
||||
const renderTemplate = async (template: JSX.Element): Promise<string> => {
|
||||
// Dynamic import to avoid Next.js bundling issues with react-dom/server
|
||||
const { renderToStaticMarkup } = await import('react-dom/server');
|
||||
const html = renderToStaticMarkup(template);
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; background-color: #f4f4f5;">
|
||||
${html}
|
||||
</body>
|
||||
</html>`;
|
||||
};
|
||||
|
||||
// Generate plain text version from HTML (basic extraction)
|
||||
const htmlToPlainText = (html: string): string => {
|
||||
return html
|
||||
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
|
||||
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
||||
.replace(/<[^>]+>/g, '')
|
||||
.replace(/ /g, ' ')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
};
|
||||
|
||||
// Log email send attempt to database
|
||||
const logEmailSend = async (
|
||||
recipient: string,
|
||||
subject: string,
|
||||
status: 'sent' | 'failed',
|
||||
messageId?: string,
|
||||
errorMessage?: string
|
||||
) => {
|
||||
try {
|
||||
await prisma.emailLog.create({
|
||||
data: {
|
||||
recipient,
|
||||
subject,
|
||||
status,
|
||||
messageId,
|
||||
errorMessage
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to log email send:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Send a single email
|
||||
const sendSingleEmail = async (
|
||||
transporter: nodemailer.Transporter,
|
||||
recipient: string,
|
||||
subject: string,
|
||||
htmlContent: string,
|
||||
textContent: string
|
||||
): Promise<SendResult> => {
|
||||
const fromAddress = process.env.EMAIL_FROM || process.env.RESEND_FROM;
|
||||
const fromName = process.env.NEXT_PUBLIC_BRAND_NAME || 'HackerNews Newsletter';
|
||||
|
||||
try {
|
||||
const info = await transporter.sendMail({
|
||||
from: `"${fromName}" <${fromAddress}>`,
|
||||
to: recipient,
|
||||
subject,
|
||||
text: textContent,
|
||||
html: htmlContent,
|
||||
headers: {
|
||||
'List-Unsubscribe': `<${process.env.HOME_URL}/unsubscribe>`,
|
||||
'X-Newsletter-ID': `hackernews-${Date.now()}`
|
||||
}
|
||||
});
|
||||
|
||||
await logEmailSend(recipient, subject, 'sent', info.messageId);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
messageId: info.messageId
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
await logEmailSend(recipient, subject, 'failed', undefined, errorMessage);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMessage
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Main sender function - maintains same API as Resend version
|
||||
export async function sender(
|
||||
recipients: string[],
|
||||
{ subject, template }: EmailTemplate
|
||||
): Promise<boolean> {
|
||||
const fromAddress = process.env.EMAIL_FROM || process.env.RESEND_FROM;
|
||||
|
||||
if (!fromAddress) {
|
||||
throw new Error('EMAIL_FROM or RESEND_FROM environment variable is not set');
|
||||
}
|
||||
|
||||
if (recipients.length === 0) {
|
||||
console.info(`${subject} email skipped for having zero recipients`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const transporter = createTransporter();
|
||||
|
||||
// Render template to HTML
|
||||
const htmlContent = await renderTemplate(template);
|
||||
const textContent = htmlToPlainText(htmlContent);
|
||||
|
||||
// Add small delay between sends to avoid overwhelming mail server
|
||||
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
const errors: Array<{ email: string; error: string }> = [];
|
||||
|
||||
for (const recipient of recipients) {
|
||||
const result = await sendSingleEmail(
|
||||
transporter,
|
||||
recipient,
|
||||
subject,
|
||||
htmlContent,
|
||||
textContent
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
errors.push({ email: recipient, error: result.error || 'Unknown error' });
|
||||
}
|
||||
|
||||
// Add 100ms delay between sends
|
||||
if (recipients.length > 1) {
|
||||
await delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the transporter pool
|
||||
transporter.close();
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.error('Email send errors:', errors);
|
||||
}
|
||||
|
||||
console.info(
|
||||
`${subject} email: ${successCount} sent, ${failCount} failed out of ${recipients.length} recipients`
|
||||
);
|
||||
|
||||
// Return true if at least one email was sent successfully
|
||||
return successCount > 0;
|
||||
}
|
||||
|
||||
// Verify transporter connection (useful for health checks)
|
||||
export async function verifyMailer(): Promise<boolean> {
|
||||
const transporter = createTransporter();
|
||||
|
||||
try {
|
||||
await transporter.verify();
|
||||
console.log('Email server connection verified');
|
||||
transporter.close();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Email server connection failed:', error);
|
||||
transporter.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
90
utils/sweego.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
interface EmailTemplate {
|
||||
subject: string;
|
||||
template: JSX.Element;
|
||||
}
|
||||
|
||||
const SWEEGO_API_URL = 'https://api.sweego.io/send';
|
||||
|
||||
const renderTemplate = async (template: JSX.Element): Promise<string> => {
|
||||
const { renderToStaticMarkup } = await import('react-dom/server');
|
||||
const html = renderToStaticMarkup(template);
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; background-color: #f4f4f5;">
|
||||
${html}
|
||||
</body>
|
||||
</html>`;
|
||||
};
|
||||
|
||||
export async function sender(
|
||||
recipients: string[],
|
||||
{ subject, template }: EmailTemplate
|
||||
): Promise<boolean> {
|
||||
if (!process.env.SWEEGO_API_KEY) {
|
||||
throw new Error('SWEEGO_API_KEY is not set');
|
||||
}
|
||||
if (!process.env.SWEEGO_FROM) {
|
||||
throw new Error('SWEEGO_FROM is not set');
|
||||
}
|
||||
|
||||
if (recipients.length === 0) {
|
||||
console.info(`${subject} email skipped for having zero recipients`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const htmlContent = await renderTemplate(template);
|
||||
const fromName = process.env.NEXT_PUBLIC_BRAND_NAME || 'Newsletter';
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
|
||||
for (const recipient of recipients) {
|
||||
try {
|
||||
const response = await fetch(SWEEGO_API_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Api-Key': process.env.SWEEGO_API_KEY
|
||||
},
|
||||
body: JSON.stringify({
|
||||
channel: 'email',
|
||||
provider: 'sweego',
|
||||
recipients: [{ email: recipient }],
|
||||
from: {
|
||||
name: fromName,
|
||||
email: process.env.SWEEGO_FROM
|
||||
},
|
||||
subject,
|
||||
'message-html': htmlContent,
|
||||
headers: {
|
||||
'List-Unsubscribe': `<mailto:${process.env.NEXT_PUBLIC_BRAND_EMAIL}>`
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
console.error(
|
||||
`Failed to send to ${recipient}: ${response.status} ${error}`
|
||||
);
|
||||
failCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
successCount++;
|
||||
} catch (error) {
|
||||
console.error(`Failed to send to ${recipient}:`, error);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.info(
|
||||
`${subject} email: ${successCount} sent, ${failCount} failed out of ${recipients.length} recipients`
|
||||
);
|
||||
|
||||
return successCount > 0;
|
||||
}
|
||||
920
yarn.lock
@@ -34,482 +34,6 @@
|
||||
resolved "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz"
|
||||
integrity sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==
|
||||
|
||||
"@aws-crypto/sha256-browser@5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz"
|
||||
integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-js" "^5.2.0"
|
||||
"@aws-crypto/supports-web-crypto" "^5.2.0"
|
||||
"@aws-crypto/util" "^5.2.0"
|
||||
"@aws-sdk/types" "^3.222.0"
|
||||
"@aws-sdk/util-locate-window" "^3.0.0"
|
||||
"@smithy/util-utf8" "^2.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-crypto/sha256-js@^5.2.0", "@aws-crypto/sha256-js@5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz"
|
||||
integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==
|
||||
dependencies:
|
||||
"@aws-crypto/util" "^5.2.0"
|
||||
"@aws-sdk/types" "^3.222.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-crypto/supports-web-crypto@^5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz"
|
||||
integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-crypto/util@^5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz"
|
||||
integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "^3.222.0"
|
||||
"@smithy/util-utf8" "^2.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/client-sesv2@^3.839.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.971.0.tgz"
|
||||
integrity sha512-NP/lbf3mfY10Txzl0ml2YnTjnZwflp1+faOotMCrXi4fb6kInosdW0ZSHXNlNulFo9cW+llq07lD59Sw3nny+A==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/credential-provider-node" "3.971.0"
|
||||
"@aws-sdk/middleware-host-header" "3.969.0"
|
||||
"@aws-sdk/middleware-logger" "3.969.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.969.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.970.0"
|
||||
"@aws-sdk/region-config-resolver" "3.969.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/util-endpoints" "3.970.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.969.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.971.0"
|
||||
"@smithy/config-resolver" "^4.4.6"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/fetch-http-handler" "^5.3.9"
|
||||
"@smithy/hash-node" "^4.2.8"
|
||||
"@smithy/invalid-dependency" "^4.2.8"
|
||||
"@smithy/middleware-content-length" "^4.2.8"
|
||||
"@smithy/middleware-endpoint" "^4.4.7"
|
||||
"@smithy/middleware-retry" "^4.4.23"
|
||||
"@smithy/middleware-serde" "^4.2.9"
|
||||
"@smithy/middleware-stack" "^4.2.8"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/node-http-handler" "^4.4.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-body-length-browser" "^4.2.0"
|
||||
"@smithy/util-body-length-node" "^4.2.1"
|
||||
"@smithy/util-defaults-mode-browser" "^4.3.22"
|
||||
"@smithy/util-defaults-mode-node" "^4.2.25"
|
||||
"@smithy/util-endpoints" "^3.2.8"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-retry" "^4.2.8"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/client-sso@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.971.0.tgz"
|
||||
integrity sha512-Xx+w6DQqJxDdymYyIxyKJnRzPvVJ4e/Aw0czO7aC9L/iraaV7AG8QtRe93OGW6aoHSh72CIiinnpJJfLsQqP4g==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/middleware-host-header" "3.969.0"
|
||||
"@aws-sdk/middleware-logger" "3.969.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.969.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.970.0"
|
||||
"@aws-sdk/region-config-resolver" "3.969.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/util-endpoints" "3.970.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.969.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.971.0"
|
||||
"@smithy/config-resolver" "^4.4.6"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/fetch-http-handler" "^5.3.9"
|
||||
"@smithy/hash-node" "^4.2.8"
|
||||
"@smithy/invalid-dependency" "^4.2.8"
|
||||
"@smithy/middleware-content-length" "^4.2.8"
|
||||
"@smithy/middleware-endpoint" "^4.4.7"
|
||||
"@smithy/middleware-retry" "^4.4.23"
|
||||
"@smithy/middleware-serde" "^4.2.9"
|
||||
"@smithy/middleware-stack" "^4.2.8"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/node-http-handler" "^4.4.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-body-length-browser" "^4.2.0"
|
||||
"@smithy/util-body-length-node" "^4.2.1"
|
||||
"@smithy/util-defaults-mode-browser" "^4.3.22"
|
||||
"@smithy/util-defaults-mode-node" "^4.2.25"
|
||||
"@smithy/util-endpoints" "^3.2.8"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-retry" "^4.2.8"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/core@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/core/-/core-3.970.0.tgz"
|
||||
integrity sha512-klpzObldOq8HXzDjDlY6K8rMhYZU6mXRz6P9F9N+tWnjoYFfeBMra8wYApydElTUYQKP1O7RLHwH1OKFfKcqIA==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/xml-builder" "3.969.0"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/signature-v4" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-env@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.970.0.tgz"
|
||||
integrity sha512-rtVzXzEtAfZBfh+lq3DAvRar4c3jyptweOAJR2DweyXx71QSMY+O879hjpMwES7jl07a3O1zlnFIDo4KP/96kQ==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-http@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.970.0.tgz"
|
||||
integrity sha512-CjDbWL7JxjLc9ZxQilMusWSw05yRvUJKRpz59IxDpWUnSMHC9JMMUUkOy5Izk8UAtzi6gupRWArp4NG4labt9Q==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/fetch-http-handler" "^5.3.9"
|
||||
"@smithy/node-http-handler" "^4.4.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-stream" "^4.5.10"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-ini@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.971.0.tgz"
|
||||
integrity sha512-c0TGJG4xyfTZz3SInXfGU8i5iOFRrLmy4Bo7lMyH+IpngohYMYGYl61omXqf2zdwMbDv+YJ9AviQTcCaEUKi8w==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/credential-provider-env" "3.970.0"
|
||||
"@aws-sdk/credential-provider-http" "3.970.0"
|
||||
"@aws-sdk/credential-provider-login" "3.971.0"
|
||||
"@aws-sdk/credential-provider-process" "3.970.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.971.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.971.0"
|
||||
"@aws-sdk/nested-clients" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/credential-provider-imds" "^4.2.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-login@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.971.0.tgz"
|
||||
integrity sha512-yhbzmDOsk0RXD3rTPhZra4AWVnVAC4nFWbTp+sUty1hrOPurUmhuz8bjpLqYTHGnlMbJp+UqkQONhS2+2LzW2g==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/nested-clients" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-node@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.971.0.tgz"
|
||||
integrity sha512-epUJBAKivtJqalnEBRsYIULKYV063o/5mXNJshZfyvkAgNIzc27CmmKRXTN4zaNOZg8g/UprFp25BGsi19x3nQ==
|
||||
dependencies:
|
||||
"@aws-sdk/credential-provider-env" "3.970.0"
|
||||
"@aws-sdk/credential-provider-http" "3.970.0"
|
||||
"@aws-sdk/credential-provider-ini" "3.971.0"
|
||||
"@aws-sdk/credential-provider-process" "3.970.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.971.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/credential-provider-imds" "^4.2.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-process@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.970.0.tgz"
|
||||
integrity sha512-0XeT8OaT9iMA62DFV9+m6mZfJhrD0WNKf4IvsIpj2Z7XbaYfz3CoDDvNoALf3rPY9NzyMHgDxOspmqdvXP00mw==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-sso@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.971.0.tgz"
|
||||
integrity sha512-dY0hMQ7dLVPQNJ8GyqXADxa9w5wNfmukgQniLxGVn+dMRx3YLViMp5ZpTSQpFhCWNF0oKQrYAI5cHhUJU1hETw==
|
||||
dependencies:
|
||||
"@aws-sdk/client-sso" "3.971.0"
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/token-providers" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.971.0.tgz"
|
||||
integrity sha512-F1AwfNLr7H52T640LNON/h34YDiMuIqW/ZreGzhRR6vnFGaSPtNSKAKB2ssAMkLM8EVg8MjEAYD3NCUiEo+t/w==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/nested-clients" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-host-header@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.969.0.tgz"
|
||||
integrity sha512-AWa4rVsAfBR4xqm7pybQ8sUNJYnjyP/bJjfAw34qPuh3M9XrfGbAHG0aiAfQGrBnmS28jlO6Kz69o+c6PRw1dw==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-logger@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.969.0.tgz"
|
||||
integrity sha512-xwrxfip7Y2iTtCMJ+iifN1E1XMOuhxIHY9DreMCvgdl4r7+48x2S1bCYPWH3eNY85/7CapBWdJ8cerpEl12sQQ==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.969.0.tgz"
|
||||
integrity sha512-2r3PuNquU3CcS1Am4vn/KHFwLi8QFjMdA/R+CRDXT4AFO/0qxevF/YStW3gAKntQIgWgQV8ZdEtKAoJvLI4UWg==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws/lambda-invoke-store" "^0.2.2"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-sdk-s3@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.970.0.tgz"
|
||||
integrity sha512-v/Y5F1lbFFY7vMeG5yYxuhnn0CAshz6KMxkz1pDyPxejNE9HtA0w8R6OTBh/bVdIm44QpjhbI7qeLdOE/PLzXQ==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/util-arn-parser" "3.968.0"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/signature-v4" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-config-provider" "^4.2.0"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-stream" "^4.5.10"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-user-agent@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.970.0.tgz"
|
||||
integrity sha512-dnSJGGUGSFGEX2NzvjwSefH+hmZQ347AwbLhAsi0cdnISSge+pcGfOFrJt2XfBIypwFe27chQhlfuf/gWdzpZg==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/util-endpoints" "3.970.0"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/nested-clients@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.971.0.tgz"
|
||||
integrity sha512-TWaILL8GyYlhGrxxnmbkazM4QsXatwQgoWUvo251FXmUOsiXDFDVX3hoGIfB3CaJhV2pJPfebHUNJtY6TjZ11g==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/middleware-host-header" "3.969.0"
|
||||
"@aws-sdk/middleware-logger" "3.969.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.969.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.970.0"
|
||||
"@aws-sdk/region-config-resolver" "3.969.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@aws-sdk/util-endpoints" "3.970.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.969.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.971.0"
|
||||
"@smithy/config-resolver" "^4.4.6"
|
||||
"@smithy/core" "^3.20.6"
|
||||
"@smithy/fetch-http-handler" "^5.3.9"
|
||||
"@smithy/hash-node" "^4.2.8"
|
||||
"@smithy/invalid-dependency" "^4.2.8"
|
||||
"@smithy/middleware-content-length" "^4.2.8"
|
||||
"@smithy/middleware-endpoint" "^4.4.7"
|
||||
"@smithy/middleware-retry" "^4.4.23"
|
||||
"@smithy/middleware-serde" "^4.2.9"
|
||||
"@smithy/middleware-stack" "^4.2.8"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/node-http-handler" "^4.4.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/smithy-client" "^4.10.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-body-length-browser" "^4.2.0"
|
||||
"@smithy/util-body-length-node" "^4.2.1"
|
||||
"@smithy/util-defaults-mode-browser" "^4.3.22"
|
||||
"@smithy/util-defaults-mode-node" "^4.2.25"
|
||||
"@smithy/util-endpoints" "^3.2.8"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-retry" "^4.2.8"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/region-config-resolver@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.969.0.tgz"
|
||||
integrity sha512-scj9OXqKpcjJ4jsFLtqYWz3IaNvNOQTFFvEY8XMJXTv+3qF5I7/x9SJtKzTRJEBF3spjzBUYPtGFbs9sj4fisQ==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/config-resolver" "^4.4.6"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.970.0.tgz"
|
||||
integrity sha512-z3syXfuK/x/IsKf/AeYmgc2NT7fcJ+3fHaGO+fkghkV9WEba3fPyOwtTBX4KpFMNb2t50zDGZwbzW1/5ighcUQ==
|
||||
dependencies:
|
||||
"@aws-sdk/middleware-sdk-s3" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/signature-v4" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/token-providers@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.971.0.tgz"
|
||||
integrity sha512-4hKGWZbmuDdONMJV0HJ+9jwTDb0zLfKxcCLx2GEnBY31Gt9GeyIQ+DZ97Bb++0voawj6pnZToFikXTyrEq2x+w==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.970.0"
|
||||
"@aws-sdk/nested-clients" "3.971.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/types@^3.222.0", "@aws-sdk/types@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.969.0.tgz"
|
||||
integrity sha512-7IIzM5TdiXn+VtgPdVLjmE6uUBUtnga0f4RiSEI1WW10RPuNvZ9U+pL3SwDiRDAdoGrOF9tSLJOFZmfuwYuVYQ==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-arn-parser@3.968.0":
|
||||
version "3.968.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.968.0.tgz"
|
||||
integrity sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-endpoints@3.970.0":
|
||||
version "3.970.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.970.0.tgz"
|
||||
integrity sha512-TZNZqFcMUtjvhZoZRtpEGQAdULYiy6rcGiXAbLU7e9LSpIYlRqpLa207oMNfgbzlL2PnHko+eVg8rajDiSOYCg==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
"@smithy/util-endpoints" "^3.2.8"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-locate-window@^3.0.0":
|
||||
version "3.965.2"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.2.tgz"
|
||||
integrity sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-user-agent-browser@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.969.0.tgz"
|
||||
integrity sha512-bpJGjuKmFr0rA6UKUCmN8D19HQFMLXMx5hKBXqBlPFdalMhxJSjcxzX9DbQh0Fn6bJtxCguFmRGOBdQqNOt49g==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/types" "^4.12.0"
|
||||
bowser "^2.11.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-user-agent-node@3.971.0":
|
||||
version "3.971.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.971.0.tgz"
|
||||
integrity sha512-Eygjo9mFzQYjbGY3MYO6CsIhnTwAMd3WmuFalCykqEmj2r5zf0leWrhPaqvA5P68V5JdGfPYgj7vhNOd6CtRBQ==
|
||||
dependencies:
|
||||
"@aws-sdk/middleware-user-agent" "3.970.0"
|
||||
"@aws-sdk/types" "3.969.0"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/xml-builder@3.969.0":
|
||||
version "3.969.0"
|
||||
resolved "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.969.0.tgz"
|
||||
integrity sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
fast-xml-parser "5.2.5"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws/lambda-invoke-store@^0.2.2":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.3.tgz"
|
||||
integrity sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz"
|
||||
@@ -1162,409 +686,6 @@
|
||||
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.13.0.tgz"
|
||||
integrity sha512-2ih5qGw5SZJ+2fLZxP6Lr6Na2NTIgPRL/7Kmyuw0uIyBQnuhQ8fi8fzUTd38eIQmqp+GYLC00cI6WgtqHxBwmw==
|
||||
|
||||
"@smithy/abort-controller@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.8.tgz"
|
||||
integrity sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/config-resolver@^4.4.6":
|
||||
version "4.4.6"
|
||||
resolved "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.6.tgz"
|
||||
integrity sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==
|
||||
dependencies:
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-config-provider" "^4.2.0"
|
||||
"@smithy/util-endpoints" "^3.2.8"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/core@^3.20.6", "@smithy/core@^3.20.8":
|
||||
version "3.20.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/core/-/core-3.20.8.tgz"
|
||||
integrity sha512-ZBOJENmvM/IrKbxUxRVavCcVCjD5VcPI1MbOURjj3jZgV/t7UaBF8Z+lLSEzoQHH7Lq/efmOhBpV5xCfPjNRZw==
|
||||
dependencies:
|
||||
"@smithy/middleware-serde" "^4.2.9"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-body-length-browser" "^4.2.0"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-stream" "^4.5.10"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
"@smithy/uuid" "^1.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/credential-provider-imds@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.8.tgz"
|
||||
integrity sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==
|
||||
dependencies:
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/fetch-http-handler@^5.3.9":
|
||||
version "5.3.9"
|
||||
resolved "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.9.tgz"
|
||||
integrity sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==
|
||||
dependencies:
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/querystring-builder" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/hash-node@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.8.tgz"
|
||||
integrity sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-buffer-from" "^4.2.0"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/invalid-dependency@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.8.tgz"
|
||||
integrity sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/is-array-buffer@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz"
|
||||
integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/is-array-buffer@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz"
|
||||
integrity sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/middleware-content-length@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.8.tgz"
|
||||
integrity sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==
|
||||
dependencies:
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/middleware-endpoint@^4.4.7", "@smithy/middleware-endpoint@^4.4.9":
|
||||
version "4.4.9"
|
||||
resolved "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.9.tgz"
|
||||
integrity sha512-+2Rxc3zzIT8BhclKEyj/ZzbOh95c55qjKA4XKx5eIGEEGPb4qFwYrNk2NZ1AGuRY71dxmpy4mar+GwurMOLT0w==
|
||||
dependencies:
|
||||
"@smithy/core" "^3.20.8"
|
||||
"@smithy/middleware-serde" "^4.2.9"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/url-parser" "^4.2.8"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/middleware-retry@^4.4.23":
|
||||
version "4.4.25"
|
||||
resolved "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.25.tgz"
|
||||
integrity sha512-NZMnOw4jeNZ4O/bbqUWaLiK3xSpLzIq0QNJhxHZGvtLoywnKPnNJRCfyOE5w82tK3n2L3ZMIC5VtSVW6WvDBkQ==
|
||||
dependencies:
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/service-error-classification" "^4.2.8"
|
||||
"@smithy/smithy-client" "^4.10.10"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-retry" "^4.2.8"
|
||||
"@smithy/uuid" "^1.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/middleware-serde@^4.2.9":
|
||||
version "4.2.9"
|
||||
resolved "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.9.tgz"
|
||||
integrity sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==
|
||||
dependencies:
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/middleware-stack@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.8.tgz"
|
||||
integrity sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/node-config-provider@^4.3.8":
|
||||
version "4.3.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.8.tgz"
|
||||
integrity sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==
|
||||
dependencies:
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/shared-ini-file-loader" "^4.4.3"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/node-http-handler@^4.4.8":
|
||||
version "4.4.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.8.tgz"
|
||||
integrity sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==
|
||||
dependencies:
|
||||
"@smithy/abort-controller" "^4.2.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/querystring-builder" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/property-provider@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.8.tgz"
|
||||
integrity sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/protocol-http@^5.3.8":
|
||||
version "5.3.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.8.tgz"
|
||||
integrity sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/querystring-builder@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.8.tgz"
|
||||
integrity sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-uri-escape" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/querystring-parser@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.8.tgz"
|
||||
integrity sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/service-error-classification@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.8.tgz"
|
||||
integrity sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
|
||||
"@smithy/shared-ini-file-loader@^4.4.3":
|
||||
version "4.4.3"
|
||||
resolved "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.3.tgz"
|
||||
integrity sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/signature-v4@^5.3.8":
|
||||
version "5.3.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.8.tgz"
|
||||
integrity sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==
|
||||
dependencies:
|
||||
"@smithy/is-array-buffer" "^4.2.0"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-hex-encoding" "^4.2.0"
|
||||
"@smithy/util-middleware" "^4.2.8"
|
||||
"@smithy/util-uri-escape" "^4.2.0"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/smithy-client@^4.10.10", "@smithy/smithy-client@^4.10.8":
|
||||
version "4.10.10"
|
||||
resolved "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.10.tgz"
|
||||
integrity sha512-yMT5cB4RdT3x+Etgc99aY/b4jmi++Bmwl7BtLAko+ma7zYZlSiFxbo58XgXouyrP8hDk2/peg55O3AyOm4GtEw==
|
||||
dependencies:
|
||||
"@smithy/core" "^3.20.8"
|
||||
"@smithy/middleware-endpoint" "^4.4.9"
|
||||
"@smithy/middleware-stack" "^4.2.8"
|
||||
"@smithy/protocol-http" "^5.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-stream" "^4.5.10"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/types@^4.12.0":
|
||||
version "4.12.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/types/-/types-4.12.0.tgz"
|
||||
integrity sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/url-parser@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.8.tgz"
|
||||
integrity sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==
|
||||
dependencies:
|
||||
"@smithy/querystring-parser" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-base64@^4.3.0":
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz"
|
||||
integrity sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==
|
||||
dependencies:
|
||||
"@smithy/util-buffer-from" "^4.2.0"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-body-length-browser@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz"
|
||||
integrity sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-body-length-node@^4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz"
|
||||
integrity sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-buffer-from@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz"
|
||||
integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==
|
||||
dependencies:
|
||||
"@smithy/is-array-buffer" "^2.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-buffer-from@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz"
|
||||
integrity sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==
|
||||
dependencies:
|
||||
"@smithy/is-array-buffer" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-config-provider@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz"
|
||||
integrity sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-defaults-mode-browser@^4.3.22":
|
||||
version "4.3.24"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.24.tgz"
|
||||
integrity sha512-k2GUY1hGk5JfrlYh7O0PgrS5//IFqbQ3nAldQYfiam+J82h6wmuPkagF+kgF6ldKGHvi7iFpyCb4yXm+P5QD0Q==
|
||||
dependencies:
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/smithy-client" "^4.10.10"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-defaults-mode-node@^4.2.25":
|
||||
version "4.2.27"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.27.tgz"
|
||||
integrity sha512-Pam2VH8BSfd9uITrepxYq8QcJKmXVBCq/KCO/3Af/f5zugVioih2rWfTi0+hRzF75DhjgNnwfwdGebItQdO9Mw==
|
||||
dependencies:
|
||||
"@smithy/config-resolver" "^4.4.6"
|
||||
"@smithy/credential-provider-imds" "^4.2.8"
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/property-provider" "^4.2.8"
|
||||
"@smithy/smithy-client" "^4.10.10"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-endpoints@^3.2.8":
|
||||
version "3.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.8.tgz"
|
||||
integrity sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==
|
||||
dependencies:
|
||||
"@smithy/node-config-provider" "^4.3.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-hex-encoding@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz"
|
||||
integrity sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-middleware@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.8.tgz"
|
||||
integrity sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==
|
||||
dependencies:
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-retry@^4.2.8":
|
||||
version "4.2.8"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.8.tgz"
|
||||
integrity sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==
|
||||
dependencies:
|
||||
"@smithy/service-error-classification" "^4.2.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-stream@^4.5.10":
|
||||
version "4.5.10"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.10.tgz"
|
||||
integrity sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==
|
||||
dependencies:
|
||||
"@smithy/fetch-http-handler" "^5.3.9"
|
||||
"@smithy/node-http-handler" "^4.4.8"
|
||||
"@smithy/types" "^4.12.0"
|
||||
"@smithy/util-base64" "^4.3.0"
|
||||
"@smithy/util-buffer-from" "^4.2.0"
|
||||
"@smithy/util-hex-encoding" "^4.2.0"
|
||||
"@smithy/util-utf8" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-uri-escape@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz"
|
||||
integrity sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-utf8@^2.0.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz"
|
||||
integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==
|
||||
dependencies:
|
||||
"@smithy/util-buffer-from" "^2.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/util-utf8@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz"
|
||||
integrity sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==
|
||||
dependencies:
|
||||
"@smithy/util-buffer-from" "^4.2.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@smithy/uuid@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz"
|
||||
integrity sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==
|
||||
dependencies:
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@swc/helpers@0.5.15":
|
||||
version "0.5.15"
|
||||
resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz"
|
||||
@@ -1616,14 +737,6 @@
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/nodemailer@^7.0.5":
|
||||
version "7.0.5"
|
||||
resolved "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.5.tgz"
|
||||
integrity sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA==
|
||||
dependencies:
|
||||
"@aws-sdk/client-sesv2" "^3.839.0"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.4"
|
||||
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz"
|
||||
@@ -1845,11 +958,6 @@
|
||||
resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz"
|
||||
integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==
|
||||
|
||||
"@vercel/analytics@^1.1.1":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.5.0.tgz"
|
||||
integrity sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz"
|
||||
@@ -2168,11 +1276,6 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
||||
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
||||
|
||||
bowser@^2.11.0:
|
||||
version "2.13.1"
|
||||
resolved "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz"
|
||||
integrity sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.12"
|
||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz"
|
||||
@@ -3108,13 +2211,6 @@ fast-uri@^3.0.1:
|
||||
resolved "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz"
|
||||
integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==
|
||||
|
||||
fast-xml-parser@5.2.5:
|
||||
version "5.2.5"
|
||||
resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz"
|
||||
integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==
|
||||
dependencies:
|
||||
strnum "^2.1.0"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz"
|
||||
@@ -4363,7 +3459,7 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
next@^15.5.9, "next@>= 13":
|
||||
next@^15.5.9:
|
||||
version "15.5.9"
|
||||
resolved "https://registry.npmjs.org/next/-/next-15.5.9.tgz"
|
||||
integrity sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==
|
||||
@@ -4401,11 +3497,6 @@ node-releases@^2.0.21:
|
||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz"
|
||||
integrity sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==
|
||||
|
||||
nodemailer@^7.0.12:
|
||||
version "7.0.12"
|
||||
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.12.tgz"
|
||||
integrity sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA==
|
||||
|
||||
normalize-package-data@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz"
|
||||
@@ -4871,7 +3962,7 @@ react-is@^16.13.1:
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", react@^18, "react@^18 || ^19 || ^19.0.0-rc", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^18.3.1, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0":
|
||||
"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", react@^18, "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^18.3.1, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0":
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||
@@ -5536,11 +4627,6 @@ strip-json-comments@^3.1.1:
|
||||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
strnum@^2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz"
|
||||
integrity sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==
|
||||
|
||||
styled-jsx@5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz"
|
||||
@@ -5728,7 +4814,7 @@ tsconfig-paths@^3.15.0:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^2.4.0, tslib@^2.6.2, tslib@^2.8.0:
|
||||
tslib@^2.4.0, tslib@^2.8.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||