feat: SMTP server (#47)
* WIP: SMTP server * Card and minor changes in Server --------- Co-authored-by: KM Koushik <koushikmohan1996@gmail.com>
This commit is contained in:
committed by
GitHub
parent
d74b20bac8
commit
0b82eb2266
28
apps/smtp-server/package.json
Normal file
28
apps/smtp-server/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "smtp-server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsc",
|
||||
"start": "node dist/server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/mailparser": "^3.4.4",
|
||||
"@types/smtp-server": "^3.5.10",
|
||||
"dotenv": "^16.4.5",
|
||||
"mailparser": "^3.7.1",
|
||||
"nodemailer": "^6.9.14",
|
||||
"smtp-server": "^3.13.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.1.0",
|
||||
"@types/nodemailer": "^6.4.15",
|
||||
"typescript": "^5.5.4"
|
||||
}
|
||||
}
|
101
apps/smtp-server/src/server.ts
Normal file
101
apps/smtp-server/src/server.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { SMTPServer, SMTPServerOptions } from 'smtp-server';
|
||||
import { Readable } from 'stream';
|
||||
import dotenv from 'dotenv';
|
||||
import { simpleParser } from 'mailparser';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const AUTH_USERNAME = process.env.SMTP_AUTH_USERNAME!;
|
||||
const UNSEND_BASE_URL = process.env.UNSEND_BASE_URL!;
|
||||
let API_KEY = '';
|
||||
|
||||
const ports = [25, 465, 2465, 587, 2587]; // Array of ports to listen on
|
||||
|
||||
const serverOptions: SMTPServerOptions = {
|
||||
onData(stream: Readable, session: any, callback: (error?: Error) => void) {
|
||||
console.log('Receiving email data...'); // Debug statement
|
||||
simpleParser(stream, (err, parsed) => {
|
||||
if (err) {
|
||||
console.error('Failed to parse email data:', err.message);
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
const emailObject: any = {
|
||||
to: Array.isArray(parsed.to) ? parsed.to.map(addr => addr.text).join(', ') : parsed.to?.text,
|
||||
from: Array.isArray(parsed.from) ? parsed.from.map(addr => addr.text).join(', ') : parsed.from?.text,
|
||||
subject: parsed.subject,
|
||||
text: parsed.text,
|
||||
html: parsed.html,
|
||||
};
|
||||
|
||||
console.log('Parsed email data:', emailObject); // Debug statement
|
||||
|
||||
sendEmailToUnsend(emailObject)
|
||||
.then(() => callback())
|
||||
.catch((error) => {
|
||||
console.error('Failed to send email:', error.message);
|
||||
callback(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
onAuth(auth: any, session: any, callback: (error?: Error, user?: any) => void) {
|
||||
API_KEY = auth.password;
|
||||
if (auth.username === AUTH_USERNAME) {
|
||||
console.log('Authenticated successfully'); // Debug statement
|
||||
callback(undefined, { user: AUTH_USERNAME });
|
||||
} else {
|
||||
console.error('Invalid username or password');
|
||||
callback(new Error('Invalid username or password'));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
async function sendEmailToUnsend(emailData: any) {
|
||||
try {
|
||||
const apiEndpoint = '/api/v1/emails';
|
||||
const url = new URL(apiEndpoint, UNSEND_BASE_URL); // Combine base URL with endpoint
|
||||
console.log('Sending email to Unsend API at:', url.href); // Debug statement
|
||||
|
||||
const response = await fetch(url.href, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(emailData),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
console.error('Unsend API error response:', errorData);
|
||||
throw new Error(`Failed to send email: ${errorData.message || 'Unknown error from server'}`);
|
||||
}
|
||||
|
||||
const responseData = await response.json();
|
||||
console.log('Unsend API response:', responseData);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.error('Error message:', error.message);
|
||||
throw new Error(`Failed to send email: ${error.message}`);
|
||||
} else {
|
||||
console.error('Unexpected error:', error);
|
||||
throw new Error('Failed to send email: Unexpected error occurred');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startServers() {
|
||||
ports.forEach(port => {
|
||||
const server = new SMTPServer(serverOptions);
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log(`SMTP server is listening on port ${port}`);
|
||||
});
|
||||
|
||||
server.on('error', (err) => {
|
||||
console.error(`Error occurred on port ${port}:`, err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
startServers();
|
37
apps/smtp-server/src/usage.js
Normal file
37
apps/smtp-server/src/usage.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const nodemailer = require('nodemailer');
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: "localhost",
|
||||
port: 2587,
|
||||
secure: false,
|
||||
auth: {
|
||||
user: "unsend",
|
||||
pass: "us_38de56vwa7_cc90a91b01a402de0c15516b3554adc1",
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
const mailOptions = {
|
||||
to: "harsh121102@gmail.com",
|
||||
from: "hello@support.harshbhat.me",
|
||||
subject: "Testing SMTP",
|
||||
html: "<strong>THIS IS USING SMTP,</strong><p>Unsend is the best open source sending platform<p><p>check out <a href='https://unsend.dev'>unsend.dev</a>",
|
||||
text: "hello,\n\nUnsend is the best open source sending platform",
|
||||
};
|
||||
|
||||
|
||||
transporter.sendMail(mailOptions, (error, info) => {
|
||||
if (error) {
|
||||
console.error('Error sending email:', error);
|
||||
} else {
|
||||
console.log('Email sent successfully:', info.response);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
24
apps/smtp-server/tsconfig.json
Normal file
24
apps/smtp-server/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Modules */
|
||||
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
||||
|
||||
/* Emit */
|
||||
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
"removeComments": true, /* Disable emitting comments. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": ["src/**/*.ts"], /* Include all TypeScript files in the src directory. */
|
||||
"exclude": ["node_modules"] /* Exclude node_modules from compilation. */
|
||||
}
|
@@ -2,15 +2,43 @@
|
||||
|
||||
import ApiList from "./api-list";
|
||||
import AddApiKey from "./add-api-key";
|
||||
import Smtp from "./smtp";
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@unsend/ui/src/tabs";
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
const [activeTab, setActiveTab] = useState("apiKeys");
|
||||
const disableSmtp = true;
|
||||
const handleTabChange = (value: any) => {
|
||||
if (value === "smtp" && disableSmtp) {
|
||||
return;
|
||||
}
|
||||
setActiveTab(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">API Keys</h1>
|
||||
<AddApiKey />
|
||||
</div>
|
||||
<ApiList />
|
||||
<Tabs defaultValue="apiKeys" value={activeTab} onValueChange={handleTabChange}>
|
||||
<TabsList>
|
||||
<TabsTrigger value="apiKeys">API keys</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="smtp"
|
||||
className={`cursor-pointer ${disableSmtp ? 'opacity-50 pointer-events-none' : ''}`}
|
||||
>
|
||||
SMTP
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="apiKeys">
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">API Keys</h1>
|
||||
<AddApiKey />
|
||||
</div>
|
||||
<ApiList />
|
||||
</TabsContent>
|
||||
<TabsContent value="smtp">
|
||||
<Smtp />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
54
apps/web/src/app/(dashboard)/api-keys/smtp.tsx
Normal file
54
apps/web/src/app/(dashboard)/api-keys/smtp.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
"use client";
|
||||
import * as React from "react";
|
||||
import { Code } from "@unsend/ui/src/code";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@unsend/ui/src/card";
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
|
||||
export default function ExampleCard() {
|
||||
const smtpDetails = {
|
||||
smtp: "smtp.example.com",
|
||||
port: "587",
|
||||
user: "user@example.com",
|
||||
password: "supersecretpassword"
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="mt-9">
|
||||
<CardHeader>
|
||||
<CardTitle>SMTP</CardTitle>
|
||||
<CardDescription>
|
||||
Send emails using SMTP instead of the REST API. See documentation for more information.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<strong>Host:</strong>
|
||||
<TextWithCopyButton className="ml-1 text-zinc-500 rounded-lg mt-1 p-2 w-full bg-gray-900" value={"smtp.unsend.dev"}></TextWithCopyButton>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Port:</strong>
|
||||
<TextWithCopyButton className="ml-1 text-zinc-500 rounded-lg mt-1 p-2 w-full bg-gray-900" value={"465"}></TextWithCopyButton>
|
||||
<p className="ml-1 mt-1 text-zinc-500 ">For encrypted/TLS connections use <strong>2465</strong>, <strong>587</strong> or <strong>2587</strong></p>
|
||||
</div>
|
||||
<div>
|
||||
<strong>User:</strong>
|
||||
<TextWithCopyButton className="ml-1 text-zinc-500 rounded-lg mt-1 p-2 w-full bg-gray-900" value={"unsend"}></TextWithCopyButton>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Password:</strong>
|
||||
<TextWithCopyButton className="ml-1 text-zinc-500 rounded-lg mt-1 p-2 w-full bg-gray-900" value={"YOUR_API_KEY"}></TextWithCopyButton>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
76
packages/ui/src/card.tsx
Normal file
76
packages/ui/src/card.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "../lib/utils"
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-xl border bg-card text-card-foreground shadow",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn("font-semibold leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
264
pnpm-lock.yaml
generated
264
pnpm-lock.yaml
generated
@@ -92,6 +92,40 @@ importers:
|
||||
specifier: ^5
|
||||
version: 5.4.2
|
||||
|
||||
apps/smtp-server:
|
||||
dependencies:
|
||||
'@types/dotenv':
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
'@types/mailparser':
|
||||
specifier: ^3.4.4
|
||||
version: 3.4.4
|
||||
'@types/smtp-server':
|
||||
specifier: ^3.5.10
|
||||
version: 3.5.10
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.4.5
|
||||
mailparser:
|
||||
specifier: ^3.7.1
|
||||
version: 3.7.1
|
||||
nodemailer:
|
||||
specifier: ^6.9.14
|
||||
version: 6.9.14
|
||||
smtp-server:
|
||||
specifier: ^3.13.4
|
||||
version: 3.13.4
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^22.1.0
|
||||
version: 22.1.0
|
||||
'@types/nodemailer':
|
||||
specifier: ^6.4.15
|
||||
version: 6.4.15
|
||||
typescript:
|
||||
specifier: ^5.5.4
|
||||
version: 5.5.4
|
||||
|
||||
apps/web:
|
||||
dependencies:
|
||||
'@auth/prisma-adapter':
|
||||
@@ -6360,7 +6394,7 @@ packages:
|
||||
/@types/cors@2.8.17:
|
||||
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
|
||||
dependencies:
|
||||
'@types/node': 20.11.27
|
||||
'@types/node': 20.12.12
|
||||
dev: true
|
||||
|
||||
/@types/d3-array@3.2.1:
|
||||
@@ -6411,6 +6445,13 @@ packages:
|
||||
'@types/ms': 0.7.34
|
||||
dev: true
|
||||
|
||||
/@types/dotenv@8.2.0:
|
||||
resolution: {integrity: sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==}
|
||||
deprecated: This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed.
|
||||
dependencies:
|
||||
dotenv: 16.4.5
|
||||
dev: false
|
||||
|
||||
/@types/eslint@8.56.5:
|
||||
resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==}
|
||||
dependencies:
|
||||
@@ -6461,6 +6502,13 @@ packages:
|
||||
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
|
||||
dev: true
|
||||
|
||||
/@types/mailparser@3.4.4:
|
||||
resolution: {integrity: sha512-C6Znp2QVS25JqtuPyxj38Qh+QoFcLycdxsvcc6IZCGekhaMBzbdTXzwGzhGoYb3TfKu8IRCNV0sV1o3Od97cEQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
iconv-lite: 0.6.3
|
||||
dev: false
|
||||
|
||||
/@types/mdast@3.0.15:
|
||||
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
|
||||
dependencies:
|
||||
@@ -6501,8 +6549,18 @@ packages:
|
||||
resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
/@types/node@22.1.0:
|
||||
resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==}
|
||||
dependencies:
|
||||
undici-types: 6.13.0
|
||||
dev: true
|
||||
|
||||
/@types/nodemailer@6.4.15:
|
||||
resolution: {integrity: sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
|
||||
/@types/normalize-package-data@2.4.4:
|
||||
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
|
||||
dev: true
|
||||
@@ -6559,6 +6617,13 @@ packages:
|
||||
resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==}
|
||||
dev: true
|
||||
|
||||
/@types/smtp-server@3.5.10:
|
||||
resolution: {integrity: sha512-i3Jx7sJ2qF52vjaOf3HguulXlWRFf6BSfsRLsIdmytDyVGv7KkhSs+gR9BXJnJWg1Ljkh/56Fh1Xqwa6u6X7zw==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
'@types/nodemailer': 6.4.15
|
||||
dev: false
|
||||
|
||||
/@types/ua-parser-js@0.7.39:
|
||||
resolution: {integrity: sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==}
|
||||
dev: true
|
||||
@@ -7428,6 +7493,10 @@ packages:
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
/base32.js@0.1.0:
|
||||
resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
|
||||
/balanced-match@2.0.0:
|
||||
resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
|
||||
dev: false
|
||||
@@ -8497,7 +8566,6 @@ packages:
|
||||
/dotenv@16.4.5:
|
||||
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
@@ -8543,6 +8611,16 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: true
|
||||
|
||||
/encoding-japanese@2.0.0:
|
||||
resolution: {integrity: sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
dev: false
|
||||
|
||||
/encoding-japanese@2.1.0:
|
||||
resolution: {integrity: sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
dev: false
|
||||
|
||||
/engine.io-parser@5.2.2:
|
||||
resolution: {integrity: sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -8554,7 +8632,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/cookie': 0.4.1
|
||||
'@types/cors': 2.8.17
|
||||
'@types/node': 20.11.27
|
||||
'@types/node': 20.12.12
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.4.2
|
||||
@@ -8831,7 +8909,7 @@ packages:
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
|
||||
eslint-plugin-react: 7.34.0(eslint@8.57.0)
|
||||
eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0)
|
||||
@@ -8889,7 +8967,7 @@ packages:
|
||||
enhanced-resolve: 5.16.0
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.3
|
||||
is-core-module: 2.13.1
|
||||
@@ -9023,6 +9101,41 @@ packages:
|
||||
ignore: 5.3.1
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.2)
|
||||
array-includes: 3.1.7
|
||||
array.prototype.findlastindex: 1.2.4
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.fromentries: 2.0.7
|
||||
object.groupby: 1.0.2
|
||||
object.values: 1.1.7
|
||||
semver: 6.3.1
|
||||
tsconfig-paths: 3.15.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -9058,40 +9171,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
array-includes: 3.1.7
|
||||
array.prototype.findlastindex: 1.2.4
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.fromentries: 2.0.7
|
||||
object.groupby: 1.0.2
|
||||
object.values: 1.1.7
|
||||
semver: 6.3.1
|
||||
tsconfig-paths: 3.15.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.4.2):
|
||||
resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
@@ -10399,6 +10478,11 @@ packages:
|
||||
property-information: 6.5.0
|
||||
space-separated-tokens: 2.0.2
|
||||
|
||||
/he@1.2.0:
|
||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/highlight.js@10.7.3:
|
||||
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
|
||||
dev: false
|
||||
@@ -10500,6 +10584,13 @@ packages:
|
||||
safer-buffer: 2.1.2
|
||||
dev: true
|
||||
|
||||
/iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
|
||||
@@ -10631,6 +10722,10 @@ packages:
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: true
|
||||
|
||||
/ipv6-normalize@1.0.1:
|
||||
resolution: {integrity: sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==}
|
||||
dev: false
|
||||
|
||||
/is-absolute-url@4.0.1:
|
||||
resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
@@ -11230,6 +11325,40 @@ packages:
|
||||
type-check: 0.4.0
|
||||
dev: true
|
||||
|
||||
/libbase64@1.2.1:
|
||||
resolution: {integrity: sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==}
|
||||
dev: false
|
||||
|
||||
/libbase64@1.3.0:
|
||||
resolution: {integrity: sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==}
|
||||
dev: false
|
||||
|
||||
/libmime@5.2.0:
|
||||
resolution: {integrity: sha512-X2U5Wx0YmK0rXFbk67ASMeqYIkZ6E5vY7pNWRKtnNzqjvdYYG8xtPDpCnuUEnPU9vlgNev+JoSrcaKSUaNvfsw==}
|
||||
dependencies:
|
||||
encoding-japanese: 2.0.0
|
||||
iconv-lite: 0.6.3
|
||||
libbase64: 1.2.1
|
||||
libqp: 2.0.1
|
||||
dev: false
|
||||
|
||||
/libmime@5.3.5:
|
||||
resolution: {integrity: sha512-nSlR1yRZ43L3cZCiWEw7ali3jY29Hz9CQQ96Oy+sSspYnIP5N54ucOPHqooBsXzwrX1pwn13VUE05q4WmzfaLg==}
|
||||
dependencies:
|
||||
encoding-japanese: 2.1.0
|
||||
iconv-lite: 0.6.3
|
||||
libbase64: 1.3.0
|
||||
libqp: 2.1.0
|
||||
dev: false
|
||||
|
||||
/libqp@2.0.1:
|
||||
resolution: {integrity: sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==}
|
||||
dev: false
|
||||
|
||||
/libqp@2.1.0:
|
||||
resolution: {integrity: sha512-O6O6/fsG5jiUVbvdgT7YX3xY3uIadR6wEZ7+vy9u7PKHAlSEB6blvC1o5pHBjgsi95Uo0aiBBdkyFecj6jtb7A==}
|
||||
dev: false
|
||||
|
||||
/lilconfig@2.1.0:
|
||||
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -11362,6 +11491,27 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/mailparser@3.7.1:
|
||||
resolution: {integrity: sha512-RCnBhy5q8XtB3mXzxcAfT1huNqN93HTYYyL6XawlIKycfxM/rXPg9tXoZ7D46+SgCS1zxKzw+BayDQSvncSTTw==}
|
||||
dependencies:
|
||||
encoding-japanese: 2.1.0
|
||||
he: 1.2.0
|
||||
html-to-text: 9.0.5
|
||||
iconv-lite: 0.6.3
|
||||
libmime: 5.3.5
|
||||
linkify-it: 5.0.0
|
||||
mailsplit: 5.4.0
|
||||
nodemailer: 6.9.13
|
||||
punycode.js: 2.3.1
|
||||
tlds: 1.252.0
|
||||
dev: false
|
||||
|
||||
/mailsplit@5.4.0:
|
||||
resolution: {integrity: sha512-wnYxX5D5qymGIPYLwnp6h8n1+6P6vz/MJn5AzGjZ8pwICWssL+CCQjWBIToOVHASmATot4ktvlLo6CyLfOXWYA==}
|
||||
dependencies:
|
||||
libbase64: 1.2.1
|
||||
libmime: 5.2.0
|
||||
libqp: 2.0.1
|
||||
/magic-string@0.30.10:
|
||||
resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
|
||||
dependencies:
|
||||
@@ -12468,6 +12618,16 @@ packages:
|
||||
vm-browserify: 1.1.2
|
||||
dev: false
|
||||
|
||||
/nodemailer@6.9.13:
|
||||
resolution: {integrity: sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: false
|
||||
|
||||
/nodemailer@6.9.14:
|
||||
resolution: {integrity: sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: false
|
||||
|
||||
/nopt@7.2.1:
|
||||
resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
@@ -13604,6 +13764,7 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
|
||||
/punycode@1.4.1:
|
||||
resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
|
||||
dev: false
|
||||
@@ -13611,7 +13772,6 @@ packages:
|
||||
/punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/qs@6.11.0:
|
||||
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
|
||||
@@ -14562,7 +14722,6 @@ packages:
|
||||
|
||||
/safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: true
|
||||
|
||||
/sax@1.3.0:
|
||||
resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
|
||||
@@ -14781,6 +14940,16 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/smtp-server@3.13.4:
|
||||
resolution: {integrity: sha512-BbElv5UP+HgPtCZtcRW35N/GFoc4DzPkrbSMLioXsrVMmQT1mMBoO0k+egl264hxWaWczoVvadSPY2pLUINFXg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
dependencies:
|
||||
base32.js: 0.1.0
|
||||
ipv6-normalize: 1.0.1
|
||||
nodemailer: 6.9.13
|
||||
punycode: 2.3.1
|
||||
dev: false
|
||||
|
||||
/socket.io-adapter@2.5.4:
|
||||
resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==}
|
||||
dependencies:
|
||||
@@ -15322,6 +15491,10 @@ packages:
|
||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
||||
dev: false
|
||||
|
||||
/tlds@1.252.0:
|
||||
resolution: {integrity: sha512-GA16+8HXvqtfEnw/DTcwB0UU354QE1n3+wh08oFjr6Znl7ZLAeUgYzCcK+/CCrOyE0vnHR8/pu3XXG3vDijXpQ==}
|
||||
hasBin: true
|
||||
|
||||
/tippy.js@6.3.7:
|
||||
resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==}
|
||||
dependencies:
|
||||
@@ -15647,6 +15820,12 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/typescript@5.5.4:
|
||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ua-parser-js@1.0.38:
|
||||
resolution: {integrity: sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==}
|
||||
dev: false
|
||||
@@ -15666,6 +15845,9 @@ packages:
|
||||
|
||||
/undici-types@5.26.5:
|
||||
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
|
||||
|
||||
/undici-types@6.13.0:
|
||||
resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==}
|
||||
dev: true
|
||||
|
||||
/undici@5.28.4:
|
||||
|
Reference in New Issue
Block a user