diff --git a/.devcontainer/on-create.sh b/.devcontainer/on-create.sh index fbd5351f2..1f71cdf3b 100755 --- a/.devcontainer/on-create.sh +++ b/.devcontainer/on-create.sh @@ -1,13 +1,10 @@ #!/usr/bin/env bash -# Start the database and mailserver -docker compose -f ./docker/compose-without-app.yml up -d - # Install dependencies npm install # Copy the env file cp .env.example .env -# Run the migrations -npm run prisma:migrate-dev +# Run the dev setup +npm run dx diff --git a/.env.example b/.env.example index 20e1ae2ae..1f2df8550 100644 --- a/.env.example +++ b/.env.example @@ -22,10 +22,23 @@ NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documen # Defines the URL to use for the database when running migrations and other commands that won't work with a connection pool. NEXT_PRIVATE_DIRECT_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso" -# [[E2E Tests]] -E2E_TEST_AUTHENTICATE_USERNAME="Test User" -E2E_TEST_AUTHENTICATE_USER_EMAIL="testuser@mail.com" -E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123" +# [[SIGNING]] +# The transport to use for document signing. Available options: local (default) | gcloud-hsm +NEXT_PRIVATE_SIGNING_TRANSPORT="local" +# OPTIONAL: The passphrase to use for the local file-based signing transport. +NEXT_PRIVATE_SIGNING_PASSPHRASE= +# OPTIONAL: The local file path to the .p12 file to use for the local signing transport. +NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH= +# OPTIONAL: The base64-encoded contents of the .p12 file to use for the local signing transport. +NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS= +# OPTIONAL: The path to the Google Cloud HSM key to use for the gcloud-hsm signing transport. +NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH= +# OPTIONAL: The path to the Google Cloud HSM public certificate file to use for the gcloud-hsm signing transport. +NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_PATH= +# OPTIONAL: The base64-encoded contents of the Google Cloud HSM public certificate file to use for the gcloud-hsm signing transport. +NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS= +# OPTIONAL: The path to the Google Cloud Credentials file to use for the gcloud-hsm signing transport. +NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS= # [[SIGNING]] # OPTIONAL: Defines the signing transport to use. Available options: local (default) @@ -100,6 +113,11 @@ NEXT_PUBLIC_FEATURE_BILLING_ENABLED= # OPTIONAL: Leave blank to allow users to signup through /signup page. NEXT_PUBLIC_DISABLE_SIGNUP= +# [[E2E Tests]] +E2E_TEST_AUTHENTICATE_USERNAME="Test User" +E2E_TEST_AUTHENTICATE_USER_EMAIL="testuser@mail.com" +E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123" + # This is only required for the marketing site # [[REDIS]] NEXT_PRIVATE_REDIS_URL= diff --git a/.github/PULL_REQUEST_TEMPLATE/generic.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/generic.md rename to .github/PULL_REQUEST_TEMPLATE.md diff --git a/.vscode/settings.json b/.vscode/settings.json index 82aa3c1a3..1fc8321db 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,9 @@ { "typescript.tsdk": "node_modules/typescript/lib", + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" + "source.fixAll": "explicit" }, "eslint.validate": ["typescript", "typescriptreact", "javascript", "javascriptreact"], "javascript.preferences.importModuleSpecifier": "non-relative", diff --git a/apps/marketing/next.config.js b/apps/marketing/next.config.js index 0a0032868..940536efa 100644 --- a/apps/marketing/next.config.js +++ b/apps/marketing/next.config.js @@ -21,7 +21,7 @@ const FONT_CAVEAT_BYTES = fs.readFileSync( const config = { experimental: { outputFileTracingRoot: path.join(__dirname, '../../'), - serverComponentsExternalPackages: ['@node-rs/bcrypt'], + serverComponentsExternalPackages: ['@node-rs/bcrypt', '@documenso/pdf-sign'], serverActions: { bodySizeLimit: '50mb', }, diff --git a/apps/marketing/src/app/(marketing)/layout.tsx b/apps/marketing/src/app/(marketing)/layout.tsx index a7c599b36..75c2d177c 100644 --- a/apps/marketing/src/app/(marketing)/layout.tsx +++ b/apps/marketing/src/app/(marketing)/layout.tsx @@ -38,7 +38,8 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) { return (
> = HTMLAttributes & { data: T; @@ -34,13 +33,13 @@ export const BarMetric = -
-

{title}

- {extraInfo} -
+
+
+
+

{title}

+ {extraInfo} +
-
diff --git a/apps/marketing/src/app/(marketing)/open/cap-table.tsx b/apps/marketing/src/app/(marketing)/open/cap-table.tsx index ba6a12dc4..05c122aa5 100644 --- a/apps/marketing/src/app/(marketing)/open/cap-table.tsx +++ b/apps/marketing/src/app/(marketing)/open/cap-table.tsx @@ -5,8 +5,6 @@ import { useEffect, useState } from 'react'; import { Cell, Legend, Pie, PieChart, Tooltip } from 'recharts'; -import { cn } from '@documenso/ui/lib/utils'; - import { CAP_TABLE } from './data'; const COLORS = ['#7fd843', '#a2e771', '#c6f2a4']; @@ -49,10 +47,12 @@ export const CapTable = ({ className, ...props }: CapTableProps) => { setIsSSR(false); }, []); return ( -
-

Cap Table

+
+
+
+

Cap Table

+
-
{!isSSR && ( & { data: Record[]; @@ -18,10 +17,12 @@ export const FundingRaised = ({ className, data, ...props }: FundingRaisedProps) })); return ( -
-

Total Funding Raised

+
+
+
+

Total Funding Raised

+
-
diff --git a/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx b/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx new file mode 100644 index 000000000..8ad860062 --- /dev/null +++ b/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { DateTime } from 'luxon'; +import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; + +import type { GetUserMonthlyGrowthResult } from '@documenso/lib/server-only/user/get-user-monthly-growth'; + +export type MonthlyCompletedDocumentsChartProps = { + className?: string; + data: GetUserMonthlyGrowthResult; +}; + +export const MonthlyCompletedDocumentsChart = ({ + className, + data, +}: MonthlyCompletedDocumentsChartProps) => { + const formattedData = [...data].reverse().map(({ month, count }) => { + return { + month: DateTime.fromFormat(month, 'yyyy-MM').toFormat('LLLL'), + count: Number(count), + }; + }); + + return ( +
+
+
+

Completed Documents per Month

+
+ + + + + + + [Number(value).toLocaleString('en-US'), 'Completed Documents']} + cursor={{ fill: 'hsl(var(--primary) / 10%)' }} + /> + + + + +
+
+ ); +}; diff --git a/apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx b/apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx index 0df73e30c..fe7941336 100644 --- a/apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx +++ b/apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx @@ -4,7 +4,6 @@ import { DateTime } from 'luxon'; import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import type { GetUserMonthlyGrowthResult } from '@documenso/lib/server-only/user/get-user-monthly-growth'; -import { cn } from '@documenso/ui/lib/utils'; export type MonthlyNewUsersChartProps = { className?: string; @@ -20,12 +19,12 @@ export const MonthlyNewUsersChart = ({ className, data }: MonthlyNewUsersChartPr }); return ( -
-
-

New Users

-
+
+
+
+

New Users

+
-
diff --git a/apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx b/apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx index 96ce34556..6ab5572ec 100644 --- a/apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx +++ b/apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx @@ -4,7 +4,6 @@ import { DateTime } from 'luxon'; import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import type { GetUserMonthlyGrowthResult } from '@documenso/lib/server-only/user/get-user-monthly-growth'; -import { cn } from '@documenso/ui/lib/utils'; export type MonthlyTotalUsersChartProps = { className?: string; @@ -20,12 +19,12 @@ export const MonthlyTotalUsersChart = ({ className, data }: MonthlyTotalUsersCha }); return ( -
-
-

Total Users

-
+
+
+
+

Total Users

+
-
diff --git a/apps/marketing/src/app/(marketing)/open/page.tsx b/apps/marketing/src/app/(marketing)/open/page.tsx index 10ab71aa7..31990519e 100644 --- a/apps/marketing/src/app/(marketing)/open/page.tsx +++ b/apps/marketing/src/app/(marketing)/open/page.tsx @@ -2,20 +2,23 @@ import type { Metadata } from 'next'; import { z } from 'zod'; +import { getCompletedDocumentsMonthly } from '@documenso/lib/server-only/user/get-monthly-completed-document'; import { getUserMonthlyGrowth } from '@documenso/lib/server-only/user/get-user-monthly-growth'; import { FUNDING_RAISED } from '~/app/(marketing)/open/data'; -import { MetricCard } from '~/app/(marketing)/open/metric-card'; -import { SalaryBands } from '~/app/(marketing)/open/salary-bands'; import { CallToAction } from '~/components/(marketing)/call-to-action'; import { BarMetric } from './bar-metrics'; import { CapTable } from './cap-table'; import { FundingRaised } from './funding-raised'; +import { MetricCard } from './metric-card'; +import { MonthlyCompletedDocumentsChart } from './monthly-completed-documents-chart'; import { MonthlyNewUsersChart } from './monthly-new-users-chart'; import { MonthlyTotalUsersChart } from './monthly-total-users-chart'; +import { SalaryBands } from './salary-bands'; import { TeamMembers } from './team-members'; import { OpenPageTooltip } from './tooltip'; +import { TotalSignedDocumentsChart } from './total-signed-documents-chart'; import { Typefully } from './typefully'; export const metadata: Metadata = { @@ -131,16 +134,18 @@ export default async function OpenPage() { { total_count: mergedPullRequests }, STARGAZERS_DATA, EARLY_ADOPTERS_DATA, + MONTHLY_USERS, + MONTHLY_COMPLETED_DOCUMENTS, ] = await Promise.all([ fetchGithubStats(), fetchOpenIssues(), fetchMergedPullRequests(), fetchStargazers(), fetchEarlyAdopters(), + getUserMonthlyGrowth(), + getCompletedDocumentsMonthly(), ]); - const MONTHLY_USERS = await getUserMonthlyGrowth(); - return (
@@ -161,7 +166,7 @@ export default async function OpenPage() {

-
+
+
+

Finances

+
+
+

Community

+
+ + data={STARGAZERS_DATA} + metricKey="stars" + title="GitHub: Total Stars" + label="Stars" + className="col-span-12 lg:col-span-6" + /> + + + data={STARGAZERS_DATA} + metricKey="mergedPRs" + title="GitHub: Total Merged PRs" + label="Merged PRs" + chartHeight={400} + className="col-span-12 lg:col-span-6" + /> + + + data={STARGAZERS_DATA} + metricKey="forks" + title="GitHub: Total Forks" + label="Forks" + chartHeight={400} + className="col-span-12 lg:col-span-6" + /> + + + data={STARGAZERS_DATA} + metricKey="openIssues" + title="GitHub: Total Open Issues" + label="Open Issues" + chartHeight={400} + className="col-span-12 lg:col-span-6" + /> + + +
+ +

Growth

+
data={EARLY_ADOPTERS_DATA} metricKey="earlyAdopters" @@ -202,57 +253,29 @@ export default async function OpenPage() { extraInfo={} /> - - data={STARGAZERS_DATA} - metricKey="stars" - title="Github: Total Stars" - label="Stars" - className="col-span-12 lg:col-span-6" - /> - - - data={STARGAZERS_DATA} - metricKey="mergedPRs" - title="Github: Total Merged PRs" - label="Merged PRs" - chartHeight={300} - className="col-span-12 lg:col-span-6" - /> - - - data={STARGAZERS_DATA} - metricKey="forks" - title="Github: Total Forks" - label="Forks" - chartHeight={300} - className="col-span-12 lg:col-span-6" - /> - - - data={STARGAZERS_DATA} - metricKey="openIssues" - title="Github: Total Open Issues" - label="Open Issues" - chartHeight={300} - className="col-span-12 lg:col-span-6" - /> - - - -
-

Where's the rest?

- -

- We're still working on getting all our metrics together. We'll update this page as - soon as we have more to share. -

-
+ +
+
+

Is there more?

+ +

+ This page is evolving as we learn what makes a great signing company. We'll update it when + we have more to share. +

+
+
); diff --git a/apps/marketing/src/app/(marketing)/open/team-members.tsx b/apps/marketing/src/app/(marketing)/open/team-members.tsx index a79fcd182..288d48a0b 100644 --- a/apps/marketing/src/app/(marketing)/open/team-members.tsx +++ b/apps/marketing/src/app/(marketing)/open/team-members.tsx @@ -1,4 +1,4 @@ -import { HTMLAttributes } from 'react'; +import type { HTMLAttributes } from 'react'; import { cn } from '@documenso/ui/lib/utils'; import { diff --git a/apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx b/apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx new file mode 100644 index 000000000..2a8393363 --- /dev/null +++ b/apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { DateTime } from 'luxon'; +import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; + +import type { GetUserMonthlyGrowthResult } from '@documenso/lib/server-only/user/get-user-monthly-growth'; + +export type TotalSignedDocumentsChartProps = { + className?: string; + data: GetUserMonthlyGrowthResult; +}; + +export const TotalSignedDocumentsChart = ({ className, data }: TotalSignedDocumentsChartProps) => { + const formattedData = [...data].reverse().map(({ month, cume_count: count }) => { + return { + month: DateTime.fromFormat(month, 'yyyy-MM').toFormat('LLLL'), + count: Number(count), + }; + }); + + return ( +
+
+
+

Total Completed Documents

+
+ + + + + + + [ + Number(value).toLocaleString('en-US'), + 'Total Completed Documents', + ]} + cursor={{ fill: 'hsl(var(--primary) / 10%)' }} + /> + + + + +
+
+ ); +}; diff --git a/apps/marketing/src/app/(marketing)/open/typefully.tsx b/apps/marketing/src/app/(marketing)/open/typefully.tsx index a233904db..4f298fbb3 100644 --- a/apps/marketing/src/app/(marketing)/open/typefully.tsx +++ b/apps/marketing/src/app/(marketing)/open/typefully.tsx @@ -6,18 +6,19 @@ import Link from 'next/link'; import { FaXTwitter } from 'react-icons/fa6'; -import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; export type TypefullyProps = HTMLAttributes; export const Typefully = ({ className, ...props }: TypefullyProps) => { return ( -
-

Twitter Stats

+
+
+
+

Twitter Stats

+
-
-
+

Documenso on X

diff --git a/apps/marketing/src/components/(marketing)/callout.tsx b/apps/marketing/src/components/(marketing)/callout.tsx index faa486c46..dfd358c71 100644 --- a/apps/marketing/src/components/(marketing)/callout.tsx +++ b/apps/marketing/src/components/(marketing)/callout.tsx @@ -53,7 +53,7 @@ export const Callout = ({ starCount }: CalloutProps) => { > diff --git a/apps/marketing/src/components/(marketing)/pricing-table.tsx b/apps/marketing/src/components/(marketing)/pricing-table.tsx index 2cd6eec00..b34173ba1 100644 --- a/apps/marketing/src/components/(marketing)/pricing-table.tsx +++ b/apps/marketing/src/components/(marketing)/pricing-table.tsx @@ -23,7 +23,7 @@ export const PricingTable = ({ className, ...props }: PricingTableProps) => { return (
-
+
{ {period === 'MONTHLY' && ( )} @@ -63,7 +63,7 @@ export const PricingTable = ({ className, ...props }: PricingTableProps) => { {period === 'YEARLY' && ( )} diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 1a48e29e3..d670dab47 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -22,7 +22,7 @@ const config = { output: process.env.DOCKER_OUTPUT ? 'standalone' : undefined, experimental: { outputFileTracingRoot: path.join(__dirname, '../../'), - serverComponentsExternalPackages: ['@node-rs/bcrypt'], + serverComponentsExternalPackages: ['@node-rs/bcrypt', '@documenso/pdf-sign'], serverActions: { bodySizeLimit: '50mb', }, diff --git a/apps/web/src/app/(dashboard)/settings/security/page.tsx b/apps/web/src/app/(dashboard)/settings/security/page.tsx index f46784aed..ba5d9846c 100644 --- a/apps/web/src/app/(dashboard)/settings/security/page.tsx +++ b/apps/web/src/app/(dashboard)/settings/security/page.tsx @@ -1,14 +1,14 @@ import type { Metadata } from 'next'; import Link from 'next/link'; -import { IDENTITY_PROVIDER_NAME } from '@documenso/lib/constants/auth'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; import { SettingsHeader } from '~/components/(dashboard)/settings/layout/header'; -import { AuthenticatorApp } from '~/components/forms/2fa/authenticator-app'; -import { RecoveryCodes } from '~/components/forms/2fa/recovery-codes'; +import { DisableAuthenticatorAppDialog } from '~/components/forms/2fa/disable-authenticator-app-dialog'; +import { EnableAuthenticatorAppDialog } from '~/components/forms/2fa/enable-authenticator-app-dialog'; +import { ViewRecoveryCodesDialog } from '~/components/forms/2fa/view-recovery-codes-dialog'; import { PasswordForm } from '~/components/forms/password'; export const metadata: Metadata = { @@ -25,57 +25,51 @@ export default async function SecuritySettingsPage() { subtitle="Here you can manage your password and security settings." /> - {user.identityProvider === 'DOCUMENSO' ? ( -
+ {user.identityProvider === 'DOCUMENSO' && ( + <>
+ + )} - -
- Two factor authentication + +
+ Two factor authentication - - Create one-time passwords that serve as a secondary authentication method for - confirming your identity when requested during the sign-in process. - -
- - -
- - {user.twoFactorEnabled && ( - -
- Recovery codes - - - Two factor authentication recovery codes are used to access your account in the - event that you lose access to your authenticator app. - -
- - -
- )} -
- ) : ( - - - Your account is managed by {IDENTITY_PROVIDER_NAME[user.identityProvider]} - - - - To update your password, enable two-factor authentication, and manage other security - settings, please go to your {IDENTITY_PROVIDER_NAME[user.identityProvider]} account - settings. + + Add an authenticator to serve as a secondary authentication method{' '} + {user.identityProvider === 'DOCUMENSO' + ? 'when signing in, or when signing documents.' + : 'for signing documents.'} +
+ + {user.twoFactorEnabled ? ( + + ) : ( + + )} + + + {user.twoFactorEnabled && ( + +
+ Recovery codes + + + Two factor authentication recovery codes are used to access your account in the event + that you lose access to your authenticator app. + +
+ +
)} diff --git a/apps/web/src/components/forms/2fa/authenticator-app.tsx b/apps/web/src/components/forms/2fa/authenticator-app.tsx deleted file mode 100644 index 3aa0e123e..000000000 --- a/apps/web/src/components/forms/2fa/authenticator-app.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client'; - -import { useState } from 'react'; - -import { Button } from '@documenso/ui/primitives/button'; - -import { DisableAuthenticatorAppDialog } from './disable-authenticator-app-dialog'; -import { EnableAuthenticatorAppDialog } from './enable-authenticator-app-dialog'; - -type AuthenticatorAppProps = { - isTwoFactorEnabled: boolean; -}; - -export const AuthenticatorApp = ({ isTwoFactorEnabled }: AuthenticatorAppProps) => { - const [modalState, setModalState] = useState<'enable' | 'disable' | null>(null); - - const isEnableDialogOpen = modalState === 'enable'; - const isDisableDialogOpen = modalState === 'disable'; - - return ( - <> -
- {isTwoFactorEnabled ? ( - - ) : ( - - )} -
- - !open && setModalState(null)} - /> - - !open && setModalState(null)} - /> - - ); -}; diff --git a/apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx b/apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx index 06211170f..c5745a499 100644 --- a/apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx +++ b/apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx @@ -1,3 +1,7 @@ +'use client'; + +import { useState } from 'react'; + import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -9,65 +13,51 @@ import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, + DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, + DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { Form, FormControl, FormField, FormItem, - FormLabel, FormMessage, } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; -import { PasswordInput } from '@documenso/ui/primitives/password-input'; import { useToast } from '@documenso/ui/primitives/use-toast'; -export const ZDisableTwoFactorAuthenticationForm = z.object({ - password: z.string().min(6).max(72), - backupCode: z.string(), +export const ZDisable2FAForm = z.object({ + token: z.string(), }); -export type TDisableTwoFactorAuthenticationForm = z.infer< - typeof ZDisableTwoFactorAuthenticationForm ->; +export type TDisable2FAForm = z.infer; -export type DisableAuthenticatorAppDialogProps = { - open: boolean; - onOpenChange: (_open: boolean) => void; -}; - -export const DisableAuthenticatorAppDialog = ({ - open, - onOpenChange, -}: DisableAuthenticatorAppDialogProps) => { +export const DisableAuthenticatorAppDialog = () => { const router = useRouter(); + const { toast } = useToast(); - const { mutateAsync: disableTwoFactorAuthentication } = - trpc.twoFactorAuthentication.disable.useMutation(); + const [isOpen, setIsOpen] = useState(false); - const disableTwoFactorAuthenticationForm = useForm({ + const { mutateAsync: disable2FA } = trpc.twoFactorAuthentication.disable.useMutation(); + + const disable2FAForm = useForm({ defaultValues: { - password: '', - backupCode: '', + token: '', }, - resolver: zodResolver(ZDisableTwoFactorAuthenticationForm), + resolver: zodResolver(ZDisable2FAForm), }); - const { isSubmitting: isDisableTwoFactorAuthenticationSubmitting } = - disableTwoFactorAuthenticationForm.formState; + const { isSubmitting: isDisable2FASubmitting } = disable2FAForm.formState; - const onDisableTwoFactorAuthenticationFormSubmit = async ({ - password, - backupCode, - }: TDisableTwoFactorAuthenticationForm) => { + const onDisable2FAFormSubmit = async ({ token }: TDisable2FAForm) => { try { - await disableTwoFactorAuthentication({ password, backupCode }); + await disable2FA({ token }); toast({ title: 'Two-factor authentication disabled', @@ -76,7 +66,7 @@ export const DisableAuthenticatorAppDialog = ({ }); flushSync(() => { - onOpenChange(false); + setIsOpen(false); }); router.refresh(); @@ -91,74 +81,51 @@ export const DisableAuthenticatorAppDialog = ({ }; return ( - - + + + + + + - Disable Authenticator App + Disable 2FA - To disable the Authenticator App for your account, please enter your password and a - backup code. If you do not have a backup code available, please contact support. + Please provide a token from the authenticator, or a backup code. If you do not have a + backup code available, please contact support. -
- -
+ + +
( - Password - + )} /> - ( - - Backup Code - - - - - - )} - /> + + + + + + +
- - - - - - diff --git a/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx b/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx index d7a8f6553..0a6aac5dc 100644 --- a/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx +++ b/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx @@ -1,8 +1,11 @@ -import { useEffect, useMemo } from 'react'; +'use client'; + +import { useEffect, useState } from 'react'; + +import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; -import { match } from 'ts-pattern'; import { renderSVG } from 'uqr'; import { z } from 'zod'; @@ -11,11 +14,13 @@ import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, + DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, + DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { Form, @@ -26,85 +31,60 @@ import { FormMessage, } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; -import { PasswordInput } from '@documenso/ui/primitives/password-input'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { RecoveryCodeList } from './recovery-code-list'; -export const ZSetupTwoFactorAuthenticationForm = z.object({ - password: z.string().min(6).max(72), -}); - -export type TSetupTwoFactorAuthenticationForm = z.infer; - -export const ZEnableTwoFactorAuthenticationForm = z.object({ +export const ZEnable2FAForm = z.object({ token: z.string(), }); -export type TEnableTwoFactorAuthenticationForm = z.infer; +export type TEnable2FAForm = z.infer; -export type EnableAuthenticatorAppDialogProps = { - open: boolean; - onOpenChange: (_open: boolean) => void; -}; - -export const EnableAuthenticatorAppDialog = ({ - open, - onOpenChange, -}: EnableAuthenticatorAppDialogProps) => { +export const EnableAuthenticatorAppDialog = () => { const { toast } = useToast(); + const router = useRouter(); - const { mutateAsync: setupTwoFactorAuthentication, data: setupTwoFactorAuthenticationData } = - trpc.twoFactorAuthentication.setup.useMutation(); + const [isOpen, setIsOpen] = useState(false); + const [recoveryCodes, setRecoveryCodes] = useState(null); + + const { mutateAsync: enable2FA } = trpc.twoFactorAuthentication.enable.useMutation(); const { - mutateAsync: enableTwoFactorAuthentication, - data: enableTwoFactorAuthenticationData, - isLoading: isEnableTwoFactorAuthenticationDataLoading, - } = trpc.twoFactorAuthentication.enable.useMutation(); - - const setupTwoFactorAuthenticationForm = useForm({ - defaultValues: { - password: '', + mutateAsync: setup2FA, + data: setup2FAData, + isLoading: isSettingUp2FA, + } = trpc.twoFactorAuthentication.setup.useMutation({ + onError: () => { + toast({ + title: 'Unable to setup two-factor authentication', + description: + 'We were unable to setup two-factor authentication for your account. Please ensure that you have entered your code correctly and try again.', + variant: 'destructive', + }); }, - resolver: zodResolver(ZSetupTwoFactorAuthenticationForm), }); - const { isSubmitting: isSetupTwoFactorAuthenticationSubmitting } = - setupTwoFactorAuthenticationForm.formState; - - const enableTwoFactorAuthenticationForm = useForm({ + const enable2FAForm = useForm({ defaultValues: { token: '', }, - resolver: zodResolver(ZEnableTwoFactorAuthenticationForm), + resolver: zodResolver(ZEnable2FAForm), }); - const { isSubmitting: isEnableTwoFactorAuthenticationSubmitting } = - enableTwoFactorAuthenticationForm.formState; + const { isSubmitting: isEnabling2FA } = enable2FAForm.formState; - const step = useMemo(() => { - if (!setupTwoFactorAuthenticationData || isSetupTwoFactorAuthenticationSubmitting) { - return 'setup'; - } - - if (!enableTwoFactorAuthenticationData || isEnableTwoFactorAuthenticationSubmitting) { - return 'enable'; - } - - return 'view'; - }, [ - setupTwoFactorAuthenticationData, - isSetupTwoFactorAuthenticationSubmitting, - enableTwoFactorAuthenticationData, - isEnableTwoFactorAuthenticationSubmitting, - ]); - - const onSetupTwoFactorAuthenticationFormSubmit = async ({ - password, - }: TSetupTwoFactorAuthenticationForm) => { + const onEnable2FAFormSubmit = async ({ token }: TEnable2FAForm) => { try { - await setupTwoFactorAuthentication({ password }); + const data = await enable2FA({ code: token }); + + setRecoveryCodes(data.recoveryCodes); + + toast({ + title: 'Two-factor authentication enabled', + description: + 'You will now be required to enter a code from your authenticator app when signing in.', + }); } catch (_err) { toast({ title: 'Unable to setup two-factor authentication', @@ -116,8 +96,8 @@ export const EnableAuthenticatorAppDialog = ({ }; const downloadRecoveryCodes = () => { - if (enableTwoFactorAuthenticationData && enableTwoFactorAuthenticationData.recoveryCodes) { - const blob = new Blob([enableTwoFactorAuthenticationData.recoveryCodes.join('\n')], { + if (recoveryCodes) { + const blob = new Blob([recoveryCodes.join('\n')], { type: 'text/plain', }); @@ -128,175 +108,126 @@ export const EnableAuthenticatorAppDialog = ({ } }; - const onEnableTwoFactorAuthenticationFormSubmit = async ({ - token, - }: TEnableTwoFactorAuthenticationForm) => { - try { - await enableTwoFactorAuthentication({ code: token }); - - toast({ - title: 'Two-factor authentication enabled', - description: - 'Two-factor authentication has been enabled for your account. You will now be required to enter a code from your authenticator app when signing in.', - }); - } catch (_err) { - toast({ - title: 'Unable to setup two-factor authentication', - description: - 'We were unable to setup two-factor authentication for your account. Please ensure that you have entered your password correctly and try again.', - variant: 'destructive', - }); + const handleEnable2FA = async () => { + if (!setup2FAData) { + await setup2FA(); } + + setIsOpen(true); }; useEffect(() => { - // Reset the form when the Dialog closes - if (!open) { - setupTwoFactorAuthenticationForm.reset(); + enable2FAForm.reset(); + + if (!isOpen && recoveryCodes && recoveryCodes.length > 0) { + setRecoveryCodes(null); + router.refresh(); } - }, [open, setupTwoFactorAuthenticationForm]); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); return ( - - - - Enable Authenticator App + + + + - {step === 'setup' && ( - - To enable two-factor authentication, please enter your password below. - - )} + + {setup2FAData && ( + <> + {recoveryCodes ? ( +
+ + Backup codes + + Your recovery codes are listed below. Please store them in a safe place. + + - {step === 'view' && ( - - Your recovery codes are listed below. Please store them in a safe place. - - )} - +
+ +
- {match(step) - .with('setup', () => { - return ( -
- - ( - - Password - - - - - - )} - /> + + + + - - + + +
+ ) : ( + + + + Enable Authenticator App + + To enable two-factor authentication, scan the following QR code using your + authenticator app. + + - - +
+
+ +

+ If your authenticator app does not support QR codes, you can use the following + code instead: +

+ +

+ {setup2FAData?.secret} +

+ +

+ Once you have scanned the QR code or entered the code manually, enter the code + provided by your authenticator app below. +

+ + ( + + Token + + + + + + )} + /> + + + + + + + + +
- ); - }) - .with('enable', () => ( -
- -

- To enable two-factor authentication, scan the following QR code using your - authenticator app. -

- -
- -

- If your authenticator app does not support QR codes, you can use the following - code instead: -

- -

- {setupTwoFactorAuthenticationData?.secret} -

- -

- Once you have scanned the QR code or entered the code manually, enter the code - provided by your authenticator app below. -

- - ( - - Token - - - - - - )} - /> - - - - - - - - - )) - .with('view', () => ( -
- {enableTwoFactorAuthenticationData?.recoveryCodes && ( - - )} - -
- - - -
-
- )) - .exhaustive()} + )} + + )}
); diff --git a/apps/web/src/components/forms/2fa/recovery-codes.tsx b/apps/web/src/components/forms/2fa/recovery-codes.tsx deleted file mode 100644 index 29834c74a..000000000 --- a/apps/web/src/components/forms/2fa/recovery-codes.tsx +++ /dev/null @@ -1,33 +0,0 @@ -'use client'; - -import { useState } from 'react'; - -import { Button } from '@documenso/ui/primitives/button'; - -import { ViewRecoveryCodesDialog } from './view-recovery-codes-dialog'; - -type RecoveryCodesProps = { - isTwoFactorEnabled: boolean; -}; - -export const RecoveryCodes = ({ isTwoFactorEnabled }: RecoveryCodesProps) => { - const [isOpen, setIsOpen] = useState(false); - - return ( - <> - - - - - ); -}; diff --git a/apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx b/apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx index 48e343e8d..66df7bbab 100644 --- a/apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx +++ b/apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx @@ -1,4 +1,6 @@ -import { useEffect, useMemo } from 'react'; +'use client'; + +import { useState } from 'react'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; @@ -6,69 +8,61 @@ import { match } from 'ts-pattern'; import { z } from 'zod'; import { downloadFile } from '@documenso/lib/client-only/download-file'; +import { AppError } from '@documenso/lib/errors/app-error'; +import { ErrorCode } from '@documenso/lib/next-auth/error-codes'; import { trpc } from '@documenso/trpc/react'; +import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, + DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, + DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { Form, FormControl, FormField, FormItem, - FormLabel, FormMessage, } from '@documenso/ui/primitives/form/form'; -import { PasswordInput } from '@documenso/ui/primitives/password-input'; -import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Input } from '@documenso/ui/primitives/input'; import { RecoveryCodeList } from './recovery-code-list'; export const ZViewRecoveryCodesForm = z.object({ - password: z.string().min(6).max(72), + token: z.string().min(1, { message: 'Token is required' }), }); export type TViewRecoveryCodesForm = z.infer; -export type ViewRecoveryCodesDialogProps = { - open: boolean; - onOpenChange: (_open: boolean) => void; -}; - -export const ViewRecoveryCodesDialog = ({ open, onOpenChange }: ViewRecoveryCodesDialogProps) => { - const { toast } = useToast(); +export const ViewRecoveryCodesDialog = () => { + const [isOpen, setIsOpen] = useState(false); const { - mutateAsync: viewRecoveryCodes, - data: viewRecoveryCodesData, - isLoading: isViewRecoveryCodesDataLoading, + data: recoveryCodes, + mutate, + isLoading, + isError, + error, } = trpc.twoFactorAuthentication.viewRecoveryCodes.useMutation(); + // error?.data?.code + const viewRecoveryCodesForm = useForm({ defaultValues: { - password: '', + token: '', }, resolver: zodResolver(ZViewRecoveryCodesForm), }); - const { isSubmitting: isViewRecoveryCodesSubmitting } = viewRecoveryCodesForm.formState; - - const step = useMemo(() => { - if (!viewRecoveryCodesData || isViewRecoveryCodesSubmitting) { - return 'authenticate'; - } - - return 'view'; - }, [viewRecoveryCodesData, isViewRecoveryCodesSubmitting]); - const downloadRecoveryCodes = () => { - if (viewRecoveryCodesData && viewRecoveryCodesData.recoveryCodes) { - const blob = new Blob([viewRecoveryCodesData.recoveryCodes.join('\n')], { + if (recoveryCodes) { + const blob = new Blob([recoveryCodes.join('\n')], { type: 'text/plain', }); @@ -79,105 +73,88 @@ export const ViewRecoveryCodesDialog = ({ open, onOpenChange }: ViewRecoveryCode } }; - const onViewRecoveryCodesFormSubmit = async ({ password }: TViewRecoveryCodesForm) => { - try { - await viewRecoveryCodes({ password }); - } catch (_err) { - toast({ - title: 'Unable to view recovery codes', - description: - 'We were unable to view your recovery codes. Please ensure that you have entered your password correctly and try again.', - variant: 'destructive', - }); - } - }; - - useEffect(() => { - // Reset the form when the Dialog closes - if (!open) { - viewRecoveryCodesForm.reset(); - } - }, [open, viewRecoveryCodesForm]); - return ( - + + + + + - - View Recovery Codes + {recoveryCodes ? ( +
+ + View Recovery Codes - {step === 'authenticate' && ( - - To view your recovery codes, please enter your password below. - - )} + + Your recovery codes are listed below. Please store them in a safe place. + + - {step === 'view' && ( - - Your recovery codes are listed below. Please store them in a safe place. - - )} - + - {match(step) - .with('authenticate', () => { - return ( -
- - ( - - Password - - - - - - )} - /> + + + + - - + +
+ ) : ( + + mutate(value))}> + + View Recovery Codes + + + Please provide a token from your authenticator, or a backup code. + + + +
+ ( + + + + + + + )} + /> + + {error && ( + + + {match(AppError.parseError(error).message) + .with( + ErrorCode.INCORRECT_TWO_FACTOR_CODE, + () => 'Invalid code. Please try again.', + ) + .otherwise( + () => 'Something went wrong. Please try again or contact support.', + )} + + + )} + + + + + - - - - - ); - }) - .with('view', () => ( -
- {viewRecoveryCodesData?.recoveryCodes && ( - - )} - -
- - - -
-
- )) - .exhaustive()} + + +
+ + + )}
); diff --git a/apps/web/src/components/forms/public-profile-claim-dialog.tsx b/apps/web/src/components/forms/public-profile-claim-dialog.tsx index dbd52fd27..e3b03a44c 100644 --- a/apps/web/src/components/forms/public-profile-claim-dialog.tsx +++ b/apps/web/src/components/forms/public-profile-claim-dialog.tsx @@ -154,7 +154,7 @@ export const ClaimPublicProfileDialogForm = ({ -
+
{baseUrl.host}/u/{field.value || ''}
diff --git a/lint-staged.config.cjs b/lint-staged.config.cjs index d7e42680e..70025bfe4 100644 --- a/lint-staged.config.cjs +++ b/lint-staged.config.cjs @@ -1,7 +1,15 @@ +const path = require('path'); + +const eslint = (filenames) => + `eslint --fix ${filenames.map((f) => `"${path.relative(process.cwd(), f)}"`).join(' ')}`; + +const prettier = (filenames) => + `prettier --write ${filenames.map((f) => `"${path.relative(process.cwd(), f)}"`).join(' ')}`; + /** @type {import('lint-staged').Config} */ module.exports = { - '**/*.{ts,tsx,cts,mts}': (files) => files.map((file) => `eslint --fix ${file}`), - '**/*.{js,jsx,cjs,mjs}': (files) => files.map((file) => `prettier --write ${file}`), - '**/*.{yml,mdx}': (files) => files.map((file) => `prettier --write ${file}`), + '**/*.{ts,tsx,cts,mts}': [eslint, prettier], + '**/*.{js,jsx,cjs,mjs}': [prettier], + '**/*.{yml,mdx}': [prettier], '**/*/package.json': 'npm run precommit', }; diff --git a/package-lock.json b/package-lock.json index d7615e179..8d47958aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "packages/*" ], "dependencies": { + "@documenso/pdf-sign": "^0.1.0", "next-runtime-env": "^3.2.0" }, "devDependencies": { @@ -19,8 +20,8 @@ "dotenv-cli": "^7.3.0", "eslint": "^8.40.0", "eslint-config-custom": "*", - "husky": "^8.0.0", - "lint-staged": "^14.0.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", "prettier": "^2.5.1", "rimraf": "^5.0.1", "turbo": "^1.9.3" @@ -1844,6 +1845,128 @@ "nodemailer": "^6.9.3" } }, + "node_modules/@documenso/pdf-sign": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign/-/pdf-sign-0.1.0.tgz", + "integrity": "sha512-7PSI+A2PRLuOo3804hJqubiV0MyFbc2a/3lp292pdGmrg0diiIOao+GaJUPN1z3xkTudU/0u0pvUHxq4h/bvPA==", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@documenso/pdf-sign-darwin-arm64": "0.1.0", + "@documenso/pdf-sign-darwin-x64": "0.1.0", + "@documenso/pdf-sign-linux-arm64-gnu": "0.1.0", + "@documenso/pdf-sign-linux-arm64-musl": "0.1.0", + "@documenso/pdf-sign-linux-x64-gnu": "0.1.0", + "@documenso/pdf-sign-linux-x64-musl": "0.1.0", + "@documenso/pdf-sign-win32-x64-msvc": "0.1.0" + } + }, + "node_modules/@documenso/pdf-sign-darwin-arm64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-darwin-arm64/-/pdf-sign-darwin-arm64-0.1.0.tgz", + "integrity": "sha512-anIGpktb0DiFUA058TpAXnCq5QvpnS3Bx7LgOZVd7wuNhDrZ4tD4P3jZOVfmnSPLLAURqiLZZ1aD187W3LX3XQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-darwin-x64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-darwin-x64/-/pdf-sign-darwin-x64-0.1.0.tgz", + "integrity": "sha512-eAXdgjXWh92UoBuPcYdXXnxKMHgGqf3Gh33K+QIcGWnXJUmA9OWYSfKFTZVP3MPs0VJZ8/e6Dj0VeOjMHuU64A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-linux-arm64-gnu": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-linux-arm64-gnu/-/pdf-sign-linux-arm64-gnu-0.1.0.tgz", + "integrity": "sha512-IBSCFYyppgOTISgXS2zfrm7CKqoW76nbZQw6vc98MY2Pp+EFhkhYTKnvuFB+Sph1cARNLBWVLlggHe3KMaTvyw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-linux-arm64-musl": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-linux-arm64-musl/-/pdf-sign-linux-arm64-musl-0.1.0.tgz", + "integrity": "sha512-++YQP13qGglXpek/LHEMCBs/j3Vf0egFCUz+IDAC0bEjJVrLdwvJnAhXNdxruVVRDBcQ/6Sx7Vq3zfyd/9wQOQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-linux-x64-gnu": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-linux-x64-gnu/-/pdf-sign-linux-x64-gnu-0.1.0.tgz", + "integrity": "sha512-19e+lbI9CeloLHo59ktsqYZ7g4lV0g8sdqIecwHZgPk+WMzh6MHb98ZREOs5iuN1RusGXIxZCMITdKr9V/cuuw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-linux-x64-musl": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-linux-x64-musl/-/pdf-sign-linux-x64-musl-0.1.0.tgz", + "integrity": "sha512-XzxazfViLR3vJPYxd4f4n3AalOnakZ/T0dpYOtNEmIA3TYmT+gXQDI0kTmfPtMLcMwoj2WirgkfSdJ1EjqGIoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@documenso/pdf-sign-win32-x64-msvc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@documenso/pdf-sign-win32-x64-msvc/-/pdf-sign-win32-x64-msvc-0.1.0.tgz", + "integrity": "sha512-MAs3nJZdhNWubCLFVEVOGDQHlZHpI1gIUSVD0j/t0ddDat+Audz9ZmzidQJEBHywXZ7dwFOYFTWgjnaCiddTpQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@documenso/prettier-config": { "resolved": "packages/prettier-config", "link": true @@ -1977,6 +2100,70 @@ "esbuild": "*" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", @@ -1992,6 +2179,294 @@ "node": ">=12" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2710,6 +3185,18 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -3032,14 +3519,6 @@ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.3.tgz", "integrity": "sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==" }, - "node_modules/@next/eslint-plugin-next": { - "version": "13.4.19", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.19.tgz", - "integrity": "sha512-N/O+zGb6wZQdwu6atMZHbR7T9Np5SUFUjZqCbj0sXm+MwQO35M8TazVB4otm87GkXYs2l6OPwARd3/PUWhZBVQ==", - "dependencies": { - "glob": "7.1.7" - } - }, "node_modules/@next/swc-darwin-arm64": { "version": "14.0.3", "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.3.tgz", @@ -5750,6 +6229,175 @@ "react": "18.2.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", + "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", + "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", + "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", + "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", + "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", + "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", + "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", + "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", + "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", + "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", + "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", + "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", + "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rushstack/eslint-patch": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", @@ -5793,6 +6441,12 @@ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@sindresorhus/slugify": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", @@ -7311,15 +7965,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==" }, - "node_modules/@types/node-forge": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", - "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/nodemailer": { "version": "6.4.14", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.14.tgz", @@ -7418,187 +8063,6 @@ "@types/node": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", - "dependencies": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", - "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", - "dependencies": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", - "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", - "dependencies": { - "@typescript-eslint/types": "6.8.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -7612,6 +8076,166 @@ "crypto-js": "^4.2.0" } }, + "node_modules/@vitest/expect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", + "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", + "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.3.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", + "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/snapshot/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/snapshot/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/@vitest/spy": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", + "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", + "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/@vvo/tzdb": { "version": "6.117.0", "resolved": "https://registry.npmjs.org/@vvo/tzdb/-/tzdb-6.117.0.tgz", @@ -7629,9 +8253,9 @@ "optional": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -7677,9 +8301,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "devOptional": true, "engines": { "node": ">=0.4.0" @@ -7714,27 +8338,15 @@ } }, "node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "type-fest": "^1.0.2" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7876,6 +8488,24 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", + "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", @@ -7928,10 +8558,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, "node_modules/array.prototype.tosorted": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7974,6 +8616,15 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -8466,6 +9117,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -8528,6 +9197,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -8628,21 +9309,71 @@ } }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -9054,9 +9785,9 @@ "integrity": "sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w==" }, "node_modules/commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "engines": { "node": ">=16" @@ -9587,6 +10318,18 @@ "node": ">=8" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -9761,6 +10504,15 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -10169,6 +10921,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", @@ -10263,6 +11034,321 @@ "@esbuild/win32-x64": "0.18.20" } }, + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -10645,35 +11731,11 @@ "semver": "bin/semver.js" } }, - "node_modules/eslint-config-next": { - "version": "13.4.19", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.19.tgz", - "integrity": "sha512-WE8367sqMnjhWHvR5OivmfwENRQ1ixfNE9hZwQqNCsd+iM3KnuMc1V8Pt6ytgjxjf23D+xbesADv9x3xaKfT3g==", - "dependencies": { - "@next/eslint-plugin-next": "13.4.19", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/eslint-config-prettier": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -10681,17 +11743,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-config-turbo": { - "version": "1.10.16", - "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-1.10.16.tgz", - "integrity": "sha512-O3NQI72bQHV7FvSC6lWj66EGx8drJJjuT1kuInn6nbMLOHdMBhSUX/8uhTAlHRQdlxZk2j9HtgFCIzSc93w42g==", - "dependencies": { - "eslint-plugin-turbo": "1.10.16" - }, - "peerDependencies": { - "eslint": ">6.6.0" - } - }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -10844,55 +11895,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, "node_modules/eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", @@ -10904,80 +11906,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-turbo": { - "version": "1.10.16", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-1.10.16.tgz", - "integrity": "sha512-ZjrR88MTN64PNGufSEcM0tf+V1xFYVbeiMeuIqr0aiABGomxFLo4DBkQ7WI4WzkZtWQSIA2sP+yxqSboEfL9MQ==", - "dependencies": { - "dotenv": "16.0.3" - }, - "peerDependencies": { - "eslint": ">6.6.0" - } - }, - "node_modules/eslint-plugin-turbo/node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz", - "integrity": "sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==", - "dependencies": { - "eslint-rule-composer": "^0.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.0.0", - "eslint": "^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, "node_modules/eslint-rule-composer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", @@ -11264,11 +12192,6 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, "node_modules/fast-equals": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", @@ -11805,16 +12728,32 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12463,15 +13402,15 @@ } }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.mjs" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -13420,6 +14359,12 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -13576,27 +14521,27 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/lint-staged": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-14.0.1.tgz", - "integrity": "sha512-Mw0cL6HXnHN1ag0mN/Dg4g6sr8uf8sn98w2Oc1ECtFto9tvRF7nkXGJRbx8gPlHyoR0pLyBr2lQHbWwmUHe1Sw==", + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, "dependencies": { "chalk": "5.3.0", - "commander": "11.0.0", + "commander": "11.1.0", "debug": "4.3.4", - "execa": "7.2.0", - "lilconfig": "2.1.0", - "listr2": "6.6.1", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", - "yaml": "2.3.1" + "yaml": "2.3.4" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=18.12.0" }, "funding": { "url": "https://opencollective.com/lint-staged" @@ -13615,35 +14560,47 @@ } }, "node_modules/lint-staged/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=14.18.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" } }, "node_modules/lint-staged/node_modules/is-stream": { @@ -13658,6 +14615,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/lint-staged/node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -13671,9 +14637,9 @@ } }, "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -13712,6 +14678,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/lint-staged/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -13724,43 +14702,105 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" }, "node_modules/listr2": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", - "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, "dependencies": { - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", + "log-update": "^6.0.0", "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/load-tsconfig": { @@ -13772,6 +14812,22 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -13882,19 +14938,19 @@ } }, "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13912,6 +14968,72 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -13927,6 +15049,23 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -13952,6 +15091,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -14012,6 +15160,18 @@ "node": ">=12" } }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/make-cancellable-promise": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.3.2.tgz", @@ -15116,6 +16276,18 @@ "node": ">=10" } }, + "node_modules/mlly": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", + "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" + } + }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", @@ -15459,31 +16631,11 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-releases": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" }, - "node_modules/node-signpdf": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-signpdf/-/node-signpdf-2.0.0.tgz", - "integrity": "sha512-B6fDvD8z2v0pRntQjgPO2ARqxh0pfNwfSn6YEbP7cv6xmPgcphFwcrMA3N47LztmpVbAM3vUFUslX32L6NRYDg==", - "deprecated": "NPM package is being replaced by @signpdf. See https://github.com/vbuch/node-signpdf", - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "node-forge": "^1.2.1" - } - }, "node_modules/node-sql-parser": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-4.11.0.tgz", @@ -16134,6 +17286,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -16240,6 +17407,17 @@ "node": ">= 6" } }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, "node_modules/playwright": { "version": "1.40.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", @@ -16284,6 +17462,14 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -16497,17 +17683,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/prettier-plugin-sql": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.14.0.tgz", @@ -17015,6 +18190,51 @@ "commander": "9.4.x" } }, + "node_modules/react-email/node_modules/@esbuild/android-arm": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.4.tgz", + "integrity": "sha512-rZzb7r22m20S1S7ufIc6DC6W659yxoOrl7sKP1nCYhuvUlnCFHVSbATG4keGUtV8rDz11sRRDbWkvQZpzPaHiw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/android-arm64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.4.tgz", + "integrity": "sha512-VPuTzXFm/m2fcGfN6CiwZTlLzxrKsWbPkG7ArRFpuxyaHUm/XFHQPD4xNwZT6uUmpIHhnSjcaCmcla8COzmZ5Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/android-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.4.tgz", + "integrity": "sha512-MW+B2O++BkcOfMWmuHXB15/l1i7wXhJFqbJhp82IBOais8RBEQv2vQz/jHrDEHaY2X0QY7Wfw86SBL2PbVOr0g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/react-email/node_modules/@esbuild/darwin-arm64": { "version": "0.16.4", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.4.tgz", @@ -17030,6 +18250,276 @@ "node": ">=12" } }, + "node_modules/react-email/node_modules/@esbuild/darwin-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.4.tgz", + "integrity": "sha512-e3doCr6Ecfwd7VzlaQqEPrnbvvPjE9uoTpxG5pyLzr2rI2NMjDHmvY1E5EO81O/e9TUOLLkXA5m6T8lfjK9yAA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.4.tgz", + "integrity": "sha512-Oup3G/QxBgvvqnXWrBed7xxkFNwAwJVHZcklWyQt7YCAL5bfUkaa6FVWnR78rNQiM8MqqLiT6ZTZSdUFuVIg1w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/freebsd-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.4.tgz", + "integrity": "sha512-vAP+eYOxlN/Bpo/TZmzEQapNS8W1njECrqkTpNgvXskkkJC2AwOXwZWai/Kc2vEFZUXQttx6UJbj9grqjD/+9Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-arm": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.4.tgz", + "integrity": "sha512-A47ZmtpIPyERxkSvIv+zLd6kNIOtJH03XA0Hy7jaceRDdQaQVGSDt4mZqpWqJYgDk9rg96aglbF6kCRvPGDSUA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-arm64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.4.tgz", + "integrity": "sha512-2zXoBhv4r5pZiyjBKrOdFP4CXOChxXiYD50LRUU+65DkdS5niPFHbboKZd/c81l0ezpw7AQnHeoCy5hFrzzs4g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-ia32": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.4.tgz", + "integrity": "sha512-uxdSrpe9wFhz4yBwt2kl2TxS/NWEINYBUFIxQtaEVtglm1eECvsj1vEKI0KX2k2wCe17zDdQ3v+jVxfwVfvvjw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-loong64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.4.tgz", + "integrity": "sha512-peDrrUuxbZ9Jw+DwLCh/9xmZAk0p0K1iY5d2IcwmnN+B87xw7kujOkig6ZRcZqgrXgeRGurRHn0ENMAjjD5DEg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-mips64el": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.4.tgz", + "integrity": "sha512-sD9EEUoGtVhFjjsauWjflZklTNr57KdQ6xfloO4yH1u7vNQlOfAlhEzbyBKfgbJlW7rwXYBdl5/NcZ+Mg2XhQA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-ppc64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.4.tgz", + "integrity": "sha512-X1HSqHUX9D+d0l6/nIh4ZZJ94eQky8d8z6yxAptpZE3FxCWYWvTDd9X9ST84MGZEJx04VYUD/AGgciddwO0b8g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-riscv64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.4.tgz", + "integrity": "sha512-97ANpzyNp0GTXCt6SRdIx1ngwncpkV/z453ZuxbnBROCJ5p/55UjhbaG23UdHj88fGWLKPFtMoU4CBacz4j9FA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-s390x": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.4.tgz", + "integrity": "sha512-pUvPQLPmbEeJRPjP0DYTC1vjHyhrnCklQmCGYbipkep+oyfTn7GTBJXoPodR7ZS5upmEyc8lzAkn2o29wD786A==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/linux-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.4.tgz", + "integrity": "sha512-N55Q0mJs3Sl8+utPRPBrL6NLYZKBCLLx0bme/+RbjvMforTGGzFvsRl4xLTZMUBFC1poDzBEPTEu5nxizQ9Nlw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/netbsd-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.4.tgz", + "integrity": "sha512-LHSJLit8jCObEQNYkgsDYBh2JrJT53oJO2HVdkSYLa6+zuLJh0lAr06brXIkljrlI+N7NNW1IAXGn/6IZPi3YQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/openbsd-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.4.tgz", + "integrity": "sha512-nLgdc6tWEhcCFg/WVFaUxHcPK3AP/bh+KEwKtl69Ay5IBqUwKDaq/6Xk0E+fh/FGjnLwqFSsarsbPHeKM8t8Sw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/sunos-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.4.tgz", + "integrity": "sha512-08SluG24GjPO3tXKk95/85n9kpyZtXCVwURR2i4myhrOfi3jspClV0xQQ0W0PYWHioJj+LejFMt41q+PG3mlAQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/win32-arm64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.4.tgz", + "integrity": "sha512-yYiRDQcqLYQSvNQcBKN7XogbrSvBE45FEQdH8fuXPl7cngzkCvpsG2H9Uey39IjQ6gqqc+Q4VXYHsQcKW0OMjQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/win32-ia32": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.4.tgz", + "integrity": "sha512-5rabnGIqexekYkh9zXG5waotq8mrdlRoBqAktjx2W3kb0zsI83mdCwrcAeKYirnUaTGztR5TxXcXmQrEzny83w==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/react-email/node_modules/@esbuild/win32-x64": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.4.tgz", + "integrity": "sha512-sN/I8FMPtmtT2Yw+Dly8Ur5vQ5a/RmC8hW7jO9PtPSQUPkowxWpcUZnqOggU7VwyT3Xkj6vcXWd3V/qTXwultQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/react-email/node_modules/@react-email/render": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.6.tgz", @@ -18578,6 +20068,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -18817,6 +20313,12 @@ "sql-formatter": "bin/sql-formatter-cli.cjs" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/stampit": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz", @@ -18858,6 +20360,12 @@ "node": ">= 0.6" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, "node_modules/stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", @@ -19108,6 +20616,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", + "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", + "dev": true, + "dependencies": { + "js-tokens": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "dev": true + }, "node_modules/stripe": { "version": "12.18.0", "resolved": "https://registry.npmjs.org/stripe/-/stripe-12.18.0.tgz", @@ -19569,6 +21095,30 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinybench": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", + "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -20181,6 +21731,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", @@ -20300,6 +21859,12 @@ "node": "*" } }, + "node_modules/ufo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -20746,6 +22311,396 @@ "d3-timer": "^3.0.1" } }, + "node_modules/vite": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.6.tgz", + "integrity": "sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", + "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/vite/node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vite/node_modules/rollup": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", + "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.13.0", + "@rollup/rollup-android-arm64": "4.13.0", + "@rollup/rollup-darwin-arm64": "4.13.0", + "@rollup/rollup-darwin-x64": "4.13.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", + "@rollup/rollup-linux-arm64-gnu": "4.13.0", + "@rollup/rollup-linux-arm64-musl": "4.13.0", + "@rollup/rollup-linux-riscv64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-musl": "4.13.0", + "@rollup/rollup-win32-arm64-msvc": "4.13.0", + "@rollup/rollup-win32-ia32-msvc": "4.13.0", + "@rollup/rollup-win32-x64-msvc": "4.13.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/vitest": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", + "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.3.1", + "@vitest/runner": "1.3.1", + "@vitest/snapshot": "1.3.1", + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.2", + "vite": "^5.0.0", + "vite-node": "1.3.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.3.1", + "@vitest/ui": "1.3.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wait-on": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", @@ -20907,6 +22862,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -21549,19 +23520,690 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "6.8.0", - "@typescript-eslint/parser": "6.8.0", - "eslint": "^8.40.0", - "eslint-config-next": "13.4.19", - "eslint-config-prettier": "^8.8.0", - "eslint-config-turbo": "^1.9.3", - "eslint-plugin-package-json": "^0.2.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-unused-imports": "^3.0.0", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", + "eslint": "^8.57.0", + "eslint-config-next": "^14.1.3", + "eslint-config-turbo": "^1.12.5", + "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-unused-imports": "^3.1.0", "typescript": "5.2.2" } }, + "packages/eslint-config/node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "packages/eslint-config/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "packages/eslint-config/node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "packages/eslint-config/node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + }, + "packages/eslint-config/node_modules/@next/eslint-plugin-next": { + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.3.tgz", + "integrity": "sha512-VCnZI2cy77Yaj3L7Uhs3+44ikMM1VD/fBMwvTBb3hIaTIuqa+DmG4dhUDq+MASu3yx97KhgsVJbsas0XuiKyww==", + "dependencies": { + "glob": "10.3.10" + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "dependencies": { + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/scope-manager": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/type-utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/types": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "packages/eslint-config/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "packages/eslint-config/node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "packages/eslint-config/node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/eslint-config/node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "packages/eslint-config/node_modules/es-abstract": { + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/es-iterator-helpers": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", + "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.4", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "packages/eslint-config/node_modules/eslint-config-next": { + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.3.tgz", + "integrity": "sha512-sUCpWlGuHpEhI0pIT0UtdSLJk5Z8E2DYinPTwsBiWaSYQomchdl0i60pjynY48+oXvtyWMQ7oE+G3m49yrfacg==", + "dependencies": { + "@next/eslint-plugin-next": "14.1.3", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/eslint-config/node_modules/eslint-config-next/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/eslint-config/node_modules/eslint-config-turbo": { + "version": "1.12.5", + "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-1.12.5.tgz", + "integrity": "sha512-wXytbX+vTzQ6rwgM6sIr447tjYJBlRj5V/eBFNGNXw5Xs1R715ppPYhbmxaFbkrWNQSGJsWRrYGAlyq0sT/OsQ==", + "dependencies": { + "eslint-plugin-turbo": "1.12.5" + }, + "peerDependencies": { + "eslint": ">6.6.0" + } + }, "packages/eslint-config/node_modules/eslint-plugin-package-json": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.2.0.tgz", @@ -21579,6 +24221,436 @@ "eslint": ">=4.7.0" } }, + "packages/eslint-config/node_modules/eslint-plugin-react": { + "version": "7.34.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.0.tgz", + "integrity": "sha512-MeVXdReleBTdkz/bvcQMSnCXGi+c9kvy51IpinjnJgutl3YTHWsDdke7Z1ufZpGfDG8xduBDKyjtB9JH1eBKIQ==", + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "packages/eslint-config/node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/eslint-config/node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "packages/eslint-config/node_modules/eslint-plugin-turbo": { + "version": "1.12.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-1.12.5.tgz", + "integrity": "sha512-cXy7mCzAdngBTJIWH4DASXHy0vQpujWDBqRTu0YYqCN/QEGsi3HWM+STZEbPYELdjtm5EsN2HshOSSqWnjdRHg==", + "dependencies": { + "dotenv": "16.0.3" + }, + "peerDependencies": { + "eslint": ">6.6.0" + } + }, + "packages/eslint-config/node_modules/eslint-plugin-unused-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.1.0.tgz", + "integrity": "sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==", + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "6 - 7", + "eslint": "8" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "packages/eslint-config/node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/eslint-config/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "packages/eslint-config/node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/eslint-config/node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "packages/eslint-config/node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "packages/eslint-config/node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/eslint-config/node_modules/typed-array-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "packages/eslint-config/node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -21591,6 +24663,24 @@ "node": ">=14.17" } }, + "packages/eslint-config/node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "packages/lib": { "name": "@documenso/lib", "version": "1.0.0", @@ -21697,14 +24787,13 @@ "version": "1.0.0", "license": "AGPLv3", "dependencies": { + "@documenso/pdf-sign": "^0.1.0", "@documenso/tsconfig": "*", - "node-forge": "^1.3.1", - "node-signpdf": "^2.0.0", "pdf-lib": "^1.17.1", "ts-pattern": "^5.0.5" }, "devDependencies": { - "@types/node-forge": "^1.3.4" + "vitest": "^1.3.1" } }, "packages/tailwind-config": { diff --git a/package.json b/package.json index cbaa2a1eb..bafada07a 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "dotenv-cli": "^7.3.0", "eslint": "^8.40.0", "eslint-config-custom": "*", - "husky": "^8.0.0", - "lint-staged": "^14.0.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", "prettier": "^2.5.1", "rimraf": "^5.0.1", "turbo": "^1.9.3" @@ -48,6 +48,7 @@ "packages/*" ], "dependencies": { + "@documenso/pdf-sign": "^0.1.0", "next-runtime-env": "^3.2.0" }, "overrides": { diff --git a/packages/app-tests/e2e/pr-718-add-stepper-component.spec.ts b/packages/app-tests/e2e/pr-718-add-stepper-component.spec.ts index 781b9eb3d..91203d32c 100644 --- a/packages/app-tests/e2e/pr-718-add-stepper-component.spec.ts +++ b/packages/app-tests/e2e/pr-718-add-stepper-component.spec.ts @@ -1,6 +1,9 @@ import { expect, test } from '@playwright/test'; import path from 'node:path'; +import { getDocumentByToken } from '@documenso/lib/server-only/document/get-document-by-token'; +import { getRecipientByEmail } from '@documenso/lib/server-only/recipient/get-recipient-by-email'; +import { DocumentStatus } from '@documenso/prisma/client'; import { TEST_USER } from '@documenso/prisma/seed/pr-718-add-stepper-component'; test(`[PR-718]: should be able to create a document`, async ({ page }) => { @@ -73,3 +76,264 @@ test(`[PR-718]: should be able to create a document`, async ({ page }) => { // Assert document was created await expect(page.getByRole('link', { name: documentTitle })).toBeVisible(); }); + +test('should be able to create a document with multiple recipients', async ({ page }) => { + await page.goto('/signin'); + + const documentTitle = `example-${Date.now()}.pdf`; + + // Sign in + await page.getByLabel('Email').fill(TEST_USER.email); + await page.getByLabel('Password', { exact: true }).fill(TEST_USER.password); + await page.getByRole('button', { name: 'Sign In' }).click(); + + // Upload document + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.locator('input[type=file]').evaluate((e) => { + if (e instanceof HTMLInputElement) { + e.click(); + } + }), + ]); + + await fileChooser.setFiles(path.join(__dirname, '../../../assets/example.pdf')); + + // Wait to be redirected to the edit page + await page.waitForURL(/\/documents\/\d+/); + + // Set title + await expect(page.getByRole('heading', { name: 'Add Title' })).toBeVisible(); + + await page.getByLabel('Title').fill(documentTitle); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add signers + await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible(); + + await page.getByLabel('Email*').fill('user1@example.com'); + await page.getByLabel('Name').fill('User 1'); + + await page.getByRole('button', { name: 'Add Signer' }).click(); + + await page.getByLabel('Email*').nth(1).fill('user2@example.com'); + await page.getByLabel('Name').nth(1).fill('User 2'); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add fields + await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible(); + + await page.getByRole('button', { name: 'User 1 Signature' }).click(); + await page.locator('canvas').click({ + position: { + x: 100, + y: 100, + }, + }); + + await page.getByRole('button', { name: 'Email Email' }).click(); + await page.locator('canvas').click({ + position: { + x: 100, + y: 200, + }, + }); + + await page.getByText('User 1 (user1@example.com)').click(); + await page.getByText('User 2 (user2@example.com)').click(); + + await page.getByRole('button', { name: 'User 2 Signature' }).click(); + await page.locator('canvas').click({ + position: { + x: 500, + y: 100, + }, + }); + + await page.getByRole('button', { name: 'Email Email' }).click(); + await page.locator('canvas').click({ + position: { + x: 500, + y: 200, + }, + }); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add subject and send + await expect(page.getByRole('heading', { name: 'Add Subject' })).toBeVisible(); + await page.getByRole('button', { name: 'Send' }).click(); + + await page.waitForURL('/documents'); + + // Assert document was created + await expect(page.getByRole('link', { name: documentTitle })).toBeVisible(); +}); + +test('should be able to create, send and sign a document', async ({ page }) => { + await page.goto('/signin'); + + const documentTitle = `example-${Date.now()}.pdf`; + + // Sign in + await page.getByLabel('Email').fill(TEST_USER.email); + await page.getByLabel('Password', { exact: true }).fill(TEST_USER.password); + await page.getByRole('button', { name: 'Sign In' }).click(); + + // Upload document + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.locator('input[type=file]').evaluate((e) => { + if (e instanceof HTMLInputElement) { + e.click(); + } + }), + ]); + + await fileChooser.setFiles(path.join(__dirname, '../../../assets/example.pdf')); + + // Wait to be redirected to the edit page + await page.waitForURL(/\/documents\/\d+/); + + // Set title + await expect(page.getByRole('heading', { name: 'Add Title' })).toBeVisible(); + + await page.getByLabel('Title').fill(documentTitle); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add signers + await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible(); + + await page.getByLabel('Email*').fill('user1@example.com'); + await page.getByLabel('Name').fill('User 1'); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add fields + await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add subject and send + await expect(page.getByRole('heading', { name: 'Add Subject' })).toBeVisible(); + await page.getByRole('button', { name: 'Send' }).click(); + + await page.waitForURL('/documents'); + + // Assert document was created + await expect(page.getByRole('link', { name: documentTitle })).toBeVisible(); + await page.getByRole('link', { name: documentTitle }).click(); + + const url = await page.url().split('/'); + const documentId = url[url.length - 1]; + + const { token } = await getRecipientByEmail({ + email: 'user1@example.com', + documentId: Number(documentId), + }); + + await page.goto(`/sign/${token}`); + await page.waitForURL(`/sign/${token}`); + + // Check if document has been viewed + const { status } = await getDocumentByToken({ token }); + expect(status).toBe(DocumentStatus.PENDING); + + await page.getByRole('button', { name: 'Complete' }).click(); + await expect(page.getByRole('dialog').getByText('Sign Document')).toBeVisible(); + await page.getByRole('button', { name: 'Sign' }).click(); + + await page.waitForURL(`/sign/${token}/complete`); + await expect(page.getByText('You have signed')).toBeVisible(); + + // Check if document has been signed + const { status: completedStatus } = await getDocumentByToken({ token }); + expect(completedStatus).toBe(DocumentStatus.COMPLETED); +}); + +test('should be able to create, send with redirect url, sign a document and redirect to redirect url', async ({ + page, +}) => { + await page.goto('/signin'); + + const documentTitle = `example-${Date.now()}.pdf`; + + // Sign in + await page.getByLabel('Email').fill(TEST_USER.email); + await page.getByLabel('Password', { exact: true }).fill(TEST_USER.password); + await page.getByRole('button', { name: 'Sign In' }).click(); + + // Upload document + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.locator('input[type=file]').evaluate((e) => { + if (e instanceof HTMLInputElement) { + e.click(); + } + }), + ]); + + await fileChooser.setFiles(path.join(__dirname, '../../../assets/example.pdf')); + + // Wait to be redirected to the edit page + await page.waitForURL(/\/documents\/\d+/); + + // Set title + await expect(page.getByRole('heading', { name: 'Add Title' })).toBeVisible(); + + await page.getByLabel('Title').fill(documentTitle); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add signers + await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible(); + + await page.getByLabel('Email*').fill('user1@example.com'); + await page.getByLabel('Name').fill('User 1'); + + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add fields + await expect(page.getByRole('heading', { name: 'Add Fields' })).toBeVisible(); + await page.getByRole('button', { name: 'Continue' }).click(); + + // Add subject and send + await expect(page.getByRole('heading', { name: 'Add Subject' })).toBeVisible(); + await page.getByRole('button', { name: 'Advanced Options' }).click(); + await page.getByLabel('Redirect URL').fill('https://documenso.com'); + + await page.getByRole('button', { name: 'Send' }).click(); + + await page.waitForURL('/documents'); + + // Assert document was created + await expect(page.getByRole('link', { name: documentTitle })).toBeVisible(); + await page.getByRole('link', { name: documentTitle }).click(); + + const url = await page.url().split('/'); + const documentId = url[url.length - 1]; + + const { token } = await getRecipientByEmail({ + email: 'user1@example.com', + documentId: Number(documentId), + }); + + await page.goto(`/sign/${token}`); + await page.waitForURL(`/sign/${token}`); + + // Check if document has been viewed + const { status } = await getDocumentByToken({ token }); + expect(status).toBe(DocumentStatus.PENDING); + + await page.getByRole('button', { name: 'Complete' }).click(); + await expect(page.getByRole('dialog').getByText('Sign Document')).toBeVisible(); + await page.getByRole('button', { name: 'Sign' }).click(); + + await page.waitForURL('https://documenso.com'); + + // Check if document has been signed + const { status: completedStatus } = await getDocumentByToken({ token }); + expect(completedStatus).toBe(DocumentStatus.COMPLETED); +}); diff --git a/packages/app-tests/e2e/test-update-user-name.spec.ts b/packages/app-tests/e2e/test-update-user-name.spec.ts new file mode 100644 index 000000000..509db651b --- /dev/null +++ b/packages/app-tests/e2e/test-update-user-name.spec.ts @@ -0,0 +1,37 @@ +import { expect, test } from '@playwright/test'; + +import { getUserByEmail } from '@documenso/lib/server-only/user/get-user-by-email'; +import { seedUser } from '@documenso/prisma/seed/users'; + +import { manualLogin } from './fixtures/authentication'; + +test('update user name', async ({ page }) => { + const user = await seedUser(); + + await manualLogin({ + page, + email: user.email, + redirectPath: '/settings/profile', + }); + + await page.getByLabel('Full Name').fill('John Doe'); + + const canvas = page.locator('canvas'); + const box = await canvas.boundingBox(); + + if (box) { + await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); + await page.mouse.down(); + await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4); + await page.mouse.up(); + } + + await page.getByRole('button', { name: 'Update profile' }).click(); + + // wait for it to finish + await expect(page.getByText('Profile updated', { exact: true })).toBeVisible(); + + await page.waitForURL('/settings/profile'); + + expect((await getUserByEmail({ email: user.email })).name).toEqual('John Doe'); +}); diff --git a/packages/app-tests/package.json b/packages/app-tests/package.json index 9dcb32f7d..84f14d469 100644 --- a/packages/app-tests/package.json +++ b/packages/app-tests/package.json @@ -6,6 +6,7 @@ "main": "index.js", "scripts": { "test:dev": "playwright test", + "test-ui:dev": "playwright test --ui", "test:e2e": "start-server-and-test \"npm run start -w @documenso/web\" http://localhost:3000 \"playwright test\"" }, "keywords": [], diff --git a/packages/eslint-config/index.cjs b/packages/eslint-config/index.cjs index aef6a944e..c4524dc3d 100644 --- a/packages/eslint-config/index.cjs +++ b/packages/eslint-config/index.cjs @@ -4,16 +4,15 @@ module.exports = { 'turbo', 'eslint:recommended', 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', 'plugin:package-json/recommended', ], - plugins: ['prettier', 'package-json', 'unused-imports'], + plugins: ['package-json', 'unused-imports'], env: { + es2022: true, node: true, browser: true, - es6: true, }, parser: '@typescript-eslint/parser', diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index d519a3362..4d25e1bd8 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -7,16 +7,14 @@ "clean": "rimraf node_modules" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "6.8.0", - "@typescript-eslint/parser": "6.8.0", - "eslint": "^8.40.0", - "eslint-config-next": "13.4.19", - "eslint-config-prettier": "^8.8.0", - "eslint-config-turbo": "^1.9.3", - "eslint-plugin-package-json": "^0.2.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-unused-imports": "^3.0.0", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", + "eslint": "^8.57.0", + "eslint-config-next": "^14.1.3", + "eslint-config-turbo": "^1.12.5", + "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-unused-imports": "^3.1.0", "typescript": "5.2.2" } } diff --git a/packages/lib/constants/date-formats.ts b/packages/lib/constants/date-formats.ts index 5b36cefdf..6b0dd69c5 100644 --- a/packages/lib/constants/date-formats.ts +++ b/packages/lib/constants/date-formats.ts @@ -13,7 +13,7 @@ export const DATE_FORMATS = [ { key: 'YYYYMMDD', label: 'YYYY-MM-DD', - value: 'YYYY-MM-DD', + value: 'yyyy-MM-dd', }, { key: 'DDMMYYYY', diff --git a/packages/lib/server-only/2fa/disable-2fa.ts b/packages/lib/server-only/2fa/disable-2fa.ts index aba763d2d..7d77ce363 100644 --- a/packages/lib/server-only/2fa/disable-2fa.ts +++ b/packages/lib/server-only/2fa/disable-2fa.ts @@ -1,40 +1,30 @@ -import { compare } from '@node-rs/bcrypt'; - import { prisma } from '@documenso/prisma'; import type { User } from '@documenso/prisma/client'; import { UserSecurityAuditLogType } from '@documenso/prisma/client'; -import { ErrorCode } from '../../next-auth/error-codes'; +import { AppError } from '../../errors/app-error'; import type { RequestMetadata } from '../../universal/extract-request-metadata'; import { validateTwoFactorAuthentication } from './validate-2fa'; type DisableTwoFactorAuthenticationOptions = { user: User; - backupCode: string; - password: string; + token: string; requestMetadata?: RequestMetadata; }; export const disableTwoFactorAuthentication = async ({ - backupCode, + token, user, - password, requestMetadata, }: DisableTwoFactorAuthenticationOptions) => { - if (!user.password) { - throw new Error(ErrorCode.USER_MISSING_PASSWORD); - } - - const isCorrectPassword = await compare(password, user.password); - - if (!isCorrectPassword) { - throw new Error(ErrorCode.INCORRECT_PASSWORD); - } - - const isValid = await validateTwoFactorAuthentication({ backupCode, user }); + let isValid = await validateTwoFactorAuthentication({ totpCode: token, user }); if (!isValid) { - throw new Error(ErrorCode.INCORRECT_TWO_FACTOR_BACKUP_CODE); + isValid = await validateTwoFactorAuthentication({ backupCode: token, user }); + } + + if (!isValid) { + throw new AppError('INCORRECT_TWO_FACTOR_CODE'); } await prisma.$transaction(async (tx) => { diff --git a/packages/lib/server-only/2fa/enable-2fa.ts b/packages/lib/server-only/2fa/enable-2fa.ts index 19a2b67c2..cf13c59e6 100644 --- a/packages/lib/server-only/2fa/enable-2fa.ts +++ b/packages/lib/server-only/2fa/enable-2fa.ts @@ -1,7 +1,7 @@ -import { ErrorCode } from '@documenso/lib/next-auth/error-codes'; import { prisma } from '@documenso/prisma'; import { type User, UserSecurityAuditLogType } from '@documenso/prisma/client'; +import { AppError } from '../../errors/app-error'; import type { RequestMetadata } from '../../universal/extract-request-metadata'; import { getBackupCodes } from './get-backup-code'; import { verifyTwoFactorAuthenticationToken } from './verify-2fa-token'; @@ -17,25 +17,38 @@ export const enableTwoFactorAuthentication = async ({ code, requestMetadata, }: EnableTwoFactorAuthenticationOptions) => { - if (user.identityProvider !== 'DOCUMENSO') { - throw new Error(ErrorCode.INCORRECT_IDENTITY_PROVIDER); - } - if (user.twoFactorEnabled) { - throw new Error(ErrorCode.TWO_FACTOR_ALREADY_ENABLED); + throw new AppError('TWO_FACTOR_ALREADY_ENABLED'); } if (!user.twoFactorSecret) { - throw new Error(ErrorCode.TWO_FACTOR_SETUP_REQUIRED); + throw new AppError('TWO_FACTOR_SETUP_REQUIRED'); } const isValidToken = await verifyTwoFactorAuthenticationToken({ user, totpCode: code }); if (!isValidToken) { - throw new Error(ErrorCode.INCORRECT_TWO_FACTOR_CODE); + throw new AppError('INCORRECT_TWO_FACTOR_CODE'); } - const updatedUser = await prisma.$transaction(async (tx) => { + let recoveryCodes: string[] = []; + + await prisma.$transaction(async (tx) => { + const updatedUser = await tx.user.update({ + where: { + id: user.id, + }, + data: { + twoFactorEnabled: true, + }, + }); + + recoveryCodes = getBackupCodes({ user: updatedUser }) ?? []; + + if (recoveryCodes.length === 0) { + throw new AppError('MISSING_BACKUP_CODE'); + } + await tx.userSecurityAuditLog.create({ data: { userId: user.id, @@ -44,18 +57,7 @@ export const enableTwoFactorAuthentication = async ({ ipAddress: requestMetadata?.ipAddress, }, }); - - return await tx.user.update({ - where: { - id: user.id, - }, - data: { - twoFactorEnabled: true, - }, - }); }); - const recoveryCodes = getBackupCodes({ user: updatedUser }); - return { recoveryCodes }; }; diff --git a/packages/lib/server-only/2fa/setup-2fa.ts b/packages/lib/server-only/2fa/setup-2fa.ts index e94676121..cc08510d0 100644 --- a/packages/lib/server-only/2fa/setup-2fa.ts +++ b/packages/lib/server-only/2fa/setup-2fa.ts @@ -1,4 +1,3 @@ -import { compare } from '@node-rs/bcrypt'; import { base32 } from '@scure/base'; import crypto from 'crypto'; import { createTOTPKeyURI } from 'oslo/otp'; @@ -12,14 +11,12 @@ import { symmetricEncrypt } from '../../universal/crypto'; type SetupTwoFactorAuthenticationOptions = { user: User; - password: string; }; const ISSUER = 'Documenso'; export const setupTwoFactorAuthentication = async ({ user, - password, }: SetupTwoFactorAuthenticationOptions) => { const key = DOCUMENSO_ENCRYPTION_KEY; @@ -27,20 +24,6 @@ export const setupTwoFactorAuthentication = async ({ throw new Error(ErrorCode.MISSING_ENCRYPTION_KEY); } - if (user.identityProvider !== 'DOCUMENSO') { - throw new Error(ErrorCode.INCORRECT_IDENTITY_PROVIDER); - } - - if (!user.password) { - throw new Error(ErrorCode.USER_MISSING_PASSWORD); - } - - const isCorrectPassword = await compare(password, user.password); - - if (!isCorrectPassword) { - throw new Error(ErrorCode.INCORRECT_PASSWORD); - } - const secret = crypto.randomBytes(10); const backupCodes = Array.from({ length: 10 }) diff --git a/packages/lib/server-only/2fa/view-backup-codes.ts b/packages/lib/server-only/2fa/view-backup-codes.ts new file mode 100644 index 000000000..a57253116 --- /dev/null +++ b/packages/lib/server-only/2fa/view-backup-codes.ts @@ -0,0 +1,30 @@ +import type { User } from '@documenso/prisma/client'; + +import { AppError } from '../../errors/app-error'; +import { getBackupCodes } from './get-backup-code'; +import { validateTwoFactorAuthentication } from './validate-2fa'; + +type ViewBackupCodesOptions = { + user: User; + token: string; +}; + +export const viewBackupCodes = async ({ token, user }: ViewBackupCodesOptions) => { + let isValid = await validateTwoFactorAuthentication({ totpCode: token, user }); + + if (!isValid) { + isValid = await validateTwoFactorAuthentication({ backupCode: token, user }); + } + + if (!isValid) { + throw new AppError('INCORRECT_TWO_FACTOR_CODE'); + } + + const backupCodes = getBackupCodes({ user }); + + if (!backupCodes) { + throw new AppError('MISSING_BACKUP_CODE'); + } + + return backupCodes; +}; diff --git a/packages/lib/server-only/document/get-document-by-token.ts b/packages/lib/server-only/document/get-document-by-token.ts index b8aa1c465..6add46c1d 100644 --- a/packages/lib/server-only/document/get-document-by-token.ts +++ b/packages/lib/server-only/document/get-document-by-token.ts @@ -30,6 +30,27 @@ export interface GetDocumentAndRecipientByTokenOptions { */ requireAccessAuth?: boolean; } +export type GetDocumentByTokenOptions = { + token: string; +}; + +export const getDocumentByToken = async ({ token }: GetDocumentByTokenOptions) => { + if (!token) { + throw new Error('Missing token'); + } + + const result = await prisma.document.findFirstOrThrow({ + where: { + Recipient: { + some: { + token, + }, + }, + }, + }); + + return result; +}; export type DocumentAndSender = Awaited>; diff --git a/packages/lib/server-only/user/get-monthly-completed-document.ts b/packages/lib/server-only/user/get-monthly-completed-document.ts new file mode 100644 index 000000000..644643bb3 --- /dev/null +++ b/packages/lib/server-only/user/get-monthly-completed-document.ts @@ -0,0 +1,35 @@ +import { DateTime } from 'luxon'; + +import { prisma } from '@documenso/prisma'; + +export type GetCompletedDocumentsMonthlyResult = Array<{ + month: string; + count: number; + cume_count: number; +}>; + +type GetCompletedDocumentsMonthlyQueryResult = Array<{ + month: Date; + count: bigint; + cume_count: bigint; +}>; + +export const getCompletedDocumentsMonthly = async () => { + const result = await prisma.$queryRaw` + SELECT + DATE_TRUNC('month', "updatedAt") AS "month", + COUNT("id") as "count", + SUM(COUNT("id")) OVER (ORDER BY DATE_TRUNC('month', "updatedAt")) as "cume_count" + FROM "Document" + WHERE "status" = 'COMPLETED' + GROUP BY "month" + ORDER BY "month" DESC + LIMIT 12 + `; + + return result.map((row) => ({ + month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'), + count: Number(row.count), + cume_count: Number(row.cume_count), + })); +}; diff --git a/packages/prisma/seed/pr-711-deletion-of-documents.ts b/packages/prisma/seed/pr-711-deletion-of-documents.ts index 5365ecf47..d2706b734 100644 --- a/packages/prisma/seed/pr-711-deletion-of-documents.ts +++ b/packages/prisma/seed/pr-711-deletion-of-documents.ts @@ -182,6 +182,7 @@ const createCompletedDocument = async (sender: User, recipients: User[]) => { title: `[${PULL_REQUEST_NUMBER}] Document 1 - Completed`, status: DocumentStatus.COMPLETED, documentDataId: documentData.id, + completedAt: new Date(), userId: sender.id, }, }); diff --git a/packages/signing/constants/byte-range.ts b/packages/signing/constants/byte-range.ts new file mode 100644 index 000000000..ee3f23814 --- /dev/null +++ b/packages/signing/constants/byte-range.ts @@ -0,0 +1,3 @@ +// We use stars as a placeholder since it's easy to find and replace, +// the length of the placeholder is to support larger pdf files +export const BYTE_RANGE_PLACEHOLDER = '**********'; diff --git a/packages/signing/helpers/addSigningPlaceholder.ts b/packages/signing/helpers/add-signing-placeholder.ts similarity index 89% rename from packages/signing/helpers/addSigningPlaceholder.ts rename to packages/signing/helpers/add-signing-placeholder.ts index 211a534ea..cdee18863 100644 --- a/packages/signing/helpers/addSigningPlaceholder.ts +++ b/packages/signing/helpers/add-signing-placeholder.ts @@ -1,4 +1,3 @@ -import signer from 'node-signpdf'; import { PDFArray, PDFDocument, @@ -9,6 +8,8 @@ import { rectangle, } from 'pdf-lib'; +import { BYTE_RANGE_PLACEHOLDER } from '../constants/byte-range'; + export type AddSigningPlaceholderOptions = { pdf: Buffer; }; @@ -20,9 +21,9 @@ export const addSigningPlaceholder = async ({ pdf }: AddSigningPlaceholderOption const byteRange = PDFArray.withContext(doc.context); byteRange.push(PDFNumber.of(0)); - byteRange.push(PDFName.of(signer.byteRangePlaceholder)); - byteRange.push(PDFName.of(signer.byteRangePlaceholder)); - byteRange.push(PDFName.of(signer.byteRangePlaceholder)); + byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER)); + byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER)); + byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER)); const signature = doc.context.obj({ Type: 'Sig', diff --git a/packages/signing/helpers/update-signing-placeholder.test.ts b/packages/signing/helpers/update-signing-placeholder.test.ts new file mode 100644 index 000000000..8adc7d44f --- /dev/null +++ b/packages/signing/helpers/update-signing-placeholder.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, it } from 'vitest'; + +import { updateSigningPlaceholder } from './update-signing-placeholder'; + +describe('updateSigningPlaceholder', () => { + const pdf = Buffer.from(` + 20 0 obj + << + /Type /Sig + /Filter /Adobe.PPKLite + /SubFilter /adbe.pkcs7.detached + /ByteRange [ 0 /********** /********** /********** ] + /Contents <0000000000000000000000000000000000000000000000000000000> + /Reason (Signed by Documenso) + /M (D:20210101000000Z) + >> + endobj + `); + + it('should not throw an error', () => { + expect(() => updateSigningPlaceholder({ pdf })).not.toThrowError(); + }); + + it('should not modify the original PDF', () => { + const result = updateSigningPlaceholder({ pdf }); + + expect(result.pdf).not.toEqual(pdf); + }); + + it('should return a PDF with the same length as the original', () => { + const result = updateSigningPlaceholder({ pdf }); + + expect(result.pdf).toHaveLength(pdf.length); + }); + + it('should update the byte range and return it', () => { + const result = updateSigningPlaceholder({ pdf }); + + expect(result.byteRange).toEqual([0, 184, 241, 92]); + }); + + it('should only update the last signature in the PDF', () => { + const pdf = Buffer.from(` + 20 0 obj + << + /Type /Sig + /Filter /Adobe.PPKLite + /SubFilter /adbe.pkcs7.detached + /ByteRange [ 0 /********** /********** /********** ] + /Contents <0000000000000000000000000000000000000000000000000000000> + /Reason (Signed by Documenso) + /M (D:20210101000000Z) + >> + endobj + 21 0 obj + << + /Type /Sig + /Filter /Adobe.PPKLite + /SubFilter /adbe.pkcs7.detached + /ByteRange [ 0 /********** /********** /********** ] + /Contents <0000000000000000000000000000000000000000000000000000000> + /Reason (Signed by Documenso) + /M (D:20210101000000Z) + >> + endobj + `); + + const result = updateSigningPlaceholder({ pdf }); + + expect(result.byteRange).toEqual([0, 512, 569, 92]); + }); +}); diff --git a/packages/signing/helpers/update-signing-placeholder.ts b/packages/signing/helpers/update-signing-placeholder.ts new file mode 100644 index 000000000..c0c95f859 --- /dev/null +++ b/packages/signing/helpers/update-signing-placeholder.ts @@ -0,0 +1,39 @@ +export type UpdateSigningPlaceholderOptions = { + pdf: Buffer; +}; + +export const updateSigningPlaceholder = ({ pdf }: UpdateSigningPlaceholderOptions) => { + const length = pdf.length; + + const byteRangePos = pdf.lastIndexOf('/ByteRange'); + const byteRangeStart = pdf.indexOf('[', byteRangePos); + const byteRangeEnd = pdf.indexOf(']', byteRangePos); + + const byteRangeSlice = pdf.subarray(byteRangeStart, byteRangeEnd + 1); + + const signaturePos = pdf.indexOf('/Contents', byteRangeEnd); + const signatureStart = pdf.indexOf('<', signaturePos); + const signatureEnd = pdf.indexOf('>', signaturePos); + + const signatureSlice = pdf.subarray(signatureStart, signatureEnd + 1); + + const byteRange = [0, 0, 0, 0]; + + byteRange[1] = signatureStart; + byteRange[2] = byteRange[1] + signatureSlice.length; + byteRange[3] = length - byteRange[2]; + + const newByteRange = `[${byteRange.join(' ')}]`.padEnd(byteRangeSlice.length, ' '); + + const updatedPdf = Buffer.concat([ + pdf.subarray(0, byteRangeStart), + Buffer.from(newByteRange), + pdf.subarray(byteRangeEnd + 1), + ]); + + if (updatedPdf.length !== length) { + throw new Error('Updated PDF length does not match original length'); + } + + return { pdf: updatedPdf, byteRange }; +}; diff --git a/packages/signing/index.ts b/packages/signing/index.ts index 06e71761f..0e24d4915 100644 --- a/packages/signing/index.ts +++ b/packages/signing/index.ts @@ -1,5 +1,6 @@ import { match } from 'ts-pattern'; +import { signWithGoogleCloudHSM } from './transports/google-cloud-hsm'; import { signWithLocalCert } from './transports/local-cert'; export type SignOptions = { @@ -11,6 +12,7 @@ export const signPdf = async ({ pdf }: SignOptions) => { return await match(transport) .with('local', async () => signWithLocalCert({ pdf })) + .with('gcloud-hsm', async () => signWithGoogleCloudHSM({ pdf })) .otherwise(() => { throw new Error(`Unsupported signing transport: ${transport}`); }); diff --git a/packages/signing/package.json b/packages/signing/package.json index 3eaab8a05..fc0bbfbf8 100644 --- a/packages/signing/package.json +++ b/packages/signing/package.json @@ -9,15 +9,15 @@ "index.ts" ], "scripts": { + "test": "vitest" }, "dependencies": { "@documenso/tsconfig": "*", - "node-forge": "^1.3.1", - "node-signpdf": "^2.0.0", + "@documenso/pdf-sign": "^0.1.0", "pdf-lib": "^1.17.1", "ts-pattern": "^5.0.5" }, "devDependencies": { - "@types/node-forge": "^1.3.4" + "vitest": "^1.3.1" } } diff --git a/packages/signing/transports/google-cloud-hsm.ts b/packages/signing/transports/google-cloud-hsm.ts new file mode 100644 index 000000000..b327c7901 --- /dev/null +++ b/packages/signing/transports/google-cloud-hsm.ts @@ -0,0 +1,79 @@ +import fs from 'node:fs'; + +import { signWithGCloud } from '@documenso/pdf-sign'; + +import { addSigningPlaceholder } from '../helpers/add-signing-placeholder'; +import { updateSigningPlaceholder } from '../helpers/update-signing-placeholder'; + +export type SignWithGoogleCloudHSMOptions = { + pdf: Buffer; +}; + +export const signWithGoogleCloudHSM = async ({ pdf }: SignWithGoogleCloudHSMOptions) => { + const keyPath = process.env.NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH; + + if (!keyPath) { + throw new Error('No certificate path provided for Google Cloud HSM signing'); + } + + // To handle hosting in serverless environments like Vercel we can supply the base64 encoded + // application credentials as an environment variable and write it to a file if it doesn't exist + if ( + process.env.GOOGLE_APPLICATION_CREDENTIALS && + process.env.NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS + ) { + if (!fs.existsSync(process.env.GOOGLE_APPLICATION_CREDENTIALS)) { + fs.writeFileSync( + process.env.GOOGLE_APPLICATION_CREDENTIALS, + Buffer.from( + process.env.NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS, + 'base64', + ), + ); + } + } + + const { pdf: pdfWithPlaceholder, byteRange } = updateSigningPlaceholder({ + pdf: await addSigningPlaceholder({ pdf }), + }); + + const pdfWithoutSignature = Buffer.concat([ + pdfWithPlaceholder.subarray(0, byteRange[1]), + pdfWithPlaceholder.subarray(byteRange[2]), + ]); + + const signatureLength = byteRange[2] - byteRange[1]; + + let cert: Buffer | null = null; + + if (process.env.NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS) { + cert = Buffer.from( + process.env.NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS, + 'base64', + ); + } + + if (!cert) { + cert = Buffer.from( + fs.readFileSync( + process.env.NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_PATH || './example/cert.crt', + ), + ); + } + + const signature = signWithGCloud({ + keyPath, + cert, + content: pdfWithoutSignature, + }); + + const signatureAsHex = signature.toString('hex'); + + const signedPdf = Buffer.concat([ + pdfWithPlaceholder.subarray(0, byteRange[1]), + Buffer.from(`<${signatureAsHex.padEnd(signatureLength - 2, '0')}>`), + pdfWithPlaceholder.subarray(byteRange[2]), + ]); + + return signedPdf; +}; diff --git a/packages/signing/transports/local-cert.ts b/packages/signing/transports/local-cert.ts index 435d9ef4d..aed849854 100644 --- a/packages/signing/transports/local-cert.ts +++ b/packages/signing/transports/local-cert.ts @@ -1,32 +1,51 @@ -import signer from 'node-signpdf'; import fs from 'node:fs'; -import { addSigningPlaceholder } from '../helpers/addSigningPlaceholder'; +import { signWithP12 } from '@documenso/pdf-sign'; + +import { addSigningPlaceholder } from '../helpers/add-signing-placeholder'; +import { updateSigningPlaceholder } from '../helpers/update-signing-placeholder'; export type SignWithLocalCertOptions = { pdf: Buffer; }; export const signWithLocalCert = async ({ pdf }: SignWithLocalCertOptions) => { - const pdfWithPlaceholder = await addSigningPlaceholder({ pdf }); + const { pdf: pdfWithPlaceholder, byteRange } = updateSigningPlaceholder({ + pdf: await addSigningPlaceholder({ pdf }), + }); - let p12Cert: Buffer | null = null; + const pdfWithoutSignature = Buffer.concat([ + pdfWithPlaceholder.subarray(0, byteRange[1]), + pdfWithPlaceholder.subarray(byteRange[2]), + ]); + + const signatureLength = byteRange[2] - byteRange[1]; + + let cert: Buffer | null = null; if (process.env.NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS) { - p12Cert = Buffer.from(process.env.NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS, 'base64'); + cert = Buffer.from(process.env.NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS, 'base64'); } - if (!p12Cert) { - p12Cert = Buffer.from( + if (!cert) { + cert = Buffer.from( fs.readFileSync(process.env.NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH || './example/cert.p12'), ); } - if (process.env.NEXT_PRIVATE_SIGNING_PASSPHRASE) { - return signer.sign(pdfWithPlaceholder, p12Cert, { - passphrase: process.env.NEXT_PRIVATE_SIGNING_PASSPHRASE, - }); - } + const signature = signWithP12({ + cert, + content: pdfWithoutSignature, + password: process.env.NEXT_PRIVATE_SIGNING_PASSPHRASE || undefined, + }); - return signer.sign(pdfWithPlaceholder, p12Cert); + const signatureAsHex = signature.toString('hex'); + + const signedPdf = Buffer.concat([ + pdfWithPlaceholder.subarray(0, byteRange[1]), + Buffer.from(`<${signatureAsHex.padEnd(signatureLength - 2, '0')}>`), + pdfWithPlaceholder.subarray(byteRange[2]), + ]); + + return signedPdf; }; diff --git a/packages/trpc/server/two-factor-authentication-router/router.ts b/packages/trpc/server/two-factor-authentication-router/router.ts index 36fe93a60..929dc3f73 100644 --- a/packages/trpc/server/two-factor-authentication-router/router.ts +++ b/packages/trpc/server/two-factor-authentication-router/router.ts @@ -1,34 +1,34 @@ import { TRPCError } from '@trpc/server'; -import { ErrorCode } from '@documenso/lib/next-auth/error-codes'; +import { AppError } from '@documenso/lib/errors/app-error'; import { disableTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/disable-2fa'; import { enableTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/enable-2fa'; -import { getBackupCodes } from '@documenso/lib/server-only/2fa/get-backup-code'; import { setupTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/setup-2fa'; -import { compareSync } from '@documenso/lib/server-only/auth/hash'; +import { viewBackupCodes } from '@documenso/lib/server-only/2fa/view-backup-codes'; import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; import { authenticatedProcedure, router } from '../trpc'; import { ZDisableTwoFactorAuthenticationMutationSchema, ZEnableTwoFactorAuthenticationMutationSchema, - ZSetupTwoFactorAuthenticationMutationSchema, ZViewRecoveryCodesMutationSchema, } from './schema'; export const twoFactorAuthenticationRouter = router({ - setup: authenticatedProcedure - .input(ZSetupTwoFactorAuthenticationMutationSchema) - .mutation(async ({ ctx, input }) => { - const user = ctx.user; - - const { password } = input; - + setup: authenticatedProcedure.mutation(async ({ ctx }) => { + try { return await setupTwoFactorAuthentication({ - user, - password, + user: ctx.user, }); - }), + } catch (err) { + console.error(err); + + throw new TRPCError({ + code: 'BAD_REQUEST', + message: 'We were unable to setup two-factor authentication. Please try again later.', + }); + } + }), enable: authenticatedProcedure .input(ZEnableTwoFactorAuthenticationMutationSchema) @@ -44,7 +44,11 @@ export const twoFactorAuthenticationRouter = router({ requestMetadata: extractNextApiRequestMetadata(ctx.req), }); } catch (err) { - console.error(err); + const error = AppError.parseError(err); + + if (error.code !== 'INCORRECT_TWO_FACTOR_CODE') { + console.error(err); + } throw new TRPCError({ code: 'BAD_REQUEST', @@ -59,16 +63,17 @@ export const twoFactorAuthenticationRouter = router({ try { const user = ctx.user; - const { password, backupCode } = input; - return await disableTwoFactorAuthentication({ user, - password, - backupCode, + token: input.token, requestMetadata: extractNextApiRequestMetadata(ctx.req), }); } catch (err) { - console.error(err); + const error = AppError.parseError(err); + + if (error.code !== 'INCORRECT_TWO_FACTOR_CODE') { + console.error(err); + } throw new TRPCError({ code: 'BAD_REQUEST', @@ -81,38 +86,18 @@ export const twoFactorAuthenticationRouter = router({ .input(ZViewRecoveryCodesMutationSchema) .mutation(async ({ ctx, input }) => { try { - const user = ctx.user; - - const { password } = input; - - if (!user.twoFactorEnabled) { - throw new TRPCError({ - code: 'BAD_REQUEST', - message: ErrorCode.TWO_FACTOR_SETUP_REQUIRED, - }); - } - - if (!user.password || !compareSync(password, user.password)) { - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: ErrorCode.INCORRECT_PASSWORD, - }); - } - - const recoveryCodes = await getBackupCodes({ user }); - - return { recoveryCodes }; - } catch (err) { - console.error(err); - - if (err instanceof TRPCError) { - throw err; - } - - throw new TRPCError({ - code: 'BAD_REQUEST', - message: 'We were unable to view your recovery codes. Please try again later.', + return await viewBackupCodes({ + user: ctx.user, + token: input.token, }); + } catch (err) { + const error = AppError.parseError(err); + + if (error.code !== 'INCORRECT_TWO_FACTOR_CODE') { + console.error(err); + } + + throw AppError.parseErrorToTRPCError(err); } }), }); diff --git a/packages/trpc/server/two-factor-authentication-router/schema.ts b/packages/trpc/server/two-factor-authentication-router/schema.ts index 3a831845f..befa8a4b1 100644 --- a/packages/trpc/server/two-factor-authentication-router/schema.ts +++ b/packages/trpc/server/two-factor-authentication-router/schema.ts @@ -1,13 +1,5 @@ import { z } from 'zod'; -export const ZSetupTwoFactorAuthenticationMutationSchema = z.object({ - password: z.string().min(1), -}); - -export type TSetupTwoFactorAuthenticationMutationSchema = z.infer< - typeof ZSetupTwoFactorAuthenticationMutationSchema ->; - export const ZEnableTwoFactorAuthenticationMutationSchema = z.object({ code: z.string().min(6).max(6), }); @@ -17,8 +9,7 @@ export type TEnableTwoFactorAuthenticationMutationSchema = z.infer< >; export const ZDisableTwoFactorAuthenticationMutationSchema = z.object({ - password: z.string().min(6).max(72), - backupCode: z.string().trim(), + token: z.string().trim().min(1), }); export type TDisableTwoFactorAuthenticationMutationSchema = z.infer< @@ -26,7 +17,7 @@ export type TDisableTwoFactorAuthenticationMutationSchema = z.infer< >; export const ZViewRecoveryCodesMutationSchema = z.object({ - password: z.string().min(6).max(72), + token: z.string().trim().min(1), }); export type TViewRecoveryCodesMutationSchema = z.infer; diff --git a/packages/tsconfig/process-env.d.ts b/packages/tsconfig/process-env.d.ts index d7fc44ef7..1b9c577cf 100644 --- a/packages/tsconfig/process-env.d.ts +++ b/packages/tsconfig/process-env.d.ts @@ -30,6 +30,10 @@ declare namespace NodeJS { NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH?: string; NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS?: string; NEXT_PRIVATE_SIGNING_LOCAL_FILE_ENCODING?: string; + NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH?: string; + NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_PATH?: string; + NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS?: string; + NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS?: string; NEXT_PRIVATE_SMTP_TRANSPORT?: 'mailchannels' | 'resend' | 'smtp-auth' | 'smtp-api'; diff --git a/packages/ui/primitives/document-flow/add-signers.tsx b/packages/ui/primitives/document-flow/add-signers.tsx index 8e174e578..9495882a4 100644 --- a/packages/ui/primitives/document-flow/add-signers.tsx +++ b/packages/ui/primitives/document-flow/add-signers.tsx @@ -178,9 +178,10 @@ export const AddSignersFormPartial = ({
{signers.map((signer, index) => ( - ( - {/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */} {ROLE_ICONS[field.value as RecipientRole]} @@ -367,7 +372,7 @@ export const AddSignersFormPartial = ({ > - + ))}
diff --git a/turbo.json b/turbo.json index 5e2c5526c..d17a09661 100644 --- a/turbo.json +++ b/turbo.json @@ -48,6 +48,14 @@ "NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT", "NEXT_PRIVATE_DATABASE_URL", "NEXT_PRIVATE_DIRECT_DATABASE_URL", + "NEXT_PRIVATE_SIGNING_TRANSPORT", + "NEXT_PRIVATE_SIGNING_PASSPHRASE", + "NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH", + "NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS", + "NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH", + "NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_PATH", + "NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS", + "NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS", "NEXT_PRIVATE_GOOGLE_CLIENT_ID", "NEXT_PRIVATE_GOOGLE_CLIENT_SECRET", "NEXT_PUBLIC_UPLOAD_TRANSPORT", @@ -93,6 +101,7 @@ "DATABASE_URL_UNPOOLED", "POSTGRES_PRISMA_URL", "POSTGRES_URL_NON_POOLING", + "GOOGLE_APPLICATION_CREDENTIALS", "E2E_TEST_AUTHENTICATE_USERNAME", "E2E_TEST_AUTHENTICATE_USER_EMAIL", "E2E_TEST_AUTHENTICATE_USER_PASSWORD"