diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 7e59b46..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - ignorePatterns: ['apps/**', 'packages/**', 'tests/playwright-report/**', 'tests/test-results/**', '**/.eslintrc.cjs'], - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/apps/web/.eslintrc.cjs b/apps/web/.eslintrc.cjs deleted file mode 100644 index 6d7ccf6..0000000 --- a/apps/web/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base', 'formbase/next', 'formbase/react'], -}; - -module.exports = config; diff --git a/apps/web/src/app/(auth)/login/login.tsx b/apps/web/src/app/(auth)/login/login.tsx index 1613406..bff9d36 100644 --- a/apps/web/src/app/(auth)/login/login.tsx +++ b/apps/web/src/app/(auth)/login/login.tsx @@ -4,13 +4,11 @@ import { useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; -import type { FormEvent } from 'react'; +import type { SyntheticEvent } from 'react'; import { IconBrandGithub, IconBrandGoogleFilled } from '@tabler/icons-react'; import { signIn } from '@formbase/auth/client'; - -import { Logo } from '../_components/logo'; import { Button } from '@formbase/ui/primitives/button'; import { Input } from '@formbase/ui/primitives/input'; import { Label } from '@formbase/ui/primitives/label'; @@ -20,6 +18,8 @@ import { LoadingButton } from '~/components/loading-button'; import { PasswordInput } from '~/components/password-input'; import { useSocialAuth } from '~/lib/hooks/use-social-auth'; +import { Logo } from '../_components/logo'; + export function Login() { const router = useRouter(); const [formError, setFormError] = useState(null); @@ -33,14 +33,16 @@ export function Login() { const displayError = formError ?? socialError; - const handleLogin = async (event: FormEvent) => { + const handleLogin = async (event: SyntheticEvent) => { event.preventDefault(); setFormError(null); setIsSubmitting(true); const formData = new FormData(event.currentTarget); - const email = String(formData.get('email') ?? ''); - const password = String(formData.get('password') ?? ''); + const emailValue = formData.get('email'); + const passwordValue = formData.get('password'); + const email = typeof emailValue === 'string' ? emailValue : ''; + const password = typeof passwordValue === 'string' ? passwordValue : ''; try { const { error } = await signIn.email({ diff --git a/apps/web/src/app/(auth)/reset-password/[token]/reset-password.tsx b/apps/web/src/app/(auth)/reset-password/[token]/reset-password.tsx index 6605bb4..95a2dbd 100644 --- a/apps/web/src/app/(auth)/reset-password/[token]/reset-password.tsx +++ b/apps/web/src/app/(auth)/reset-password/[token]/reset-password.tsx @@ -3,7 +3,7 @@ import { useState } from 'react'; import { useRouter } from 'next/navigation'; -import type { FormEvent } from 'react'; +import type { SyntheticEvent } from 'react'; import { ExclamationTriangleIcon } from '@radix-ui/react-icons'; import { toast } from 'sonner'; @@ -19,13 +19,14 @@ export function ResetPassword({ token }: { token: string }) { const [formError, setFormError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); - const handleReset = async (event: FormEvent) => { + const handleReset = async (event: SyntheticEvent) => { event.preventDefault(); setFormError(null); setIsSubmitting(true); const formData = new FormData(event.currentTarget); - const newPassword = String(formData.get('password') ?? ''); + const passwordValue = formData.get('password'); + const newPassword = typeof passwordValue === 'string' ? passwordValue : ''; try { const { error } = await authClient.resetPassword({ @@ -34,8 +35,9 @@ export function ResetPassword({ token }: { token: string }) { }); if (error) { - setFormError(error.message); - toast(error.message, { + const errorMessage = error.message ?? null; + setFormError(errorMessage); + toast(errorMessage ?? 'Unable to reset password. Please try again.', { icon: ( ), diff --git a/apps/web/src/app/(auth)/reset-password/send-reset-email.tsx b/apps/web/src/app/(auth)/reset-password/send-reset-email.tsx index 0a7ca5e..6deec79 100644 --- a/apps/web/src/app/(auth)/reset-password/send-reset-email.tsx +++ b/apps/web/src/app/(auth)/reset-password/send-reset-email.tsx @@ -1,8 +1,10 @@ 'use client'; -import { type FormEvent, useState } from 'react'; +import { useState } from 'react'; import { useRouter } from 'next/navigation'; +import type { SyntheticEvent } from 'react'; + import { toast } from 'sonner'; import { authClient } from '@formbase/auth/client'; @@ -16,13 +18,14 @@ export function SendResetEmail() { const [formError, setFormError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); - const handleResetRequest = async (event: FormEvent) => { + const handleResetRequest = async (event: SyntheticEvent) => { event.preventDefault(); setFormError(null); setIsSubmitting(true); const formData = new FormData(event.currentTarget); - const email = String(formData.get('email') ?? ''); + const emailValue = formData.get('email'); + const email = typeof emailValue === 'string' ? emailValue : ''; try { const { error } = await authClient.requestPasswordReset({ @@ -30,7 +33,7 @@ export function SendResetEmail() { }); if (error) { - setFormError(error.message); + setFormError(error.message ?? null); return; } @@ -46,10 +49,7 @@ export function SendResetEmail() { return (
-
@@ -218,7 +218,12 @@ export function ApiKeysSection() { )} - setNewKeyValue(null)}> + { + setNewKeyValue(null); + }} + > API Key Created @@ -231,14 +236,24 @@ export function ApiKeysSection() { {newKeyValue && } - + !open && setDeleteKeyId(null)} + onOpenChange={(open) => { + if (!open) { + setDeleteKeyId(null); + } + }} > @@ -278,7 +293,9 @@ interface ApiKeyRowProps { function ApiKeyRow({ apiKey, onDelete }: ApiKeyRowProps) { const isExpired = apiKey.expiresAt && new Date(apiKey.expiresAt) < new Date(); - const { data: usageStats } = api.apiKeys.getUsageStats.useQuery({ id: apiKey.id }); + const { data: usageStats } = api.apiKeys.getUsageStats.useQuery({ + id: apiKey.id, + }); return (
@@ -295,7 +312,9 @@ function ApiKeyRow({ apiKey, onDelete }: ApiKeyRowProps) { {apiKey.keyPrefix}... - Created {format(new Date(apiKey.createdAt), 'MMM d, yyyy')} + + Created {format(new Date(apiKey.createdAt), 'MMM d, yyyy')} + {apiKey.lastUsedAt && ( Last used {format(new Date(apiKey.lastUsedAt), 'MMM d, yyyy')} diff --git a/apps/web/src/app/(main)/dashboard/settings/profile-form.tsx b/apps/web/src/app/(main)/dashboard/settings/profile-form.tsx index a163f49..73f5465 100644 --- a/apps/web/src/app/(main)/dashboard/settings/profile-form.tsx +++ b/apps/web/src/app/(main)/dashboard/settings/profile-form.tsx @@ -9,8 +9,6 @@ import { toast } from 'sonner'; import { z } from 'zod'; import { type User } from '@formbase/auth'; - -import { LoadingButton } from '~/components/loading-button'; import { Form, FormControl, @@ -21,6 +19,7 @@ import { } from '@formbase/ui/primitives/form'; import { Input } from '@formbase/ui/primitives/input'; +import { LoadingButton } from '~/components/loading-button'; import { api } from '~/lib/trpc/react'; const profileFormSchema = z.object({ @@ -34,8 +33,10 @@ const profileFormSchema = z.object({ type ProfileFormValues = z.infer; +type ProfileFormUser = Omit & { name: string | null }; + type ProfileFormProps = { - user: User; + user: ProfileFormUser; }; export function ProfileForm({ user }: ProfileFormProps) { diff --git a/apps/web/src/app/(main)/form/[id]/copy-button.tsx b/apps/web/src/app/(main)/form/[id]/copy-button.tsx index c706151..dbe01f8 100644 --- a/apps/web/src/app/(main)/form/[id]/copy-button.tsx +++ b/apps/web/src/app/(main)/form/[id]/copy-button.tsx @@ -10,7 +10,7 @@ type CopyFormIdProps = { }; export default function CopyFormId({ formId }: CopyFormIdProps) { - const [_, copy] = useCopyToClipboard(); + const [, copy] = useCopyToClipboard(); return (
diff --git a/apps/web/src/app/(main)/form/[id]/export-submissions-button.tsx b/apps/web/src/app/(main)/form/[id]/export-submissions-button.tsx index ffede22..6793a0d 100644 --- a/apps/web/src/app/(main)/form/[id]/export-submissions-button.tsx +++ b/apps/web/src/app/(main)/form/[id]/export-submissions-button.tsx @@ -3,7 +3,7 @@ import { ArrowDownToLine, FileDown } from 'lucide-react'; import { toast } from 'sonner'; -import { type FormData } from '@formbase/db/schema'; +import { type RouterOutputs } from '@formbase/api'; import { Button } from '@formbase/ui/primitives/button'; import { DropdownMenu, @@ -14,15 +14,17 @@ import { DropdownMenuTrigger, } from '@formbase/ui/primitives/dropdown-menu'; +import { formatSubmissionValue } from './format-submission-value'; + type ExportSubmissionsDropDownButtonProps = { - submissions: FormData[]; + submissions: Array; formKeys: string[]; formTitle: string; honeypotField: string; }; const createCSVContent = ( - submissions: FormData[], + submissions: Array, formKeys: string[], honeypotField: string, ): string => { @@ -35,10 +37,10 @@ const createCSVContent = ( submissions.forEach((submission) => { if (submission.data && typeof submission.data === 'object') { - const dataValues = filteredKeys.map( - (key) => (submission.data as Record)[key] ?? '', + const dataValues = filteredKeys.map((key) => + formatSubmissionValue(submission.data?.[key]), ); - const row = [...dataValues, submission.isSpam].join(','); + const row = [...dataValues, String(submission.isSpam)].join(','); csvContent += row + '\n'; } }); @@ -47,18 +49,20 @@ const createCSVContent = ( }; const createJSONContent = ( - submissions: FormData[], + submissions: Array, honeypotField: string, ): string => { const jsonContent = JSON.stringify( submissions.map((submission) => { - const data = + const dataEntries = submission.data && typeof submission.data === 'object' - ? { ...(submission.data as Record) } - : {}; - delete data[honeypotField]; + ? Object.entries(submission.data).filter( + ([key]) => key !== honeypotField, + ) + : []; + return { - ...data, + ...Object.fromEntries(dataEntries), isSpam: submission.isSpam, }; }), diff --git a/apps/web/src/app/(main)/form/[id]/form-settings.tsx b/apps/web/src/app/(main)/form/[id]/form-settings.tsx index 74fb8f6..3f807b5 100644 --- a/apps/web/src/app/(main)/form/[id]/form-settings.tsx +++ b/apps/web/src/app/(main)/form/[id]/form-settings.tsx @@ -3,14 +3,19 @@ import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; -import { BellRing, ExternalLink, FolderPen, FolderX, Shield } from 'lucide-react'; +import { + BellRing, + ExternalLink, + FolderPen, + FolderX, + Shield, +} from 'lucide-react'; import { useForm } from 'react-hook-form'; import { toast } from 'sonner'; import { z } from 'zod'; import { type RouterOutputs } from '@formbase/api'; import { type User } from '@formbase/auth'; -import { LoadingButton } from '~/components/loading-button'; import { Form, FormControl, @@ -23,6 +28,7 @@ import { Input } from '@formbase/ui/primitives/input'; import { Label } from '@formbase/ui/primitives/label'; import { Switch } from '@formbase/ui/primitives/switch'; +import { LoadingButton } from '~/components/loading-button'; import { api } from '~/lib/trpc/react'; import { revalidateDashboard } from '../../_actions/revalidateDashboard'; @@ -40,10 +46,6 @@ const enableFormSubmissionsSchema = z.object({ enableFormSubmissions: z.boolean().default(true).optional(), }); -const enableRetentionSchema = z.object({ - enableRetention: z.boolean().default(true).optional(), -}); - const enableNotificationsSchema = z.object({ enableNotifications: z.boolean().default(true).optional(), }); @@ -58,7 +60,6 @@ const honeypotFieldSchema = z.object({ type FormNameSchema = z.infer; type EnableFormSubmissionsSchema = z.infer; -type _EnableSubmissionsRetentionSchema = z.infer; type EnableFormNotificationsSchema = z.infer; type FormReturnUrlSchema = z.infer; @@ -368,7 +369,7 @@ const EnableFormSubmissions = ({ const router = useRouter(); const enableSubmissionsForm = useForm({ - resolver: zodResolver(enableRetentionSchema), + resolver: zodResolver(enableFormSubmissionsSchema), defaultValues: { enableFormSubmissions: enableSubmissions, }, @@ -562,7 +563,9 @@ const HoneypotFieldSetting = ({ return ( - + { + if (value === null || value === undefined) { + return ''; + } + + if (typeof value === 'string') { + return value; + } + + if (typeof value === 'number' || typeof value === 'boolean') { + return String(value); + } + + return JSON.stringify(value); +}; diff --git a/apps/web/src/app/(main)/form/[id]/page.tsx b/apps/web/src/app/(main)/form/[id]/page.tsx index eb8c06e..236f563 100644 --- a/apps/web/src/app/(main)/form/[id]/page.tsx +++ b/apps/web/src/app/(main)/form/[id]/page.tsx @@ -1,6 +1,10 @@ import { getSession } from '@formbase/auth/server'; -import { type FormData } from '@formbase/db/schema'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@formbase/ui/primitives/tabs'; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from '@formbase/ui/primitives/tabs'; import { CopyButton } from '~/components/copy-button'; import { api } from '~/lib/trpc/server'; @@ -53,7 +57,7 @@ export default async function FormPage({ Total Submissions: {formSubmissions.length} )} diff --git a/apps/web/src/app/(main)/form/[id]/submissions-table.tsx b/apps/web/src/app/(main)/form/[id]/submissions-table.tsx index 0a1aae1..4b34e6b 100644 --- a/apps/web/src/app/(main)/form/[id]/submissions-table.tsx +++ b/apps/web/src/app/(main)/form/[id]/submissions-table.tsx @@ -23,7 +23,7 @@ import { import { AlertTriangle, CheckCircle, Trash2, TrashIcon } from 'lucide-react'; import { toast } from 'sonner'; -import { type FormData } from '@formbase/db/schema'; +import { type RouterOutputs } from '@formbase/api'; import { Badge } from '@formbase/ui/primitives/badge'; import { Button } from '@formbase/ui/primitives/button'; import { Checkbox } from '@formbase/ui/primitives/checkbox'; @@ -45,11 +45,14 @@ import { formatFileName } from '@formbase/utils'; import { api } from '~/lib/trpc/react'; +import { formatSubmissionValue } from './format-submission-value'; import { ImagePreviewDialog } from './image-preview-dialog'; +type Submission = RouterOutputs['formData']['all'][number]; + type SubmissionsTableProps = { formKeys: string[]; - submissions: FormData[]; + submissions: Submission[]; }; export function SubmissionsTable({ @@ -108,22 +111,19 @@ export function SubmissionsTable({ { onSuccess: () => { router.refresh(); - toast.success( - isSpam ? 'Marked as spam' : 'Marked as not spam', - { - icon: isSpam ? ( - - ) : ( - - ), - }, - ); + toast.success(isSpam ? 'Marked as spam' : 'Marked as not spam', { + icon: isSpam ? ( + + ) : ( + + ), + }); }, }, ); }; - const columns: Array> = [ + const columns: Array> = [ { id: 'select', header: ({ table }) => { @@ -134,7 +134,7 @@ export function SubmissionsTable({ (table.getIsSomePageRowsSelected() && 'indeterminate') } onCheckedChange={(value) => { - table.toggleAllPageRowsSelected(!!value); + table.toggleAllPageRowsSelected(value); }} aria-label="Select all" /> @@ -168,13 +168,14 @@ export function SubmissionsTable({ ); }, - cell: ({ row }: { row: Row }) => { - const data = row.original.data as Record | null; - if (!data?.[submission]) { + cell: ({ row }: { row: Row }) => { + const data = row.original.data; + const fileUrl = data?.[submission]; + + if (typeof fileUrl !== 'string') { return null; } - const fileUrl = data[submission] as string; const fileName = formatFileName(fileUrl); return ( @@ -209,17 +210,16 @@ export function SubmissionsTable({ ); }, - cell: ({ row }: { row: Row }) => { - const data = row.original.data as Record< - string, - string | undefined - > | null; + cell: ({ row }: { row: Row }) => { + const data = row.original.data; if (!data) { return null; } - return
{data[submission]}
; + const value = data[submission]; + + return
{formatSubmissionValue(value)}
; }, }; }), @@ -242,7 +242,7 @@ export function SubmissionsTable({ const dateB = new Date(b.original.createdAt); return dateA.getTime() - dateB.getTime(); }, - cell: ({ row }: { row: Row }) => { + cell: ({ row }: { row: Row }) => { const date = new Date(row.original.createdAt); const dateString = date.toLocaleDateString('en-US', { month: 'long', @@ -264,15 +264,12 @@ export function SubmissionsTable({ accessorKey: 'isSpam', header: () => { return ( - ); }, - cell: ({ row }: { row: Row }) => { + cell: ({ row }: { row: Row }) => { const isSpam = row.original.isSpam; if (!isSpam) { return null; @@ -289,7 +286,7 @@ export function SubmissionsTable({ id: 'actions', enableHiding: false, size: 20, - cell: ({ row }: { row: Row }) => { + cell: ({ row }: { row: Row }) => { const submissionId = row.original.id; const isSpam = row.original.isSpam; diff --git a/apps/web/src/app/api/health/route.ts b/apps/web/src/app/api/health/route.ts index 0ba0da2..85d71eb 100644 --- a/apps/web/src/app/api/health/route.ts +++ b/apps/web/src/app/api/health/route.ts @@ -1,11 +1,11 @@ -import { db, drizzlePrimitives } from '@formbase/db'; +import { queryClient } from '@formbase/db'; export async function GET() { try { - await db.execute(drizzlePrimitives.sql`SELECT 1000`); + await queryClient.execute('SELECT 1000'); return new Response('All systems operational', { status: 200 }); - } catch (err) { + } catch { return new Response(`An error occured`, { status: 500 }); } } diff --git a/apps/web/src/app/api/s/[id]/route.ts b/apps/web/src/app/api/s/[id]/route.ts index d0db918..3755074 100644 --- a/apps/web/src/app/api/s/[id]/route.ts +++ b/apps/web/src/app/api/s/[id]/route.ts @@ -1,14 +1,13 @@ -import { env } from "@formbase/env"; -import { userAgent } from "next/server"; +import { userAgent } from 'next/server'; -import { sendMail } from "~/lib/email/mailer"; -import { renderNewSubmissionEmail } from "~/lib/email/templates/new-submission"; -import { checkForSpam, stripHoneypotField } from "~/lib/spam-detection"; -import { api } from "~/lib/trpc/server"; -import { assignFileOrImage, uploadFileFromBlob } from "~/lib/upload-file"; -import { type RouterOutputs } from "@formbase/api"; +import { type RouterOutputs } from '@formbase/api'; +import { env } from '@formbase/env'; -type Json = string | number | boolean | null | { [key: string]: Json } | Json[]; +import { sendMail } from '~/lib/email/mailer'; +import { renderNewSubmissionEmail } from '~/lib/email/templates/new-submission'; +import { checkForSpam, stripHoneypotField } from '~/lib/spam-detection'; +import { api } from '~/lib/trpc/server'; +import { assignFileOrImage, uploadFileFromBlob } from '~/lib/upload-file'; type FormDataResult = | { @@ -30,12 +29,15 @@ const CORS_HEADERS = { async function getFormData(request: Request): Promise { const contentType = request.headers.get('content-type') ?? ''; - if (contentType.includes('multipart/form-data') || contentType.includes('application/x-www-form-urlencoded')) { + if ( + contentType.includes('multipart/form-data') || + contentType.includes('application/x-www-form-urlencoded') + ) { try { const rawFormData = await request.formData(); const data: Record = {}; rawFormData.forEach((value, key) => { - data[key] = value as Blob | string; + data[key] = value; }); return { data, source: 'formData', rawFormData }; } catch { @@ -44,13 +46,14 @@ async function getFormData(request: Request): Promise { } try { - const jsonData = (await request.json()) as Record; + const jsonData: unknown = await request.json(); if (typeof jsonData !== 'object' || jsonData === null) { throw new Error('Invalid form data'); } + const jsonObject = jsonData as Record; const data: Record = {}; - Object.keys(jsonData).forEach((key) => { - data[key] = jsonData[key] as Blob | string | undefined; + Object.keys(jsonObject).forEach((key) => { + data[key] = jsonObject[key] as Blob | string | undefined; }); return { data, source: 'json' }; } catch { @@ -99,10 +102,6 @@ export async function POST( try { const { id } = await params; - if (!id) { - return new Response('Form ID is required', { status: 400 }); - } - const formId = id; const form = await api.form.getFormById({ formId }); if (!form) { @@ -122,15 +121,15 @@ export async function POST( } const honeypotField = form.honeypotField; - const spamResult = checkForSpam(formData as Record, honeypotField); - const cleanedFormData = stripHoneypotField(formData as Record, honeypotField); + const spamResult = checkForSpam(formData, honeypotField); + const cleanedFormData = stripHoneypotField(formData, honeypotField); const formDataKeys = Object.keys(cleanedFormData); const formKeys = form.keys; const updatedKeys = [...new Set([...formKeys, ...formDataKeys])]; await api.formData.setFormData({ - data: cleanedFormData as Json, + data: cleanedFormData, formId, keys: updatedKeys, isSpam: spamResult.isSpam, diff --git a/apps/web/src/app/api/trpc/[trpc]/route.ts b/apps/web/src/app/api/trpc/[trpc]/route.ts index 5f7bdaf..ace5e09 100644 --- a/apps/web/src/app/api/trpc/[trpc]/route.ts +++ b/apps/web/src/app/api/trpc/[trpc]/route.ts @@ -18,10 +18,11 @@ const handler = (req: NextRequest) => router: appRouter, createContext: () => createContext(req), onError: ({ path, error }) => { - env.NODE_ENV === 'development' && + if (env.NODE_ENV === 'development') { console.error( `❌ tRPC failed on ${path ?? ''}: ${error.message}`, ); + } }, }); diff --git a/apps/web/src/app/api/v1/[...trpc]/route.ts b/apps/web/src/app/api/v1/[...trpc]/route.ts index 47502bf..72c8ccb 100644 --- a/apps/web/src/app/api/v1/[...trpc]/route.ts +++ b/apps/web/src/app/api/v1/[...trpc]/route.ts @@ -1,30 +1,47 @@ -import { type NextRequest, NextResponse } from 'next/server'; +import { after, NextResponse } from 'next/server'; + +import type { ApiV1Context } from '@formbase/api/routers/api-v1'; +import type { NextRequest } from 'next/server'; + import { createOpenApiFetchHandler } from 'trpc-to-openapi'; -import { apiV1Router, createApiV1Context, type ApiV1Context } from '@formbase/api/routers/api-v1'; import { logApiRequest } from '@formbase/api'; +import { apiV1Router, createApiV1Context } from '@formbase/api/routers/api-v1'; import { db } from '@formbase/db'; export const dynamic = 'force-dynamic'; +type OpenApiErrorBody = { + code?: unknown; + message?: unknown; +}; + async function transformErrorResponse(response: Response): Promise { if (response.ok) return response; try { - const body = await response.json(); + const body = (await response.json()) as OpenApiErrorBody; + const code = + typeof body.code === 'string' ? body.code : 'INTERNAL_SERVER_ERROR'; + const message = + typeof body.message === 'string' + ? body.message + : 'An unexpected error occurred'; const errorResponse = { error: { - code: body.code ?? 'INTERNAL_SERVER_ERROR', - message: body.message ?? 'An unexpected error occurred', + code, + message, }, }; const headers = new Headers(response.headers); - if (response.status === 429 && body.message) { - const match = body.message.match(/Retry after (\d+) seconds/); - if (match) { - headers.set('Retry-After', match[1]); + if (response.status === 429) { + const match = /Retry after (\d+) seconds/.exec(message); + const retryAfterSeconds = match?.[1]; + + if (retryAfterSeconds) { + headers.set('Retry-After', retryAfterSeconds); } } @@ -44,14 +61,17 @@ const handler = async (req: NextRequest) => { const response = await createOpenApiFetchHandler({ endpoint: '/api/v1', router: apiV1Router, - createContext: async () => { - ctx = await createApiV1Context({ headers: req.headers }); + createContext: () => { + ctx = createApiV1Context({ + headers: req.headers, + afterResponse: after, + }); return ctx; }, req, responseMeta: ({ ctx: responseCtx }) => { const headers: Record = {}; - const typedCtx = responseCtx as ApiV1Context | undefined; + const typedCtx = responseCtx; if (typedCtx?.rateLimitRemaining !== undefined) { headers['X-RateLimit-Remaining'] = String(typedCtx.rateLimitRemaining); @@ -66,18 +86,25 @@ const handler = async (req: NextRequest) => { const responseTime = Date.now() - startTime; const typedCtx = ctx as ApiV1Context | null; + const apiKey = typedCtx?.apiKey; + + if (apiKey) { + const ipAddress = + req.headers.get('x-forwarded-for') ?? req.headers.get('x-real-ip'); + const userAgent = req.headers.get('user-agent'); - if (typedCtx?.apiKey) { - logApiRequest(db, { - apiKeyId: typedCtx.apiKey.id, - userId: typedCtx.apiKey.userId, - method: req.method, - path: new URL(req.url).pathname, - statusCode: response.status, - ipAddress: req.headers.get('x-forwarded-for') ?? req.headers.get('x-real-ip') ?? undefined, - userAgent: req.headers.get('user-agent') ?? undefined, - responseTimeMs: responseTime, - }).catch(() => {}); + after(async () => { + await logApiRequest(db, { + apiKeyId: apiKey.id, + userId: apiKey.userId, + method: req.method, + path: new URL(req.url).pathname, + statusCode: response.status, + ...(ipAddress ? { ipAddress } : {}), + ...(userAgent ? { userAgent } : {}), + responseTimeMs: responseTime, + }).catch(() => undefined); + }); } return transformErrorResponse(response); diff --git a/apps/web/src/app/api/v1/openapi.json/route.ts b/apps/web/src/app/api/v1/openapi.json/route.ts index dc18a9e..2c73c81 100644 --- a/apps/web/src/app/api/v1/openapi.json/route.ts +++ b/apps/web/src/app/api/v1/openapi.json/route.ts @@ -1,11 +1,11 @@ import { generateOpenApiDocument } from 'trpc-to-openapi'; -import { env } from '@formbase/env'; import { apiV1Router } from '@formbase/api/routers/api-v1'; +import { env } from '@formbase/env'; export const dynamic = 'force-dynamic'; -export async function GET() { +export function GET() { const openApiDocument = generateOpenApiDocument(apiV1Router, { title: 'Formbase API', version: '1.0.0', diff --git a/apps/web/src/app/s/[formId]/page.tsx b/apps/web/src/app/s/[formId]/page.tsx index 47a0686..242e56a 100644 --- a/apps/web/src/app/s/[formId]/page.tsx +++ b/apps/web/src/app/s/[formId]/page.tsx @@ -1,5 +1,3 @@ -import Link from 'next/link'; - import { Button } from '@formbase/ui/primitives/button'; import { api } from '~/lib/trpc/server'; @@ -12,17 +10,6 @@ export default async function FormCompletedPage({ const { formId } = await params; const form = await api.form.getReturnUrl({ formId }); - if (!form) { - return ( -
-

Form not found

- - - -
- ); - } - return (

Done Submitting using Formbase

diff --git a/apps/web/src/components/copy-button.tsx b/apps/web/src/components/copy-button.tsx index e4ce3bf..ca40486 100644 --- a/apps/web/src/components/copy-button.tsx +++ b/apps/web/src/components/copy-button.tsx @@ -15,7 +15,7 @@ type CopyButtonProps = { }; export const CopyButton = ({ text, className }: CopyButtonProps) => { - const [_, copy] = useCopyToClipboard(); + const [, copy] = useCopyToClipboard(); const [hasCopied, setHasCopied] = useState(false); return ( diff --git a/apps/web/src/components/loading-button.tsx b/apps/web/src/components/loading-button.tsx index 291e39a..10b0d63 100644 --- a/apps/web/src/components/loading-button.tsx +++ b/apps/web/src/components/loading-button.tsx @@ -19,7 +19,7 @@ const LoadingButton = forwardRef( diff --git a/apps/web/src/components/social-login-buttons.tsx b/apps/web/src/components/social-login-buttons.tsx index b82354d..6d8e3f1 100644 --- a/apps/web/src/components/social-login-buttons.tsx +++ b/apps/web/src/components/social-login-buttons.tsx @@ -28,7 +28,9 @@ export function SocialLoginButtons({ variant="outline" className="w-full" disabled={isDisabled} - onClick={() => onSocialSignIn('github')} + onClick={() => { + onSocialSignIn('github'); + }} > {actionText} with GitHub @@ -37,7 +39,9 @@ export function SocialLoginButtons({ variant="outline" className="w-full" disabled={isDisabled} - onClick={() => onSocialSignIn('google')} + onClick={() => { + onSocialSignIn('google'); + }} > {actionText} with Google diff --git a/apps/web/src/lib/highlight-code.ts b/apps/web/src/lib/highlight-code.ts index 31c28b1..f2341a7 100644 --- a/apps/web/src/lib/highlight-code.ts +++ b/apps/web/src/lib/highlight-code.ts @@ -2,12 +2,12 @@ import type { ThemeInput } from 'shiki'; -import { getHighlighter } from 'shiki'; +import { createHighlighter } from 'shiki'; import { blackoutTheme } from './themes/dark'; export async function highlightCode(code: string) { - const highlighter = await getHighlighter({ + const highlighter = await createHighlighter({ langs: ['typescript', 'html'], themes: [], }); diff --git a/apps/web/src/lib/hooks/use-copy-to-clipboard.ts b/apps/web/src/lib/hooks/use-copy-to-clipboard.ts index 0de22af..3da2fce 100644 --- a/apps/web/src/lib/hooks/use-copy-to-clipboard.ts +++ b/apps/web/src/lib/hooks/use-copy-to-clipboard.ts @@ -17,7 +17,7 @@ export function useCopyToClipboard(): [CopiedValue, CopyFn] { await navigator.clipboard.writeText(text); setCopiedText(text); return true; - } catch (error) { + } catch { setCopiedText(null); return false; } diff --git a/apps/web/src/lib/spam-detection.ts b/apps/web/src/lib/spam-detection.ts index 3daa3cc..9bd6da6 100644 --- a/apps/web/src/lib/spam-detection.ts +++ b/apps/web/src/lib/spam-detection.ts @@ -30,6 +30,7 @@ export function stripHoneypotField( formData: Record, honeypotField: string, ): Record { - const { [honeypotField]: _, ...rest } = formData; - return rest; + return Object.fromEntries( + Object.entries(formData).filter(([key]) => key !== honeypotField), + ); } diff --git a/apps/web/src/lib/upload-file.ts b/apps/web/src/lib/upload-file.ts index 53735ff..a0c70a9 100644 --- a/apps/web/src/lib/upload-file.ts +++ b/apps/web/src/lib/upload-file.ts @@ -11,6 +11,8 @@ const getClient = () => { if (client) return client; if ( !env.STORAGE_ENDPOINT || + env.STORAGE_PORT === undefined || + env.STORAGE_USESSL === undefined || !env.STORAGE_ACCESS_KEY || !env.STORAGE_SECRET_KEY ) { @@ -18,8 +20,8 @@ const getClient = () => { } client = new Client({ endPoint: env.STORAGE_ENDPOINT, - port: env.STORAGE_PORT!, - useSSL: env.STORAGE_USESSL!, + port: env.STORAGE_PORT, + useSSL: env.STORAGE_USESSL, accessKey: env.STORAGE_ACCESS_KEY, secretKey: env.STORAGE_SECRET_KEY, }); @@ -35,7 +37,12 @@ async function ensureBucket(bucketName: string) { export async function uploadFile(fileBuffer: Buffer, mimetype: string) { const c = getClient(); - const bucket = env.STORAGE_BUCKET!; + const bucket = env.STORAGE_BUCKET; + + if (!bucket) { + throw new Error('Storage bucket is not configured'); + } + const name = `${generateId(15)}.${mimetype.split('/')[1]}`; await ensureBucket(bucket); @@ -64,8 +71,7 @@ export function assignFileOrImage({ fileUrl: string; }): void { const isImage = - formData[key] instanceof Blob && - (formData[key] as Blob).type.startsWith('image/'); + formData[key] instanceof Blob && formData[key].type.startsWith('image/'); const field = isImage ? 'image' : 'file'; formData[field] = fileUrl; diff --git a/apps/web/src/proxy.ts b/apps/web/src/proxy.ts index 8aef4fb..1719ec8 100644 --- a/apps/web/src/proxy.ts +++ b/apps/web/src/proxy.ts @@ -24,7 +24,7 @@ export async function proxy(request: NextRequest): Promise { const path = request.nextUrl.pathname; const url = request.nextUrl as unknown as URL; - if (path.match('^/s/([a-zA-Z0-9_-]+)$')) { + if (/^\/s\/([a-zA-Z0-9_-]+)$/.exec(path)) { const subpath = path.split('/')[path.split('/').length - 1]; return NextResponse.rewrite(new URL(`/api/s/${subpath}`, url)); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 8973fcc..36bd5a1 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -12,7 +12,6 @@ ".next/types/**/*.ts", "**/*.js", "**/*.cjs", - ".eslintrc.cjs", "**/*.mjs" ], "exclude": ["node_modules", "test-results"] diff --git a/bun.lock b/bun.lock index b919173..981a630 100644 --- a/bun.lock +++ b/bun.lock @@ -10,12 +10,9 @@ "devDependencies": { "@formbase/tsconfig": "workspace:*", "@ianvs/prettier-plugin-sort-imports": "^4.7.1", - "@types/eslint": "^8.56.12", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "eslint": "^8.57.1", + "@types/eslint": "^9.6.1", + "eslint": "^10.2.1", "eslint-config-formbase": "workspace:*", - "eslint-plugin-eslint-comments": "^3.2.0", "prettier": "^3.8.3", "prettier-plugin-astro": "^0.13.0", "prettier-plugin-curly": "^0.2.2", @@ -24,7 +21,7 @@ "prettier-plugin-tailwindcss": "^0.5.14", "rimraf": "^5.0.10", "turbo": "^2.9.6", - "typescript": "5.8.2", + "typescript": "6.0.3", }, }, "apps/web": { @@ -128,18 +125,20 @@ "name": "eslint-config-formbase", "version": "0.1.0", "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - }, - "devDependencies": { - "@formbase/tsconfig": "workspace:*", - "astro-eslint-parser": "^1.4.0", - "eslint-config-next": "^16.2.4", - "eslint-config-prettier": "^9.1.0", + "@eslint/compat": "^2.0.5", + "@next/eslint-plugin-next": "^16.2.4", + "@typescript-eslint/eslint-plugin": "^8.59.1", + "@typescript-eslint/parser": "^8.59.1", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^17.5.0", + }, + "devDependencies": { + "@formbase/tsconfig": "workspace:*", + "eslint": "^10.2.1", }, }, "packages/config/tailwind": { @@ -188,6 +187,7 @@ }, "devDependencies": { "@formbase/tsconfig": "workspace:*", + "@types/node": "^20.19.39", "dotenv": "^16.4.5", "dotenv-cli": "^7.4.2", "drizzle-kit": "^0.21.4", @@ -292,7 +292,7 @@ "@types/node": "^20.19.39", "@vitest/coverage-v8": "^2.1.8", "drizzle-orm": "^0.30.10", - "typescript": "5.8.2", + "typescript": "6.0.3", "vitest": "^2.1.8", }, }, @@ -356,12 +356,8 @@ "@documenso/nodemailer-resend": ["@documenso/nodemailer-resend@3.0.0", "", { "dependencies": { "resend": "^3.2.0" }, "peerDependencies": { "nodemailer": "^6.9.3" } }, "sha512-fdcGRhLPQ1fpT3/Ixbhap5iioJInR3sP7MO5KH+cBt72d4B90Fi/ooJRguYYrebMzB/A3tNKm6tP7nTzfPKLOw=="], - "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], - "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], @@ -422,9 +418,17 @@ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - "@eslint/eslintrc": ["@eslint/eslintrc@2.1.4", "", { "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" } }, "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="], + "@eslint/compat": ["@eslint/compat@2.0.5", "", { "dependencies": { "@eslint/core": "^1.2.1" }, "peerDependencies": { "eslint": "^8.40 || 9 || 10" }, "optionalPeers": ["eslint"] }, "sha512-IbHDbHJfkVNv6xjlET8AIVo/K1NQt7YT4Rp6ok/clyBGcpRx1l6gv0Rq3vBvYfPJIZt6ODf66Zq08FJNDpnzgg=="], + + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.5.5", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w=="], + + "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], - "@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="], + "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="], "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], @@ -462,11 +466,15 @@ "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], - "@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="], + "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="], + + "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="], + + "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="], "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - "@humanwhocodes/object-schema": ["@humanwhocodes/object-schema@2.0.3", "", {}, "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="], + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], "@ianvs/prettier-plugin-sort-imports": ["@ianvs/prettier-plugin-sort-imports@4.7.1", "", { "dependencies": { "@babel/generator": "^7.26.2", "@babel/parser": "^7.26.2", "@babel/traverse": "^7.25.9", "@babel/types": "^7.26.0", "semver": "^7.5.2" }, "peerDependencies": { "@prettier/plugin-oxc": "^0.0.4 || ^0.1.0", "@vue/compiler-sfc": "2.7.x || 3.x", "content-tag": "^4.0.0", "prettier": "2 || 3 || ^4.0.0-0", "prettier-plugin-ember-template-tag": "^2.1.0" }, "optionalPeers": ["@prettier/plugin-oxc", "@vue/compiler-sfc", "content-tag", "prettier-plugin-ember-template-tag"] }, "sha512-jmTNYGlg95tlsoG3JLCcuC4BrFELJtLirLAkQW/71lXSyOhVt/Xj7xWbbGcuVbNq1gwWgSyMrPjJc9Z30hynVw=="], @@ -566,8 +574,6 @@ "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.18.1", "", { "dependencies": { "@microsoft/tsdoc": "0.16.0", "ajv": "~8.18.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], - "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], "@next/env": ["@next/env@16.2.4", "", {}, "sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw=="], @@ -602,14 +608,10 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="], - "@one-ini/wasm": ["@one-ini/wasm@0.1.1", "", {}, "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], - "@playwright/test": ["@playwright/test@1.59.1", "", { "dependencies": { "playwright": "1.59.1" }, "bin": { "playwright": "cli.js" } }, "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg=="], "@radix-ui/colors": ["@radix-ui/colors@3.0.0", "", {}, "sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg=="], @@ -742,8 +744,6 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="], - "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], - "@rushstack/node-core-library": ["@rushstack/node-core-library@5.23.1", "", { "dependencies": { "ajv": "~8.18.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.7.4" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-wlKmIKIYCKuCASbITvOxLZXepPbwXvrv7S6ig6XNWFchSyhL/E2txmVXspHY49Wu2dzf7nI27a2k/yV5BA3EiA=="], "@rushstack/problem-matcher": ["@rushstack/problem-matcher@0.2.1", "", { "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog=="], @@ -852,8 +852,6 @@ "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-1XUUyWW0W6FTSqGEhU8RHVqb2wP1SPkr7hIvBlMEwH9jr+sJQK5kqeosLJ/QaUv4ecSAd1ZhIrLoW7qslAzT4A=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="], @@ -876,7 +874,9 @@ "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], - "@types/eslint": ["@types/eslint@8.56.12", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g=="], + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], @@ -884,8 +884,6 @@ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], - "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], @@ -902,66 +900,28 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@7.18.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/type-utils": "7.18.0", "@typescript-eslint/utils": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.56.0" } }, "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/type-utils": "8.59.1", "@typescript-eslint/utils": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@7.18.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.52.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.52.0", "@typescript-eslint/types": "^8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.1", "@typescript-eslint/types": "^8.59.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" } }, "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1" } }, "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.52.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@7.18.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1", "@typescript-eslint/utils": "8.59.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w=="], - "@typescript-eslint/types": ["@typescript-eslint/types@7.18.0", "", {}, "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.59.1", "", {}, "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.1", "@typescript-eslint/tsconfig-utils": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@7.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], - "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], - - "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], - - "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], - - "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], - - "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], - - "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], - - "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], - - "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], - - "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], - - "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], - - "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], - - "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], - - "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], - - "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], - - "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], - - "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], - - "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], - - "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], - - "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], - "@vitest/coverage-v8": ["@vitest/coverage-v8@2.1.9", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", "debug": "^4.3.7", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.12", "magicast": "^0.3.5", "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, "peerDependencies": { "@vitest/browser": "2.1.9", "vitest": "2.1.9" }, "optionalPeers": ["@vitest/browser"] }, "sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ=="], "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], @@ -980,23 +940,23 @@ "abbrev": ["abbrev@2.0.0", "", {}, "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ajv": ["ajv@6.15.0", "", { "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" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], @@ -1006,12 +966,8 @@ "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], - "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], - "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], @@ -1024,10 +980,6 @@ "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], - "astro-eslint-parser": ["astro-eslint-parser@1.4.0", "", { "dependencies": { "@astrojs/compiler": "^2.0.0 || ^3.0.0", "@typescript-eslint/scope-manager": "^7.0.0 || ^8.0.0", "@typescript-eslint/types": "^7.0.0 || ^8.0.0", "astrojs-compiler-sync": "^1.0.0", "debug": "^4.3.4", "entities": "^7.0.0", "eslint-scope": "^8.0.1", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "fast-glob": "^3.3.3", "is-glob": "^4.0.3", "semver": "^7.3.8" } }, "sha512-+QDcgc7e+au6EZ0YjMmRRjNoQo5bDMlaR45aWDoFsuxQTCM9qmCHRoiKJPELgckJ8Wmr7vcfpa9eCDHBFh6G4w=="], - - "astrojs-compiler-sync": ["astrojs-compiler-sync@1.1.1", "", { "dependencies": { "synckit": "^0.11.0" }, "peerDependencies": { "@astrojs/compiler": ">=0.27.0" } }, "sha512-0mKvB9sDQRIZPsEJadw6OaFbGJ92cJPPR++ICca9XEyiUAZqgVuk25jNmzHPT0KF80rI94trSZrUR5iHFXGGOQ=="], - "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], @@ -1040,7 +992,7 @@ "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.24", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA=="], @@ -1052,7 +1004,7 @@ "block-stream2": ["block-stream2@2.1.0", "", { "dependencies": { "readable-stream": "^3.4.0" } }, "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg=="], - "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -1076,16 +1028,12 @@ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "caniuse-lite": ["caniuse-lite@1.0.30001763", "", {}, "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], @@ -1218,11 +1166,9 @@ "difflib": ["difflib@0.2.4", "", { "dependencies": { "heap": ">= 0.2.0" } }, "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w=="], - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - "disposable-email-domains": ["disposable-email-domains@1.0.62", "", {}, "sha512-LBQvhRw7mznQTPoyZbsmYeNOZt1pN5aCsx4BAU/3siVFuiM9f2oyKzUaB8v1jbxFjE3aYqYiMo63kAL4pHgfWQ=="], - "doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="], + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="], @@ -1270,7 +1216,7 @@ "enhanced-resolve": ["enhanced-resolve@5.21.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA=="], - "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], @@ -1308,37 +1254,27 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", "@eslint/js": "8.57.1", "@humanwhocodes/config-array": "^0.13.0", "@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" } }, "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA=="], + "eslint": ["eslint@10.2.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.5.5", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q=="], "eslint-config-formbase": ["eslint-config-formbase@workspace:packages/config/eslint"], - "eslint-config-next": ["eslint-config-next@16.2.4", "", { "dependencies": { "@next/eslint-plugin-next": "16.2.4", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-A6ekXYFj/YQxBPMl45g3e+U8zJo+X2+ZQwcz34pPKjpc/3S4roBA2Rd9xWB4FKuSxhofo1/95WjzmUY+wHrOhg=="], - - "eslint-config-prettier": ["eslint-config-prettier@9.1.2", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ=="], - - "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], - - "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], - - "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="], + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], "eslint-plugin-eslint-comments": ["eslint-plugin-eslint-comments@3.2.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5", "ignore": "^5.0.5" }, "peerDependencies": { "eslint": ">=4.19.1" } }, "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ=="], - "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], - "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@4.6.2", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ=="], + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="], - "eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], + "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], - "eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], "esniff": ["esniff@2.0.1", "", { "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.62", "event-emitter": "^0.3.5", "type": "^2.7.2" } }, "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg=="], - "espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], @@ -1362,7 +1298,7 @@ "fast-equals": ["fast-equals@5.4.0", "", {}, "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw=="], - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], @@ -1380,7 +1316,7 @@ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], - "file-entry-cache": ["file-entry-cache@6.0.1", "", { "dependencies": { "flat-cache": "^3.0.4" } }, "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -1390,7 +1326,7 @@ "fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="], - "flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="], + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], @@ -1434,20 +1370,16 @@ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - "globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="], + "globals": ["globals@17.5.0", "", {}, "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g=="], "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - "goober": ["goober@2.1.18", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], - "h3": ["h3@1.15.1", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.3", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3" } }, "sha512-+ORaOBttdUm1E2Uu/obAyCguiI7MbBvsLTndc3gyK3zU+SYLoZXlyCP9Xgy0gikkGufFLTZXCXD6+4BsufnmHA=="], "hanji": ["hanji@0.0.5", "", { "dependencies": { "lodash.throttle": "^4.1.1", "sisteransi": "^1.0.5" } }, "sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw=="], @@ -1490,8 +1422,6 @@ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - "import-lazy": ["import-lazy@4.0.0", "", {}, "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw=="], "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], @@ -1522,8 +1452,6 @@ "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], - "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="], - "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], @@ -1550,8 +1478,6 @@ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], - "is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="], - "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], "is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], @@ -1608,8 +1534,6 @@ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], @@ -1620,7 +1544,7 @@ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], @@ -1762,7 +1686,7 @@ "mini-svg-data-uri": ["mini-svg-data-uri@1.4.4", "", { "bin": { "mini-svg-data-uri": "cli.js" } }, "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="], - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -1784,8 +1708,6 @@ "nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="], - "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "next": ["next@16.2.4", "", { "dependencies": { "@next/env": "16.2.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.4", "@next/swc-darwin-x64": "16.2.4", "@next/swc-linux-arm64-gnu": "16.2.4", "@next/swc-linux-arm64-musl": "16.2.4", "@next/swc-linux-x64-gnu": "16.2.4", "@next/swc-linux-x64-musl": "16.2.4", "@next/swc-win32-arm64-msvc": "16.2.4", "@next/swc-win32-x64-msvc": "16.2.4", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q=="], @@ -1818,8 +1740,6 @@ "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], - "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], - "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], @@ -1838,24 +1758,18 @@ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="], - "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], @@ -2038,8 +1952,6 @@ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="], "sort-object-keys": ["sort-object-keys@2.0.1", "", {}, "sha512-R89fO+z3x7hiKPXX5P0qim+ge6Y60AjtlW+QQpRozrrNcR1lw9Pkpm5MLB56HoNvdcLHL4wbpq16OcvGpEDJIg=="], @@ -2058,8 +1970,6 @@ "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], - "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], @@ -2096,14 +2006,10 @@ "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], - - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - "strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], @@ -2114,12 +2020,10 @@ "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], - "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="], "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], @@ -2132,8 +2036,6 @@ "test-exclude": ["test-exclude@7.0.1", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^9.0.4" } }, "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg=="], - "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], @@ -2166,14 +2068,12 @@ "trpc-to-openapi": ["trpc-to-openapi@2.4.0", "", { "dependencies": { "co-body": "6.2.0", "h3": "1.15.1", "openapi3-ts": "4.4.0" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.6.1" }, "peerDependencies": { "@trpc/server": "^11.1.0", "zod": "^3.23.8", "zod-openapi": "4.2.4" } }, "sha512-B6xrwOC3Ab0q1BWD/QbJzK4OUpCLoT02hAzshSUXEuIZGcJZkMG/OJ4/3gd20dyr8aI+CrFirpWKRIo7JmHbMQ=="], - "ts-api-utils": ["ts-api-utils@1.4.3", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw=="], + "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], "ts-pattern": ["ts-pattern@5.9.0", "", {}, "sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg=="], - "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="], @@ -2188,8 +2088,6 @@ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], - "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], @@ -2200,9 +2098,7 @@ "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], - "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - - "typescript-eslint": ["typescript-eslint@8.52.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.52.0", "@typescript-eslint/parser": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "ufo": ["ufo@1.6.2", "", {}, "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q=="], @@ -2226,8 +2122,6 @@ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], - "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -2298,8 +2192,6 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@babel/core/json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], @@ -2310,14 +2202,14 @@ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@formbase/utils/tailwind-merge": ["tailwind-merge@2.6.1", "", {}, "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="], "@formbase/web/date-fns": ["date-fns@3.6.0", "", {}, "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww=="], "@formbase/web/sonner": ["sonner@1.7.4", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw=="], - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "@microsoft/api-extractor/minimatch": ["minimatch@10.2.3", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg=="], "@microsoft/api-extractor/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], @@ -2326,8 +2218,6 @@ "@microsoft/tsdoc-config/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], - "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], - "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], @@ -2388,10 +2278,6 @@ "@rushstack/node-core-library/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "@rushstack/terminal/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "@rushstack/ts-command-line/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "@tailwindcss/node/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], @@ -2408,32 +2294,18 @@ "@types/ws/@types/node": ["@types/node@20.19.27", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug=="], - "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], - - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], - - "astro-eslint-parser/@astrojs/compiler": ["@astrojs/compiler@2.13.0", "", {}, "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw=="], - - "astro-eslint-parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], - - "astro-eslint-parser/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - "astro-eslint-parser/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + "@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "astro-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "ajv-draft-04/ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - "astro-eslint-parser/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], - - "astro-eslint-parser/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + "ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], "better-auth/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], "browserslist/baseline-browser-mapping": ["baseline-browser-mapping@2.9.13", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-WhtvB2NG2wjr04+h77sg3klAIwrgOqnjS49GGudnUPGFFgg7G17y7Qecqp+2Dr5kUDxNRBca0SK7cG8JwzkWDQ=="], - "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "drizzle-kit/esbuild": ["esbuild@0.19.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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], "drizzle-kit/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], @@ -2442,37 +2314,23 @@ "editorconfig/minimatch": ["minimatch@9.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w=="], - "eslint-config-next/eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="], - - "eslint-config-next/globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="], - - "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - "eslint-plugin-eslint-comments/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-plugin-import/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + "eslint-plugin-jsx-a11y/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "eslint-plugin-react/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + "eslint-plugin-react/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "eslint-plugin-react-hooks/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], - "flat-cache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], @@ -2482,6 +2340,8 @@ "minio/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "mlly/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], @@ -2502,34 +2362,28 @@ "rollup/@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg=="], - "string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], "test-exclude/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "tsup/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], - "typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.52.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/type-utils": "8.52.0", "@typescript-eslint/utils": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q=="], - - "typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.52.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg=="], - - "typescript-eslint/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.52.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.52.0", "@typescript-eslint/tsconfig-utils": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ=="], - - "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.52.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ=="], - "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], "vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], @@ -2574,14 +2428,8 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "@microsoft/api-extractor/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], - "@microsoft/tsdoc-config/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "@react-email/heading/@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" }, "optionalPeers": ["@types/react"] }, "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw=="], "@react-email/render/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], @@ -2610,12 +2458,8 @@ "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "astro-eslint-parser/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], - "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="], @@ -2666,9 +2510,9 @@ "editorconfig/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "eslint-config-next/eslint-plugin-react-hooks/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "eslint-plugin-jsx-a11y/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "flat-cache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -2678,38 +2522,10 @@ "resend/@react-email/render/react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "test-exclude/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], - - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], - - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], - - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], - - "typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], - - "typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], - - "typescript-eslint/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "typescript-eslint/@typescript-eslint/typescript-estree/ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], @@ -2760,30 +2576,22 @@ "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "@microsoft/api-extractor/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "drizzle-kit/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "resend/@react-email/render/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], - - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], + "editorconfig/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], + "eslint-plugin-jsx-a11y/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "eslint-plugin-react/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "typescript-eslint/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "resend/@react-email/render/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], + "test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "drizzle-kit/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], } } diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..26e8561 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,56 @@ +// @ts-nocheck +import base from './packages/config/eslint/base.js'; +import next from './packages/config/eslint/next.js'; +import react from './packages/config/eslint/react.js'; + +const webFiles = ['apps/web/**/*.{js,jsx,mjs,ts,tsx,mts,cts}']; +const uiFiles = ['packages/ui/**/*.{js,jsx,mjs,ts,tsx,mts,cts}']; +const reactFiles = [...webFiles, ...uiFiles]; + +const scopeConfigs = (configs, files, ignorePrefix) => + configs.map((config) => { + if (config.ignores && !config.files) { + return { + ...config, + ignores: config.ignores.map((pattern) => `${ignorePrefix}/${pattern}`), + }; + } + + return { + ...config, + files, + }; + }); + +export default [ + { + ignores: [ + '**/node_modules/**', + '**/dist/**', + '**/.next/**', + '**/.turbo/**', + '**/coverage/**', + '**/test-results/**', + '**/playwright-report/**', + 'apps/web/next-env.d.ts', + 'packages/core/.tsup/**', + ], + }, + ...base, + ...scopeConfigs(next, webFiles, 'apps/web'), + ...scopeConfigs(react, reactFiles, 'packages/ui'), + { + files: ['tests/**/*.{js,jsx,mjs,ts,tsx,mts,cts}'], + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unnecessary-condition': 'off', + '@typescript-eslint/require-await': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/use-unknown-in-catch-callback-variable': 'off', + }, + }, +]; diff --git a/package.json b/package.json index c12e58d..5aa2606 100644 --- a/package.json +++ b/package.json @@ -25,15 +25,15 @@ "tests:ui": "bun run --cwd=tests test:e2e:ui", "typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo" }, + "dependencies": { + "disposable-email-domains": "^1.0.62" + }, "devDependencies": { "@formbase/tsconfig": "workspace:*", "@ianvs/prettier-plugin-sort-imports": "^4.7.1", - "@types/eslint": "^8.56.12", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "eslint": "^8.57.1", + "@types/eslint": "^9.6.1", + "eslint": "^10.2.1", "eslint-config-formbase": "workspace:*", - "eslint-plugin-eslint-comments": "^3.2.0", "prettier": "^3.8.3", "prettier-plugin-astro": "^0.13.0", "prettier-plugin-curly": "^0.2.2", @@ -42,10 +42,7 @@ "prettier-plugin-tailwindcss": "^0.5.14", "rimraf": "^5.0.10", "turbo": "^2.9.6", - "typescript": "5.8.2" + "typescript": "6.0.3" }, - "packageManager": "bun@1.3.11", - "dependencies": { - "disposable-email-domains": "^1.0.62" - } + "packageManager": "bun@1.3.11" } diff --git a/packages/api/.eslintrc.cjs b/packages/api/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/api/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/api/lib/audit-log.ts b/packages/api/lib/audit-log.ts index 1f6b255..c3fbfe3 100644 --- a/packages/api/lib/audit-log.ts +++ b/packages/api/lib/audit-log.ts @@ -1,10 +1,10 @@ -import type { LibSQLDatabase } from 'drizzle-orm/libsql'; +import type { db as database } from '@formbase/db'; import { drizzlePrimitives } from '@formbase/db'; import { apiAuditLogs } from '@formbase/db/schema'; import { generateId } from '@formbase/utils/generate-id'; -type Database = LibSQLDatabase>; +type Database = typeof database; interface AuditLogParams { apiKeyId: string | null; @@ -38,7 +38,13 @@ function sanitizeRequestBody(body: unknown): string | null { if (typeof body !== 'object') return JSON.stringify(body); const sanitized = { ...(body as Record) }; - const sensitiveKeys = ['password', 'token', 'secret', 'apiKey', 'authorization']; + const sensitiveKeys = [ + 'password', + 'token', + 'secret', + 'apiKey', + 'authorization', + ]; for (const key of sensitiveKeys) { if (key in sanitized) { @@ -51,5 +57,7 @@ function sanitizeRequestBody(body: unknown): string | null { export async function cleanupOldAuditLogs(db: Database) { const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000); - await db.delete(apiAuditLogs).where(drizzlePrimitives.lt(apiAuditLogs.createdAt, ninetyDaysAgo)); + await db + .delete(apiAuditLogs) + .where(drizzlePrimitives.lt(apiAuditLogs.createdAt, ninetyDaysAgo)); } diff --git a/packages/api/middleware/api-auth.ts b/packages/api/middleware/api-auth.ts index f44de42..bd08af7 100644 --- a/packages/api/middleware/api-auth.ts +++ b/packages/api/middleware/api-auth.ts @@ -1,17 +1,19 @@ -import type { LibSQLDatabase } from 'drizzle-orm/libsql'; +import type { db as database } from '@formbase/db'; import { drizzlePrimitives } from '@formbase/db'; import { apiKeys } from '@formbase/db/schema'; -const { and, eq, gt, isNull, or } = drizzlePrimitives; - import { hashApiKey } from '../lib/api-key'; -type Database = LibSQLDatabase>; +const { and, eq, gt, isNull, or } = drizzlePrimitives; + +type Database = typeof database; +type AfterResponse = (task: () => Promise | void) => void; export async function validateApiKey( authorization: string | null | undefined, db: Database, + afterResponse?: AfterResponse, ) { if (!authorization?.startsWith('Bearer ')) { return null; @@ -30,11 +32,19 @@ export async function validateApiKey( }); if (apiKey) { - db.update(apiKeys) - .set({ lastUsedAt: new Date() }) - .where(eq(apiKeys.id, apiKey.id)) - .then(() => {}) - .catch(() => {}); + const updateLastUsedAt = async () => { + await db + .update(apiKeys) + .set({ lastUsedAt: new Date() }) + .where(eq(apiKeys.id, apiKey.id)) + .catch(() => undefined); + }; + + if (afterResponse) { + afterResponse(updateLastUsedAt); + } else { + void updateLastUsedAt(); + } } return apiKey; diff --git a/packages/api/routers/api-v1/forms.ts b/packages/api/routers/api-v1/forms.ts index 4c06c29..519c46e 100644 --- a/packages/api/routers/api-v1/forms.ts +++ b/packages/api/routers/api-v1/forms.ts @@ -69,7 +69,7 @@ export const formsRouter = createApiV1Router({ description: form.description, returnUrl: form.returnUrl, keys: parseJsonArray(form.keys), - submissionCount: form.formData?.length ?? 0, + submissionCount: form.formData.length, createdAt: form.createdAt.toISOString(), updatedAt: form.updatedAt?.toISOString() ?? null, })), @@ -144,7 +144,7 @@ export const formsRouter = createApiV1Router({ description: form.description, returnUrl: form.returnUrl, keys: parseJsonArray(form.keys), - submissionCount: form.formData?.length ?? 0, + submissionCount: form.formData.length, createdAt: form.createdAt.toISOString(), updatedAt: form.updatedAt?.toISOString() ?? null, }; diff --git a/packages/api/routers/api-v1/index.ts b/packages/api/routers/api-v1/index.ts index 51db99c..01e6962 100644 --- a/packages/api/routers/api-v1/index.ts +++ b/packages/api/routers/api-v1/index.ts @@ -1,8 +1,6 @@ -import { initTRPC } from '@trpc/server'; - import { formsRouter } from './forms'; import { submissionsRouter } from './submissions'; -import { createApiV1Router, type ApiV1Context } from './trpc'; +import { createApiV1Caller, createApiV1Router } from './trpc'; export const apiV1Router = createApiV1Router({ forms: formsRouter, @@ -11,7 +9,6 @@ export const apiV1Router = createApiV1Router({ export type ApiV1Router = typeof apiV1Router; -const t = initTRPC.context().create(); -export const createApiV1CallerFactory = t.createCallerFactory(apiV1Router); +export const createApiV1CallerFactory = createApiV1Caller(apiV1Router); export { createApiV1Context, type ApiV1Context } from './trpc'; diff --git a/packages/api/routers/api-v1/ownership.ts b/packages/api/routers/api-v1/ownership.ts index f83f29d..17142fd 100644 --- a/packages/api/routers/api-v1/ownership.ts +++ b/packages/api/routers/api-v1/ownership.ts @@ -1,28 +1,16 @@ -import { TRPCError } from '@trpc/server'; - -import { drizzlePrimitives } from '@formbase/db'; - -const { and, eq } = drizzlePrimitives; +import type { db as database } from '@formbase/db'; -type DbContext = { db: typeof import('@formbase/db').db; user: { id: string } }; +import { TRPCError } from '@trpc/server'; -export async function assertApiFormOwnership( - ctx: DbContext, - formId: string, -) { - const form = await ctx.db.query.forms.findFirst({ - where: (table) => - and(eq(table.id, formId), eq(table.userId, ctx.user.id)), - }); +import { + assertFormDataOwnership, + assertFormOwnership, +} from '../form-ownership'; - if (!form) { - throw new TRPCError({ - code: 'NOT_FOUND', - message: 'Form not found', - }); - } +type DbContext = { db: typeof database; user: { id: string } }; - return form; +export async function assertApiFormOwnership(ctx: DbContext, formId: string) { + return assertFormOwnership(ctx, formId, 'Form not found'); } export async function assertApiSubmissionOwnership( @@ -30,14 +18,13 @@ export async function assertApiSubmissionOwnership( formId: string, submissionId: string, ) { - await assertApiFormOwnership(ctx, formId); - - const submission = await ctx.db.query.formDatas.findFirst({ - where: (table) => - and(eq(table.id, submissionId), eq(table.formId, formId)), - }); + const submission = await assertFormDataOwnership( + ctx, + submissionId, + 'Submission not found', + ); - if (!submission) { + if (submission.formId !== formId) { throw new TRPCError({ code: 'NOT_FOUND', message: 'Submission not found', diff --git a/packages/api/routers/api-v1/trpc.ts b/packages/api/routers/api-v1/trpc.ts index 51ff11b..edf8834 100644 --- a/packages/api/routers/api-v1/trpc.ts +++ b/packages/api/routers/api-v1/trpc.ts @@ -1,16 +1,20 @@ -import { initTRPC, TRPCError } from '@trpc/server'; +import type { User } from '@formbase/db/schema'; import type { OpenApiMeta } from 'trpc-to-openapi'; + +import { initTRPC, TRPCError } from '@trpc/server'; import { ZodError } from 'zod'; -import type { User } from '@formbase/db/schema'; import { db } from '@formbase/db'; import { validateApiKey } from '../../middleware/api-auth'; import { checkRateLimit } from '../../middleware/rate-limit'; +type AfterResponse = (task: () => Promise | void) => void; + export interface ApiV1Context { db: typeof db; headers: Headers; + afterResponse?: AfterResponse; apiKey?: { id: string; userId: string; @@ -22,12 +26,14 @@ export interface ApiV1Context { retryAfterSeconds?: number; } -export const createApiV1Context = async (opts: { +export const createApiV1Context = (opts: { headers: Headers; -}): Promise => { + afterResponse?: AfterResponse; +}): ApiV1Context => { return { db, headers: opts.headers, + ...(opts.afterResponse ? { afterResponse: opts.afterResponse } : {}), }; }; @@ -49,11 +55,17 @@ const t = initTRPC export const createApiV1Router = t.router; +export const createApiV1Caller = t.createCallerFactory; + export const publicApiProcedure = t.procedure; export const apiKeyProcedure = t.procedure.use(async ({ ctx, next }) => { const authorization = ctx.headers.get('authorization'); - const apiKey = await validateApiKey(authorization, ctx.db); + const apiKey = await validateApiKey( + authorization, + ctx.db, + ctx.afterResponse, + ); if (!apiKey) { throw new TRPCError({ @@ -71,14 +83,21 @@ export const apiKeyProcedure = t.procedure.use(async ({ ctx, next }) => { }); } + const apiKeyCtx = { + id: apiKey.id, + userId: apiKey.userId, + user: apiKey.user, + }; + + ctx.apiKey = apiKeyCtx; + ctx.user = apiKey.user; + ctx.rateLimitRemaining = rateLimit.remaining; + ctx.rateLimitReset = rateLimit.resetAt.getTime(); + return next({ ctx: { ...ctx, - apiKey: { - id: apiKey.id, - userId: apiKey.userId, - user: apiKey.user, - }, + apiKey: apiKeyCtx, user: apiKey.user, rateLimitRemaining: rateLimit.remaining, rateLimitReset: rateLimit.resetAt.getTime(), diff --git a/packages/api/routers/form-ownership.ts b/packages/api/routers/form-ownership.ts index 521cf1a..363632f 100644 --- a/packages/api/routers/form-ownership.ts +++ b/packages/api/routers/form-ownership.ts @@ -1,32 +1,36 @@ +import type { db as database } from '@formbase/db'; + import { TRPCError } from '@trpc/server'; import { drizzlePrimitives } from '@formbase/db'; -import { type createTRPCContext } from '../trpc'; - const { and, eq } = drizzlePrimitives; -type Context = Awaited>; -type AuthedContext = Context & { user: NonNullable }; +type OwnershipContext = { db: typeof database; user: { id: string } }; export const assertFormOwnership = async ( - ctx: AuthedContext, + ctx: OwnershipContext, formId: string, + notFoundMessage?: string, ) => { const form = await ctx.db.query.forms.findFirst({ where: (table) => and(eq(table.id, formId), eq(table.userId, ctx.user.id)), }); if (!form) { - throw new TRPCError({ code: 'NOT_FOUND' }); + throw new TRPCError({ + code: 'NOT_FOUND', + ...(notFoundMessage ? { message: notFoundMessage } : {}), + }); } return form; }; export const assertFormDataOwnership = async ( - ctx: AuthedContext, + ctx: OwnershipContext, formDataId: string, + notFoundMessage?: string, ) => { const formData = await ctx.db.query.formDatas.findFirst({ where: (table, { eq }) => eq(table.id, formDataId), @@ -39,10 +43,20 @@ export const assertFormDataOwnership = async ( }, }); - if (!formData?.form || formData.form.userId !== ctx.user.id) { - throw new TRPCError({ code: 'NOT_FOUND' }); + if (formData?.form.userId !== ctx.user.id) { + throw new TRPCError({ + code: 'NOT_FOUND', + ...(notFoundMessage ? { message: notFoundMessage } : {}), + }); } - const { form, ...rest } = formData; - return rest; + return { + id: formData.id, + formId: formData.formId, + data: formData.data, + createdAt: formData.createdAt, + isSpam: formData.isSpam, + spamReason: formData.spamReason, + manualOverride: formData.manualOverride, + }; }; diff --git a/packages/api/routers/formData.ts b/packages/api/routers/formData.ts index 7d217ed..e8493b8 100644 --- a/packages/api/routers/formData.ts +++ b/packages/api/routers/formData.ts @@ -7,10 +7,7 @@ import { generateId } from '@formbase/utils/generate-id'; import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; import { parseJsonObject, serializeJson } from '../utils/json'; -import { - assertFormDataOwnership, - assertFormOwnership, -} from './form-ownership'; +import { assertFormDataOwnership, assertFormOwnership } from './form-ownership'; const { eq } = drizzlePrimitives; @@ -106,7 +103,7 @@ export const formDataRouter = createTRPCRouter({ ...flattenObject({ ...data, data: parsed ?? {}, - } as Record), + }), ...normalized, }; }); diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index fe061ba..9fadae2 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs"] } diff --git a/packages/auth/.eslintrc.cjs b/packages/auth/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/auth/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index 66295ff..cba6256 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "lib": ["DOM", "DOM.Iterable", "ESNext"] }, - "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs"] } diff --git a/packages/config/eslint/.eslintrc.cjs b/packages/config/eslint/.eslintrc.cjs deleted file mode 100644 index b82c090..0000000 --- a/packages/config/eslint/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['./base.js'], -}; - -module.exports = config; diff --git a/packages/config/eslint/base.js b/packages/config/eslint/base.js index af54e55..5a4eff5 100644 --- a/packages/config/eslint/base.js +++ b/packages/config/eslint/base.js @@ -1,61 +1,75 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - ignorePatterns: ['node_modules', 'dist', '.next'], - env: { - es2022: true, - node: true, +// @ts-nocheck +const { fixupPluginRules } = require('@eslint/compat'); +const eslintComments = require('eslint-plugin-eslint-comments'); +const prettier = require('eslint-config-prettier'); +const tsPlugin = require('@typescript-eslint/eslint-plugin'); +const tsParser = require('@typescript-eslint/parser'); +const globals = require('globals'); + +const eslintCommentsPlugin = fixupPluginRules(eslintComments); + +const files = ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']; +const tsFiles = ['**/*.{ts,tsx,mts,cts}']; + +module.exports = [ + { + files, + languageOptions: { + ecmaVersion: 2022, + globals: { + ...globals.es2022, + ...globals.node, + }, + }, + plugins: { + 'eslint-comments': eslintCommentsPlugin, + }, + rules: { + ...eslintComments.configs.recommended.rules, + }, }, - extends: ['plugin:eslint-comments/recommended', 'prettier'], - overrides: [ - { - files: [ - '**/*.ts', - '**/*.tsx', - '**/*.js', - '**/*.jsx', - '**/*.mjs', - '**/*.cjs', - ], - parser: '@typescript-eslint/parser', + { + files: tsFiles, + languageOptions: { + parser: tsParser, parserOptions: { project: true, }, - plugins: ['@typescript-eslint'], - extends: [ - 'plugin:@typescript-eslint/strict-type-checked', - 'plugin:@typescript-eslint/stylistic-type-checked', + }, + plugins: { + '@typescript-eslint': tsPlugin, + }, + rules: { + ...tsPlugin.configs['strict-type-checked'].rules, + ...tsPlugin.configs['stylistic-type-checked'].rules, + '@typescript-eslint/restrict-template-expressions': 'off', + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/array-type': [ + 'error', + { + default: 'array-simple', + readonly: 'array-simple', + }, + ], + '@typescript-eslint/consistent-type-imports': [ + 'warn', + { + prefer: 'type-imports', + fixStyle: 'inline-type-imports', + }, + ], + '@typescript-eslint/no-unused-vars': [ + 'warn', + { argsIgnorePattern: '^_' }, + ], + '@typescript-eslint/require-await': 'error', + '@typescript-eslint/no-misused-promises': [ + 'error', + { + checksVoidReturn: { attributes: false }, + }, ], - rules: { - '@typescript-eslint/restrict-template-expressions': 'off', - '@typescript-eslint/consistent-type-definitions': 'off', - '@typescript-eslint/array-type': [ - 'error', - { - default: 'array-simple', - readonly: 'array-simple', - }, - ], - '@typescript-eslint/consistent-type-imports': [ - 'warn', - { - prefer: 'type-imports', - fixStyle: 'inline-type-imports', - }, - ], - '@typescript-eslint/no-unused-vars': [ - 'warn', - { argsIgnorePattern: '^_' }, - ], - '@typescript-eslint/require-await': 'error', - '@typescript-eslint/no-misused-promises': [ - 'error', - { - checksVoidReturn: { attributes: false }, - }, - ], - }, }, - ], -}; - -module.exports = config; + }, + prettier, +]; diff --git a/packages/config/eslint/next.js b/packages/config/eslint/next.js index ca98818..20ea235 100644 --- a/packages/config/eslint/next.js +++ b/packages/config/eslint/next.js @@ -1,6 +1,19 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - extends: ['plugin:@next/next/recommended'], -}; +// @ts-nocheck +const nextPlugin = require('@next/eslint-plugin-next'); -module.exports = config; +module.exports = [ + { + files: ['**/*.{js,jsx,mjs,ts,tsx,mts,cts}'], + plugins: { + '@next/next': nextPlugin, + }, + settings: { + next: { + rootDir: 'apps/web/', + }, + }, + rules: { + ...nextPlugin.configs.recommended.rules, + }, + }, +]; diff --git a/packages/config/eslint/package.json b/packages/config/eslint/package.json index ea01a39..71a5264 100644 --- a/packages/config/eslint/package.json +++ b/packages/config/eslint/package.json @@ -12,17 +12,19 @@ "typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0" - }, - "devDependencies": { - "@formbase/tsconfig": "workspace:*", - "astro-eslint-parser": "^1.4.0", - "eslint-config-next": "^16.2.4", - "eslint-config-prettier": "^9.1.0", + "@eslint/compat": "^2.0.5", + "@next/eslint-plugin-next": "^16.2.4", + "@typescript-eslint/eslint-plugin": "^8.59.1", + "@typescript-eslint/parser": "^8.59.1", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^4.6.2" + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^17.5.0" + }, + "devDependencies": { + "@formbase/tsconfig": "workspace:*", + "eslint": "^10.2.1" } } diff --git a/packages/config/eslint/react.js b/packages/config/eslint/react.js index d08ad70..a4cf4ec 100644 --- a/packages/config/eslint/react.js +++ b/packages/config/eslint/react.js @@ -1,25 +1,35 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - overrides: [ - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], - extends: [ - 'plugin:react/recommended', - 'plugin:react-hooks/recommended', - 'plugin:jsx-a11y/recommended', - ], - settings: { - react: { - version: 'detect', - }, - }, - rules: { - 'react/react-in-jsx-scope': 'off', - 'react/prop-types': 'off', - 'react/no-unknown-property': ['error', { ignore: ['tw'] }], +// @ts-nocheck +const { fixupPluginRules } = require('@eslint/compat'); +const jsxA11y = require('eslint-plugin-jsx-a11y'); +const react = require('eslint-plugin-react'); +const reactHooks = require('eslint-plugin-react-hooks'); + +const jsxA11yPlugin = fixupPluginRules(jsxA11y); +const reactPlugin = fixupPluginRules(react); +const reactHooksPlugin = fixupPluginRules(reactHooks); + +module.exports = [ + { + files: ['**/*.{ts,tsx,js,jsx}'], + plugins: { + react: reactPlugin, + 'react-hooks': reactHooksPlugin, + 'jsx-a11y': jsxA11yPlugin, + }, + settings: { + react: { + version: 'detect', }, }, - ], -}; - -module.exports = config; + rules: { + ...react.configs.flat.recommended.rules, + ...react.configs.flat['jsx-runtime'].rules, + ...jsxA11y.flatConfigs.recommended.rules, + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'react/no-unknown-property': ['error', { ignore: ['tw'] }], + }, + }, +]; diff --git a/packages/config/eslint/tsconfig.json b/packages/config/eslint/tsconfig.json index 8112b52..43e61c4 100644 --- a/packages/config/eslint/tsconfig.json +++ b/packages/config/eslint/tsconfig.json @@ -1,4 +1,4 @@ { "extends": ["@formbase/tsconfig/base.json"], - "include": ["*.js", ".eslintrc.cjs"] + "include": ["*.js"] } diff --git a/packages/config/tailwind/.eslintrc.cjs b/packages/config/tailwind/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/config/tailwind/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/config/tailwind/src/preset.ts b/packages/config/tailwind/src/preset.ts index dadf53a..3332f68 100644 --- a/packages/config/tailwind/src/preset.ts +++ b/packages/config/tailwind/src/preset.ts @@ -1,3 +1,4 @@ +import themer from '@tailus/themer'; import aspectRatio from '@tailwindcss/aspect-ratio'; import containerQueries from '@tailwindcss/container-queries'; import forms from '@tailwindcss/forms'; @@ -6,7 +7,6 @@ import animate from 'tailwindcss-animate'; import plugin from 'tailwindcss/plugin'; import { type Config } from 'tailwindcss'; -import themer from '@tailus/themer'; // Default sans-serif font stack (previously from tailwindcss/defaultTheme) const defaultSansFonts = [ @@ -126,47 +126,47 @@ export const tailwindPreset: Config = { typography, forms, aspectRatio, - { - config: containerQueries.config ?? {}, - handler: containerQueries.handler, - }, + containerQueries, themer({ - radius: 'smoothest', - background: 'lighter', - border: 'light', - padding: 'large', - components: { - button: { - rounded: '2xl', - }, + radius: 'smoothest', + background: 'lighter', + border: 'light', + padding: 'large', + components: { + button: { + rounded: '2xl', }, - }), + }, + }), // Base UI data attribute variants - plugin(function ({ addVariant }) { + plugin(function (api) { // Base UI state variants - addVariant('data-open', '&[data-open]'); - addVariant('data-closed', '&:not([data-open])'); - addVariant('data-checked', '&[data-checked]'); - addVariant('data-unchecked', '&:not([data-checked])'); - addVariant('data-disabled', '&[data-disabled]'); - addVariant('data-highlighted', '&[data-highlighted]'); - addVariant('data-pressed', '&[data-pressed]'); - addVariant('data-selected', '&[data-selected]'); - addVariant('data-invalid', '&[data-invalid]'); - addVariant('data-valid', '&[data-valid]'); - addVariant('data-required', '&[data-required]'); - addVariant('data-readonly', '&[data-readonly]'); - addVariant('data-focus', '&[data-focus]'); - addVariant('data-focus-visible', '&[data-focus-visible]'); - addVariant('data-active', '&[data-active]'); - addVariant('data-hover', '&[data-hover]'); + api.addVariant('data-open', '&[data-open]'); + api.addVariant('data-closed', '&:not([data-open])'); + api.addVariant('data-checked', '&[data-checked]'); + api.addVariant('data-unchecked', '&:not([data-checked])'); + api.addVariant('data-disabled', '&[data-disabled]'); + api.addVariant('data-highlighted', '&[data-highlighted]'); + api.addVariant('data-pressed', '&[data-pressed]'); + api.addVariant('data-selected', '&[data-selected]'); + api.addVariant('data-invalid', '&[data-invalid]'); + api.addVariant('data-valid', '&[data-valid]'); + api.addVariant('data-required', '&[data-required]'); + api.addVariant('data-readonly', '&[data-readonly]'); + api.addVariant('data-focus', '&[data-focus]'); + api.addVariant('data-focus-visible', '&[data-focus-visible]'); + api.addVariant('data-active', '&[data-active]'); + api.addVariant('data-hover', '&[data-hover]'); - // For children with data attributes - addVariant('in-data-open', '[data-open] &'); - addVariant('in-data-closed', ':not([data-open]) &'); + // for children with data attributes + api.addVariant('in-data-open', '[data-open] &'); + api.addVariant('in-data-closed', ':not([data-open]) &'); - // Supports backdrop filter - addVariant('supports-backdrop-filter', '@supports (backdrop-filter: blur(0))'); + // supports backdrop filter + api.addVariant( + 'supports-backdrop-filter', + '@supports (backdrop-filter: blur(0))', + ); }), ], }; diff --git a/packages/config/tailwind/tsconfig.json b/packages/config/tailwind/tsconfig.json index 3f01aee..09510b4 100644 --- a/packages/config/tailwind/tsconfig.json +++ b/packages/config/tailwind/tsconfig.json @@ -1,4 +1,4 @@ { "extends": ["@formbase/tsconfig/base.json"], - "include": ["**/*.ts", ".eslintrc.cjs"] + "include": ["**/*.ts"] } diff --git a/packages/config/tsconfig/base.json b/packages/config/tsconfig/base.json index 75c712f..f7d3802 100644 --- a/packages/config/tsconfig/base.json +++ b/packages/config/tsconfig/base.json @@ -13,6 +13,7 @@ "noUncheckedIndexedAccess": true, "noUnusedLocals": true, "noUnusedParameters": true, + "ignoreDeprecations": "6.0", "isolatedModules": true, diff --git a/packages/core/.eslintrc.cjs b/packages/core/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/core/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index fe061ba..9fadae2 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs"] } diff --git a/packages/db/.eslintrc.cjs b/packages/db/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/db/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/db/drizzle.config.ts b/packages/db/drizzle.config.ts index a7381d8..38127a0 100644 --- a/packages/db/drizzle.config.ts +++ b/packages/db/drizzle.config.ts @@ -4,11 +4,11 @@ import { env } from '@formbase/env'; export default { dialect: 'sqlite', - driver: 'libsql', + driver: 'turso', schema: './schema/index.ts', out: './drizzle', dbCredentials: { url: env.DATABASE_URL, - authToken: env.TURSO_AUTH_TOKEN, + ...(env.TURSO_AUTH_TOKEN ? { authToken: env.TURSO_AUTH_TOKEN } : {}), }, } satisfies Config; diff --git a/packages/db/index.ts b/packages/db/index.ts index 414dc5a..88e77ee 100644 --- a/packages/db/index.ts +++ b/packages/db/index.ts @@ -1,5 +1,17 @@ import { createClient } from '@libsql/client'; -import { and, count, eq, gt, gte, inArray, isNull, lt, lte, or, sql } from 'drizzle-orm'; +import { + and, + count, + eq, + gt, + gte, + inArray, + isNull, + lt, + lte, + or, + sql, +} from 'drizzle-orm'; import { drizzle } from 'drizzle-orm/libsql'; import { env } from '@formbase/env'; @@ -17,7 +29,7 @@ if (databaseUrl.startsWith('libsql://') && !authToken) { export const queryClient = createClient({ url: databaseUrl, - authToken, + ...(authToken ? { authToken } : {}), }); export const db = drizzle(queryClient, { diff --git a/packages/db/migrate.ts b/packages/db/migrate.ts index e8ee1d3..8f81ea8 100644 --- a/packages/db/migrate.ts +++ b/packages/db/migrate.ts @@ -1,5 +1,7 @@ import 'dotenv/config'; +import type { Table } from 'drizzle-orm'; + import { getTableName, isTable, sql } from 'drizzle-orm'; import { migrate } from 'drizzle-orm/libsql/migrator'; import { readMigrationFiles } from 'drizzle-orm/migrator'; @@ -10,8 +12,8 @@ import * as schema from './schema'; const migrationsFolder = './drizzle'; const migrationsTable = '__drizzle_migrations'; const migrations = readMigrationFiles({ migrationsFolder }); -const tableNames = Object.values(schema) - .filter(isTable) +const tableNames = (Object.values(schema) as unknown[]) + .filter((value): value is Table => isTable(value)) .map((table) => getTableName(table)); const getLastMigrationTimestamp = async () => { @@ -58,8 +60,8 @@ const baselineMigrations = async () => { return; } - await db.session.run(sql` - CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} ( + await queryClient.execute(` + CREATE TABLE IF NOT EXISTS ${migrationsTable} ( id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric @@ -70,13 +72,14 @@ const baselineMigrations = async () => { sql`INSERT INTO ${sql.identifier(migrationsTable)} ("hash", "created_at") VALUES (${latest.hash}, ${latest.folderMillis})`, ); - console.warn( - 'Migrations were baselined to match the current schema.', - ); + console.warn('Migrations were baselined to match the current schema.'); }; let baselined = false; -if ((await getLastMigrationTimestamp()) === null && (await hasAnySchemaTable())) { +if ( + (await getLastMigrationTimestamp()) === null && + (await hasAnySchemaTable()) +) { await baselineMigrations(); baselined = true; } @@ -93,4 +96,4 @@ if (!baselined) { } } -await queryClient.close(); +queryClient.close(); diff --git a/packages/db/package.json b/packages/db/package.json index 182dbe3..c4d9ae7 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@formbase/tsconfig": "workspace:*", + "@types/node": "^20.19.39", "dotenv": "^16.4.5", "dotenv-cli": "^7.4.2", "drizzle-kit": "^0.21.4", diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json index 84bf774..5ce8675 100644 --- a/packages/db/tsconfig.json +++ b/packages/db/tsconfig.json @@ -1,4 +1,4 @@ { "extends": ["@formbase/tsconfig/base.json"], - "include": ["**/*.ts", ".eslintrc.cjs", "**/*.mjs"] + "include": ["**/*.ts", "**/*.mjs"] } diff --git a/packages/email/index.ts b/packages/email/index.ts index 34d2f13..0266a4b 100644 --- a/packages/email/index.ts +++ b/packages/email/index.ts @@ -47,7 +47,14 @@ const getTransporter = () => { name: 'noop', version: '1.0.0', send: (_mail, callback) => { - callback(null, { messageId: 'test-message-id' }); + callback(null, { + accepted: [], + envelope: { from: '', to: [] }, + messageId: 'test-message-id', + pending: [], + rejected: [], + response: '250 ok', + }); }, }); return cachedTransporter; @@ -74,7 +81,9 @@ const getTransporter = () => { !!env.SMTP_PASS; if (!hasSmtpConfig) { - throw new Error('Email transport not configured. Set SMTP_TRANSPORT to resend or smtp.'); + throw new Error( + 'Email transport not configured. Set SMTP_TRANSPORT to resend or smtp.', + ); } cachedTransporter = createSmtpTransport(); @@ -91,4 +100,3 @@ export const sendMail = async ({ to, subject, body }: MessageInfo) => { }; return transporter.sendMail(mailOptions); }; - diff --git a/packages/email/tsconfig.json b/packages/email/tsconfig.json index a270307..9fadae2 100644 --- a/packages/email/tsconfig.json +++ b/packages/email/tsconfig.json @@ -3,6 +3,5 @@ "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs"] } - diff --git a/packages/env/.eslintrc.cjs b/packages/env/.eslintrc.cjs deleted file mode 100644 index 0c9b06c..0000000 --- a/packages/env/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base'], -}; - -module.exports = config; diff --git a/packages/env/tsconfig.json b/packages/env/tsconfig.json index fe061ba..44c57c5 100644 --- a/packages/env/tsconfig.json +++ b/packages/env/tsconfig.json @@ -1,7 +1,8 @@ { "extends": ["@formbase/tsconfig/base.json"], "compilerOptions": { + "types": ["node"], "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.mjs", "**/*.js", "**/*.cjs"] } diff --git a/packages/ui/.eslintrc.cjs b/packages/ui/.eslintrc.cjs deleted file mode 100644 index a104a02..0000000 --- a/packages/ui/.eslintrc.cjs +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - extends: ['formbase/base', 'formbase/react'], -}; - -module.exports = config; diff --git a/packages/ui/hooks/use-mobile.ts b/packages/ui/hooks/use-mobile.ts new file mode 100644 index 0000000..f271f6c --- /dev/null +++ b/packages/ui/hooks/use-mobile.ts @@ -0,0 +1,27 @@ +import * as React from 'react'; + +const MOBILE_BREAKPOINT = 768; + +export function useIsMobile() { + const [isMobile, setIsMobile] = React.useState( + undefined, + ); + + React.useEffect(() => { + const mediaQuery = window.matchMedia( + `(max-width: ${MOBILE_BREAKPOINT - 1}px)`, + ); + const handleChange = () => { + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + }; + + mediaQuery.addEventListener('change', handleChange); + handleChange(); + + return () => { + mediaQuery.removeEventListener('change', handleChange); + }; + }, []); + + return isMobile ?? false; +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 8785535..37d93f3 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -16,6 +16,8 @@ "dependencies": { "@base-ui/react": "^1.0.0", "@hookform/resolvers": "^3.4.2", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-toast": "^1.2.15", "@tabler/icons-react": "^3.41.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -24,6 +26,7 @@ "embla-carousel-autoplay": "^8.6.0", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", + "next-themes": "^0.4.6", "react": "^19.2.5", "react-day-picker": "^9.14.0", "react-dom": "^19.2.5", diff --git a/packages/ui/primitives/button.tsx b/packages/ui/primitives/button.tsx index d28a2cc..1586b4e 100644 --- a/packages/ui/primitives/button.tsx +++ b/packages/ui/primitives/button.tsx @@ -47,6 +47,8 @@ const buttonVariants = cva( type ButtonProps = React.ComponentProps<'button'> & VariantProps & { asChild?: boolean; + nativeButton?: boolean; + render?: React.ReactElement; }; const Button = React.forwardRef( @@ -57,23 +59,34 @@ const Button = React.forwardRef( size = 'default', asChild = false, children, + nativeButton, + render, + type, ...props }, ref, ) => { - // Handle asChild by using the child element as the render prop const renderProp = - asChild && React.isValidElement(children) ? children : undefined; + render ?? + (asChild && React.isValidElement(children) ? children : undefined); + const primitiveProps = { + ...props, + ...(renderProp || nativeButton === false + ? { + ...(renderProp ? { render: renderProp } : {}), + nativeButton: false, + } + : { nativeButton, type }), + } as React.ComponentPropsWithoutRef; return ( - {asChild ? undefined : children} + {renderProp ? undefined : children} ); }, diff --git a/packages/ui/primitives/calendar.tsx b/packages/ui/primitives/calendar.tsx index f4f9e65..cd662d4 100644 --- a/packages/ui/primitives/calendar.tsx +++ b/packages/ui/primitives/calendar.tsx @@ -1,133 +1,136 @@ -"use client" +'use client'; + +import * as React from 'react'; + +import type { DayButton } from 'react-day-picker'; -import * as React from "react" import { - DayPicker, - getDefaultClassNames, - type DayButton, -} from "react-day-picker" + IconChevronDown, + IconChevronLeft, + IconChevronRight, +} from '@tabler/icons-react'; +import { DayPicker, getDefaultClassNames } from 'react-day-picker'; -import { cn } from "@formbase/ui/utils/cn" -import { Button, buttonVariants } from "@formbase/ui/primitives/button" -import { IconChevronLeft, IconChevronRight, IconChevronDown } from "@tabler/icons-react" +import { Button, buttonVariants } from '@formbase/ui/primitives/button'; +import { cn } from '@formbase/ui/utils/cn'; function Calendar({ className, classNames, showOutsideDays = true, - captionLayout = "label", - buttonVariant = "ghost", + captionLayout = 'label', + buttonVariant = 'ghost', formatters, components, ...props }: React.ComponentProps & { - buttonVariant?: React.ComponentProps["variant"] + buttonVariant?: React.ComponentProps['variant']; }) { - const defaultClassNames = getDefaultClassNames() + const defaultClassNames = getDefaultClassNames(); return ( svg]:**:rtl:rotate-180`, String.raw`[.rdp-button\_previous>svg]:**:rtl:rotate-180`, - className + className, )} captionLayout={captionLayout} formatters={{ formatMonthDropdown: (date) => - date.toLocaleString("default", { month: "short" }), + date.toLocaleString('default', { month: 'short' }), ...formatters, }} classNames={{ - root: cn("w-fit", defaultClassNames.root), + root: cn('w-fit', defaultClassNames.root), months: cn( - "flex gap-4 flex-col md:flex-row relative", - defaultClassNames.months + 'flex gap-4 flex-col md:flex-row relative', + defaultClassNames.months, ), - month: cn("flex flex-col w-full gap-4", defaultClassNames.month), + month: cn('flex flex-col w-full gap-4', defaultClassNames.month), nav: cn( - "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between", - defaultClassNames.nav + 'flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between', + defaultClassNames.nav, ), button_previous: cn( buttonVariants({ variant: buttonVariant }), - "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", - defaultClassNames.button_previous + 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none', + defaultClassNames.button_previous, ), button_next: cn( buttonVariants({ variant: buttonVariant }), - "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", - defaultClassNames.button_next + 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none', + defaultClassNames.button_next, ), month_caption: cn( - "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)", - defaultClassNames.month_caption + 'flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)', + defaultClassNames.month_caption, ), dropdowns: cn( - "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5", - defaultClassNames.dropdowns + 'w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5', + defaultClassNames.dropdowns, ), dropdown_root: cn( - "relative cn-calendar-dropdown-root rounded-(--cell-radius)", - defaultClassNames.dropdown_root + 'relative cn-calendar-dropdown-root rounded-(--cell-radius)', + defaultClassNames.dropdown_root, ), dropdown: cn( - "absolute bg-popover inset-0 opacity-0", - defaultClassNames.dropdown + 'absolute bg-popover inset-0 opacity-0', + defaultClassNames.dropdown, ), caption_label: cn( - "select-none font-medium", - captionLayout === "label" - ? "text-sm" - : "cn-calendar-caption-label rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5", - defaultClassNames.caption_label - ), - table: "w-full border-collapse", - weekdays: cn("flex", defaultClassNames.weekdays), + 'select-none font-medium', + captionLayout === 'label' + ? 'text-sm' + : 'cn-calendar-caption-label rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5', + defaultClassNames.caption_label, + ), + table: 'w-full border-collapse', + weekdays: cn('flex', defaultClassNames.weekdays), weekday: cn( - "text-muted-foreground rounded-(--cell-radius) flex-1 font-normal text-[0.8rem] select-none", - defaultClassNames.weekday + 'text-muted-foreground rounded-(--cell-radius) flex-1 font-normal text-[0.8rem] select-none', + defaultClassNames.weekday, ), - week: cn("flex w-full mt-2", defaultClassNames.week), + week: cn('flex w-full mt-2', defaultClassNames.week), week_number_header: cn( - "select-none w-(--cell-size)", - defaultClassNames.week_number_header + 'select-none w-(--cell-size)', + defaultClassNames.week_number_header, ), week_number: cn( - "text-[0.8rem] select-none text-muted-foreground", - defaultClassNames.week_number + 'text-[0.8rem] select-none text-muted-foreground', + defaultClassNames.week_number, ), day: cn( - "relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none", + 'relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none', props.showWeekNumber - ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)" - : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)", - defaultClassNames.day + ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)' + : '[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)', + defaultClassNames.day, ), range_start: cn( - "rounded-l-(--cell-radius) bg-muted elative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:right-0 z-0 isolate", - defaultClassNames.range_start + 'rounded-l-(--cell-radius) bg-muted elative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:right-0 z-0 isolate', + defaultClassNames.range_start, ), - range_middle: cn("rounded-none", defaultClassNames.range_middle), + range_middle: cn('rounded-none', defaultClassNames.range_middle), range_end: cn( - "rounded-r-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:left-0 z-0 isolate", - defaultClassNames.range_end + 'rounded-r-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:left-0 z-0 isolate', + defaultClassNames.range_end, ), today: cn( - "bg-muted text-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none", - defaultClassNames.today + 'bg-muted text-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none', + defaultClassNames.today, ), outside: cn( - "text-muted-foreground aria-selected:text-muted-foreground", - defaultClassNames.outside + 'text-muted-foreground aria-selected:text-muted-foreground', + defaultClassNames.outside, ), disabled: cn( - "text-muted-foreground opacity-50", - defaultClassNames.disabled + 'text-muted-foreground opacity-50', + defaultClassNames.disabled, ), - hidden: cn("invisible", defaultClassNames.hidden), + hidden: cn('invisible', defaultClassNames.hidden), ...classNames, }} components={{ @@ -139,24 +142,27 @@ function Calendar({ className={cn(className)} {...props} /> - ) + ); }, Chevron: ({ className, orientation, ...props }) => { - if (orientation === "left") { + if (orientation === 'left') { return ( - - ) + + ); } - if (orientation === "right") { + if (orientation === 'right') { return ( - - ) + + ); } return ( - - ) + + ); }, DayButton: CalendarDayButton, WeekNumber: ({ children, ...props }) => { @@ -166,13 +172,13 @@ function Calendar({ {children}
- ) + ); }, ...components, }} {...props} /> - ) + ); } function CalendarDayButton({ @@ -181,12 +187,12 @@ function CalendarDayButton({ modifiers, ...props }: React.ComponentProps) { - const defaultClassNames = getDefaultClassNames() + const defaultClassNames = getDefaultClassNames(); - const ref = React.useRef(null) + const ref = React.useRef(null); React.useEffect(() => { - if (modifiers.focused) ref.current?.focus() - }, [modifiers.focused]) + if (modifiers['focused']) ref.current?.focus(); + }, [modifiers]); return ( - ) + ); } function CarouselNext({ className, - variant = "outline", - size = "icon-sm", + variant = 'outline', + size = 'icon-sm', ...props }: React.ComponentProps) { - const { orientation, scrollNext, canScrollNext } = useCarousel() + const { orientation, scrollNext, canScrollNext } = useCarousel(); return ( - ) + ); } export { @@ -241,4 +239,4 @@ export { CarouselPrevious, CarouselNext, useCarousel, -} +}; diff --git a/packages/ui/primitives/chart.tsx b/packages/ui/primitives/chart.tsx index 52fc345..b33e3d9 100644 --- a/packages/ui/primitives/chart.tsx +++ b/packages/ui/primitives/chart.tsx @@ -1,37 +1,48 @@ -"use client" +'use client'; -import * as React from "react" -import * as RechartsPrimitive from "recharts" +import * as React from 'react'; -import { cn } from "@formbase/ui/utils/cn" +import * as RechartsPrimitive from 'recharts'; -// Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: "", dark: ".dark" } as const +import { cn } from '@formbase/ui/utils/cn'; -export type ChartConfig = { - [k in string]: { - label?: React.ReactNode - icon?: React.ComponentType +// format: { THEME_NAME: CSS_SELECTOR } +const THEMES = { light: '', dark: '.dark' } as const; + +const getStringProperty = (value: unknown, key: string) => { + if (typeof value !== 'object' || value === null || !(key in value)) { + return undefined; + } + + const property = (value as Record)[key]; + return typeof property === 'string' ? property : undefined; +}; + +export type ChartConfig = Record< + string, + { + label?: React.ReactNode; + icon?: React.ComponentType; } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -} +>; type ChartContextProps = { - config: ChartConfig -} + config: ChartConfig; +}; -const ChartContext = React.createContext(null) +const ChartContext = React.createContext(null); function useChart() { - const context = React.useContext(ChartContext) + const context = React.useContext(ChartContext); if (!context) { - throw new Error("useChart must be used within a ") + throw new Error('useChart must be used within a '); } - return context + return context; } function ChartContainer({ @@ -40,14 +51,14 @@ function ChartContainer({ children, config, ...props -}: React.ComponentProps<"div"> & { - config: ChartConfig +}: React.ComponentProps<'div'> & { + config: ChartConfig; children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer - >["children"] + >['children']; }) { - const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const uniqueId = React.useId(); + const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}`; return ( @@ -56,7 +67,7 @@ function ChartContainer({ data-chart={chartId} className={cn( "[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden", - className + className, )} {...props} > @@ -66,16 +77,16 @@ function ChartContainer({
- ) + ); } const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color - ) + ([, config]) => config.theme ?? config.color, + ); if (!colorConfig.length) { - return null + return null; } return ( @@ -88,27 +99,27 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || - itemConfig.color - return color ? ` --color-${key}: ${color};` : null + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? + itemConfig.color; + return color ? ` --color-${key}: ${color};` : null; }) - .join("\n")} + .join('\n')} } -` +`, ) - .join("\n"), + .join('\n'), }} /> - ) -} + ); +}; -const ChartTooltip = RechartsPrimitive.Tooltip +const ChartTooltip = RechartsPrimitive.Tooltip; function ChartTooltipContent({ active, payload, className, - indicator = "dot", + indicator = 'dot', hideLabel = false, hideIndicator = false, label, @@ -119,41 +130,41 @@ function ChartTooltipContent({ nameKey, labelKey, }: React.ComponentProps & - React.ComponentProps<"div"> & { - hideLabel?: boolean - hideIndicator?: boolean - indicator?: "line" | "dot" | "dashed" - nameKey?: string - labelKey?: string + React.ComponentProps<'div'> & { + hideLabel?: boolean; + hideIndicator?: boolean; + indicator?: 'line' | 'dot' | 'dashed'; + nameKey?: string; + labelKey?: string; }) { - const { config } = useChart() + const { config } = useChart(); const tooltipLabel = React.useMemo(() => { if (hideLabel || !payload?.length) { - return null + return null; } - const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) + const [item] = payload; + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? 'value'}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); const value = - !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label - : itemConfig?.label + !labelKey && typeof label === 'string' + ? (config[label]?.label ?? label) + : itemConfig?.label; if (labelFormatter) { return ( -
+
{labelFormatter(value, payload)}
- ) + ); } if (!value) { - return null + return null; } - return
{value}
+ return
{value}
; }, [ label, labelFormatter, @@ -162,40 +173,42 @@ function ChartTooltipContent({ labelClassName, config, labelKey, - ]) + ]); if (!active || !payload?.length) { - return null + return null; } - const nestLabel = payload.length === 1 && indicator !== "dot" + const nestLabel = payload.length === 1 && indicator !== 'dot'; return (
{!nestLabel ? tooltipLabel : null}
{payload - .filter((item) => item.type !== "none") + .filter((item) => item.type !== 'none') .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const key = `${nameKey ?? item.name ?? item.dataKey ?? 'value'}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); + const itemPayload: unknown = item.payload; + const indicatorColor = + color ?? getStringProperty(itemPayload, 'fill') ?? item.color; return (
svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5", - indicator === "dot" && "items-center" + '[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5', + indicator === 'dot' && 'items-center', )} > - {formatter && item?.value !== undefined && item.name ? ( - formatter(item.value, item.name, item, index, item.payload) + {formatter && item.value !== undefined && item.name ? ( + formatter(item.value, item.name, item, index, payload) ) : ( <> {itemConfig?.icon ? ( @@ -204,19 +217,19 @@ function ChartTooltipContent({ !hideIndicator && (
@@ -224,14 +237,14 @@ function ChartTooltipContent({ )}
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
{item.value && ( @@ -243,51 +256,51 @@ function ChartTooltipContent({ )}
- ) + ); })}
- ) + ); } -const ChartLegend = RechartsPrimitive.Legend +const ChartLegend = RechartsPrimitive.Legend; function ChartLegendContent({ className, hideIcon = false, payload, - verticalAlign = "bottom", + verticalAlign = 'bottom', nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string +}: React.ComponentProps<'div'> & + Pick & { + hideIcon?: boolean; + nameKey?: string; }) { - const { config } = useChart() + const { config } = useChart(); if (!payload?.length) { - return null + return null; } return (
{payload - .filter((item) => item.type !== "none") + .filter((item) => item.type !== 'none') .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) + const key = `${nameKey ?? item.dataKey ?? 'value'}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); return (
svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3" + '[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3', )} > {itemConfig?.icon && !hideIcon ? ( @@ -302,48 +315,42 @@ function ChartLegendContent({ )} {itemConfig?.label}
- ) + ); })}
- ) + ); } function getPayloadConfigFromPayload( config: ChartConfig, payload: unknown, - key: string + key: string, ) { - if (typeof payload !== "object" || payload === null) { - return undefined + if (typeof payload !== 'object' || payload === null) { + return undefined; } + const payloadRecord = payload as Record; const payloadPayload = - "payload" in payload && - typeof payload.payload === "object" && - payload.payload !== null - ? payload.payload - : undefined + 'payload' in payloadRecord && + typeof payloadRecord['payload'] === 'object' && + payloadRecord['payload'] !== null + ? (payloadRecord['payload'] as Record) + : undefined; - let configLabelKey: string = key + let configLabelKey: string = key; - if ( - key in payload && - typeof payload[key as keyof typeof payload] === "string" - ) { - configLabelKey = payload[key as keyof typeof payload] as string + if (key in payloadRecord && typeof payloadRecord[key] === 'string') { + configLabelKey = payloadRecord[key]; } else if ( payloadPayload && key in payloadPayload && - typeof payloadPayload[key as keyof typeof payloadPayload] === "string" + typeof payloadPayload[key] === 'string' ) { - configLabelKey = payloadPayload[ - key as keyof typeof payloadPayload - ] as string + configLabelKey = payloadPayload[key]; } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key]; } export { @@ -353,4 +360,4 @@ export { ChartLegend, ChartLegendContent, ChartStyle, -} +}; diff --git a/packages/ui/primitives/field.tsx b/packages/ui/primitives/field.tsx index 016059f..6eaf6ed 100644 --- a/packages/ui/primitives/field.tsx +++ b/packages/ui/primitives/field.tsx @@ -1,71 +1,82 @@ -"use client" +'use client'; -import { useMemo } from "react" -import { cva, type VariantProps } from "class-variance-authority" +import { useMemo } from 'react'; -import { cn } from "@formbase/ui/utils/cn" -import { Label } from "@formbase/ui/primitives/label" -import { Separator } from "@formbase/ui/primitives/separator" +import type { VariantProps } from 'class-variance-authority'; -function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { +import { cva } from 'class-variance-authority'; + +import { Label } from '@formbase/ui/primitives/label'; +import { Separator } from '@formbase/ui/primitives/separator'; +import { cn } from '@formbase/ui/utils/cn'; + +function FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) { return (
[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col", className)} + className={cn( + 'gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col', + className, + )} {...props} /> - ) + ); } function FieldLegend({ className, - variant = "legend", + variant = 'legend', ...props -}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { +}: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) { return ( - ) + ); } -function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { +function FieldGroup({ className, ...props }: React.ComponentProps<'div'>) { return (
- ) + ); } -const fieldVariants = cva("data-[invalid=true]:text-destructive gap-2 group/field flex w-full", { - variants: { - orientation: { - vertical: - "flex-col *:w-full [&>.sr-only]:w-auto", - horizontal: - "flex-row items-center *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:items-start [&>[role=checkbox],[role=radio]]:has-[>[data-slot=field-content]]:mt-px", - responsive: - "flex-col *:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:*:data-[slot=field-label]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:[&>[role=checkbox],[role=radio]]:has-[>[data-slot=field-content]]:mt-px", +const fieldVariants = cva( + 'data-[invalid=true]:text-destructive gap-2 group/field flex w-full', + { + variants: { + orientation: { + vertical: 'flex-col *:w-full [&>.sr-only]:w-auto', + horizontal: + 'flex-row items-center *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:items-start [&>[role=checkbox],[role=radio]]:has-[>[data-slot=field-content]]:mt-px', + responsive: + 'flex-col *:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:*:data-[slot=field-label]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:[&>[role=checkbox],[role=radio]]:has-[>[data-slot=field-content]]:mt-px', + }, + }, + defaultVariants: { + orientation: 'vertical', }, }, - defaultVariants: { - orientation: "vertical", - }, -}) +); function Field({ className, - orientation = "vertical", + orientation = 'vertical', ...props -}: React.ComponentProps<"div"> & VariantProps) { +}: React.ComponentProps<'div'> & VariantProps) { return (
- ) + ); } -function FieldContent({ className, ...props }: React.ComponentProps<"div">) { +function FieldContent({ className, ...props }: React.ComponentProps<'div'>) { return (
- ) + ); } function FieldLabel({ @@ -98,55 +109,58 @@ function FieldLabel({