diff --git a/apps/app/languine.lock b/apps/app/languine.lock index 1836fd9e89..d57d3a00fd 100644 --- a/apps/app/languine.lock +++ b/apps/app/languine.lock @@ -90,6 +90,34 @@ files: common.comments.placeholder: dc11131e02964ba21e7418a386add056 common.comments.empty.title: f3a648d591b6c76efb96f7a77071d23c common.comments.empty.description: 0a0df874a9a6b1f3b710b48f10bcd494 + common.upload.fileUpload.uploadingText: f2870421907fa4e9e9c6fbe349234ecf + common.upload.fileUpload.uploadingFile: 5d8792ec4500487cd04d588e4dabd830 + common.upload.fileUpload.dropFileHere: 8ea866b321e27837bd677bd711f20020 + common.upload.fileUpload.dropFileHereAlt: 8ea866b321e27837bd677bd711f20020 + common.upload.fileUpload.releaseToUpload: 71611d0ba234b4775232cd78dd6ba086 + common.upload.fileUpload.addFiles: 5f4514405d9574e7b2b4c6c16573c5ca + common.upload.fileUpload.uploadAdditionalEvidence: 46b0e2e3da5518086b9a39ecea20507a + common.upload.fileUpload.dragDropOrClick: 91ccb262f46331f20a9a3e44f0392703 + common.upload.fileUpload.dragDropOrClickToSelect: 9ffee77fccb7b4804451d4a20f078240 + common.upload.fileUpload.maxFileSize: 54f591179ba34ce8d3eb9d941a56878a + common.upload.fileUrl.additionalLinks: 93823085d6dc9b7eba33ee74ca7ff786 + common.upload.fileUrl.add: ec211f7c20af43e742bf2570c3cb84f9 + common.upload.fileUrl.linksAdded: de53b2e4348255782648fe8c449c4db6 + common.upload.fileUrl.enterUrl: e1f70f4a4265cb51c1b219aa60eaa441 + common.upload.fileUrl.addAnotherLink: d53fe8cfe74a5ec2e99bf0dca0e5327f + common.upload.fileUrl.saveLinks: d7fa2bfcc59f0361b9445d7808ac4675 + common.upload.fileUrl.urlBadge: e6b391a8d2c4d45902a23a8b6585703d + common.upload.fileUrl.copyLink: 78fc13f46174a57416493b60e99777c7 + common.upload.fileUrl.openLink: ff161e0db9bfff8b46662512b662b5e3 + common.upload.fileUrl.deleteLink: d008a25cd6325ee1fbd11e43225ece3d + common.upload.fileCard.preview: 31fde7b05ac8952dacf4af8a704074ec + common.upload.fileCard.filePreview: 2f9e2860469a0a7176e029379ffb772b + common.upload.fileCard.previewNotAvailable: e6b101b4b3bfa818b2d1e351e4f08112 + common.upload.fileCard.openFile: 6dbd6898da5ec262f46c9a3ecf1f9fe4 + common.upload.fileCard.deleteFile: 7d1e2483f22443e6aa5e0c3212fc312a + common.upload.fileCard.deleteFileConfirmTitle: 7d1e2483f22443e6aa5e0c3212fc312a + common.upload.fileCard.deleteFileConfirmDescription: cdcf3ab5d2a2177da6d02ccf32bbc76d + common.upload.fileSection.filesUploaded: 3031c6bab57d63c21aad3d1aeffda1a4 common.attachments.title: 7e2708aeb65763c54052f57ed1a1ec1d common.attachments.description: b8f87f50e2e7eb3a7e67cd28395428d1 common.attachments.upload: 18924edc9e6a8120618ae1f429332b16 diff --git a/apps/app/src/actions/soc2-seed.ts b/apps/app/src/actions/soc2-seed.ts deleted file mode 100644 index c884888163..0000000000 --- a/apps/app/src/actions/soc2-seed.ts +++ /dev/null @@ -1,12 +0,0 @@ -// soc2-seed.ts - -"use server"; - -import { type ArtifactType, db } from "@bubba/db"; -import { soc2Categories, soc2Controls } from "../lib/soc2-controls"; - -export const soc2Seed = async ({ - organizationId, -}: { - organizationId: string; -}) => {}; diff --git a/apps/app/src/actions/vendor/create-vendor-action.ts b/apps/app/src/actions/vendor/create-vendor-action.ts deleted file mode 100644 index 24998cbfe2..0000000000 --- a/apps/app/src/actions/vendor/create-vendor-action.ts +++ /dev/null @@ -1,64 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import { db } from "@bubba/db"; -import { revalidatePath } from "next/cache"; -import { z } from "zod"; -import { authActionClient } from "../safe-action"; -import { createVendorSchema } from "../schema"; - -export const createVendorAction = authActionClient - .schema(createVendorSchema) - .metadata({ - name: "create-vendor", - track: { - event: "create-vendor", - channel: "server", - }, - }) - .action(async ({ parsedInput, ctx }) => { - const { name, website, description, category, ownerId, contacts } = - parsedInput; - const { user } = ctx; - - try { - const session = await auth(); - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return { - success: false, - error: "Not authorized", - }; - } - - await db.vendors.create({ - data: { - name, - website, - description, - category, - ownerId, - organizationId, - VendorContact: { - create: contacts.map((contact) => ({ - ...contact, - organizationId, - })), - }, - }, - }); - - revalidatePath("/vendors/register"); - - return { - success: true, - data: null, - }; - } catch (error) { - return { - success: false, - error: "Failed to create vendor", - }; - } - }); diff --git a/apps/app/src/actions/vendor/create-vendor-comment-action.ts b/apps/app/src/actions/vendor/create-vendor-comment-action.ts deleted file mode 100644 index 3f162c481a..0000000000 --- a/apps/app/src/actions/vendor/create-vendor-comment-action.ts +++ /dev/null @@ -1,60 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import { db } from "@bubba/db"; -import { revalidatePath } from "next/cache"; -import { z } from "zod"; -import { authActionClient } from "../safe-action"; - -const schema = z.object({ - vendorId: z.string(), - content: z.string().min(1), -}); - -export const createVendorCommentAction = authActionClient - .schema(schema) - .metadata({ - name: "create-vendor-comment", - track: { - event: "create-vendor-comment", - channel: "server", - }, - }) - .action(async ({ parsedInput, ctx }) => { - const { vendorId, content } = parsedInput; - const { user } = ctx; - - try { - const session = await auth(); - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return { - success: false, - error: "Not authorized", - }; - } - - await db.vendorComment.create({ - data: { - content, - vendorId, - ownerId: user.id, - organizationId, - }, - }); - - revalidatePath("/vendors/register"); - revalidatePath(`/vendors/${vendorId}`); - - return { - success: true, - data: null, - }; - } catch (error) { - return { - success: false, - error: "Failed to create vendor comment", - }; - } - }); diff --git a/apps/app/src/actions/vendor/update-vendor-action.ts b/apps/app/src/actions/vendor/update-vendor-action.ts deleted file mode 100644 index d832fb49c0..0000000000 --- a/apps/app/src/actions/vendor/update-vendor-action.ts +++ /dev/null @@ -1,86 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import { db } from "@bubba/db"; -import { revalidatePath } from "next/cache"; -import { z } from "zod"; -import { authActionClient } from "../safe-action"; -import { updateVendorSchema } from "../schema"; - -export const updateVendorAction = authActionClient - .schema(updateVendorSchema) - .metadata({ - name: "update-vendor", - track: { - event: "update-vendor", - channel: "server", - }, - }) - .action(async ({ parsedInput, ctx }) => { - const { - id, - name, - website, - description, - category, - status, - ownerId, - contacts, - } = parsedInput; - const { user } = ctx; - - try { - const session = await auth(); - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return { - success: false, - error: "Not authorized", - }; - } - - // First delete existing contacts - await db.vendorContact.deleteMany({ - where: { - vendorId: id, - organizationId, - }, - }); - - // Update vendor and create new contacts - await db.vendors.update({ - where: { - id, - organizationId, - }, - data: { - name, - website, - description, - category, - status, - ownerId, - VendorContact: { - create: contacts.map((contact) => ({ - ...contact, - organizationId, - })), - }, - }, - }); - - revalidatePath(`/vendors/${id}`); - revalidatePath("/vendors"); - - return { - success: true, - data: null, - }; - } catch (error) { - return { - success: false, - error: "Failed to update vendor", - }; - } - }); diff --git a/apps/app/src/actions/vendor/update-vendor-risk-action.ts b/apps/app/src/actions/vendor/update-vendor-risk-action.ts deleted file mode 100644 index 40f8b48285..0000000000 --- a/apps/app/src/actions/vendor/update-vendor-risk-action.ts +++ /dev/null @@ -1,63 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import { db } from "@bubba/db"; -import { revalidatePath } from "next/cache"; -import { z } from "zod"; -import { authActionClient } from "../safe-action"; - -const schema = z.object({ - id: z.string(), - inherent_risk: z.enum(["low", "medium", "high", "unknown"]).optional(), - residual_risk: z.enum(["low", "medium", "high", "unknown"]).optional(), -}); - -export const updateVendorRiskAction = authActionClient - .schema(schema) - .metadata({ - name: "update-vendor-risk", - track: { - event: "update-vendor-risk", - channel: "server", - }, - }) - .action(async ({ parsedInput, ctx }) => { - const { id, inherent_risk, residual_risk } = parsedInput; - const { user } = ctx; - - try { - const session = await auth(); - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return { - success: false, - error: "Not authorized", - }; - } - - await db.vendors.update({ - where: { - id, - organizationId, - }, - data: { - inherent_risk, - residual_risk, - }, - }); - - revalidatePath("/vendors/register"); - revalidatePath(`/vendors/${id}`); - - return { - success: true, - data: null, - }; - } catch (error) { - return { - success: false, - error: "Failed to update vendor risk", - }; - } - }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/layout.tsx deleted file mode 100644 index 00a16291e5..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getI18n } from "@/locales/server"; -import { SecondaryMenu } from "@bubba/ui/secondary-menu"; - -export default async function Layout({ - children, -}: { - children: React.ReactNode; -}) { - const t = await getI18n(); - - return ( -
- - -
{children}
-
- ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/page.tsx deleted file mode 100644 index 7d1001ebda..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/(overview)/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { auth } from "@/auth"; -import { VendorsByAssignee } from "@/components/vendors/charts/vendors-by-assignee"; -import { VendorsByCategory } from "@/components/vendors/charts/vendors-by-category"; -import { VendorsByStatus } from "@/components/vendors/charts/vendors-by-status"; -import { redirect } from "next/navigation"; - -export default async function VendorManagement() { - const session = await auth(); - - if (!session?.user?.organizationId) { - redirect("/onboarding"); - } - - return ( -
-
- - -
- -
- -
-
- ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/layout.tsx deleted file mode 100644 index ffcb48d24f..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/layout.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { auth } from "@/auth"; -import { Title } from "@/components/title"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import { SecondaryMenu } from "@bubba/ui/secondary-menu"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface LayoutProps { - children: React.ReactNode; - params: Promise<{ vendorId: string }>; -} - -export default async function Layout({ children, params }: LayoutProps) { - const t = await getI18n(); - const session = await auth(); - - if (!session || !session.user.organizationId) { - redirect("/"); - } - - const vendorId = await params; - const vendor = await getVendor( - vendorId.vendorId, - session.user.organizationId, - ); - - if (!vendor) { - redirect("/vendors"); - } - - return ( -
- - <SecondaryMenu - isChild - items={[ - { path: `/vendors/${vendorId.vendorId}`, label: t("risk.overview") }, - { - path: `/vendors/${vendorId.vendorId}/tasks`, - label: t("risk.tasks.title"), - }, - ]} - /> - - <main className="mt-8">{children}</main> - </div> - ); -} - -const getVendor = unstable_cache( - async (vendorId: string, organizationId: string) => { - const vendor = await db.vendors.findUnique({ - where: { - id: vendorId, - organizationId: organizationId, - }, - }); - - return vendor; - }, - ["vendor-cache"], -); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/page.tsx deleted file mode 100644 index ba1937f632..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[vendorId]/page.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { auth } from "@/auth"; -import { VendorAssessment } from "@/components/vendors/vendor-assessment"; -import { VendorComments } from "@/components/vendors/vendor-comments"; -import { VendorOverview } from "@/components/vendors/vendor-overview"; -import { db } from "@bubba/db"; -import { notFound, redirect } from "next/navigation"; -import { Suspense } from "react"; - -interface PageProps { - params: Promise<{ - vendorId: string; - }>; -} - -export default async function VendorPage({ params }: PageProps) { - const session = await auth(); - const vendorId = (await params).vendorId; - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return redirect("/"); - } - - const vendor = await db.vendors.findUnique({ - where: { - id: vendorId, - organizationId, - }, - include: { - VendorContact: true, - owner: true, - VendorComment: { - include: { - owner: true, - }, - orderBy: { - createdAt: "desc", - }, - }, - }, - }); - - if (!vendor) { - return notFound(); - } - - const users = await db.user.findMany({ - where: { - organizationId, - }, - }); - - return ( - <div className="space-y-6"> - <VendorOverview vendor={vendor} users={users} /> - - <div className="grid grid-cols-1 gap-6 md:grid-cols-2"> - <VendorAssessment vendor={vendor} /> - <VendorComments vendor={vendor} users={users} /> - </div> - </div> - ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/layout.tsx deleted file mode 100644 index 00a16291e5..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getI18n } from "@/locales/server"; -import { SecondaryMenu } from "@bubba/ui/secondary-menu"; - -export default async function Layout({ - children, -}: { - children: React.ReactNode; -}) { - const t = await getI18n(); - - return ( - <div className="max-w-[1200px]"> - <SecondaryMenu - items={[ - { path: "/vendors", label: t("risk.overview") }, - { path: "/vendors/register", label: t("vendor.register_title") }, - ]} - /> - - <main className="mt-8">{children}</main> - </div> - ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/page.tsx deleted file mode 100644 index 9ec9863938..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/page.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import { auth } from "@/auth"; -import { DataTable } from "@/components/tables/vendor-register/data-table"; -import { - NoResults, - NoVendors, -} from "@/components/tables/vendor-register/empty-states"; -import { FilterToolbar } from "@/components/tables/vendor-register/filter-toolbar"; -import { Loading } from "@/components/tables/vendor-register/loading"; -import { getServerColumnHeaders } from "@/components/tables/vendor-register/server-columns"; -import { VendorOverview } from "@/components/vendors/charts/vendor-overview"; -import { type VendorCategory, type VendorStatus, db } from "@bubba/db"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface PageProps { - searchParams: Promise<{ - search?: string; - category?: string; - status?: string; - sort?: string; - page?: string; - per_page?: string; - }>; -} - -export default async function VendorRegisterPage({ searchParams }: PageProps) { - const session = await auth(); - const organizationId = session?.user.organizationId; - const columnHeaders = await getServerColumnHeaders(); - - if (!organizationId) { - return redirect("/"); - } - - const { - search, - status, - category, - sort, - page = "1", - per_page = "10", - } = await searchParams; - - const [column, order] = sort?.split(":") ?? []; - - const hasFilters = !!(search || status || category); - - const { vendors: loadedVendors, total } = await getVendors({ - organizationId, - search, - status: status as VendorStatus, - category: category as VendorCategory, - column, - order, - page: Number.parseInt(page), - per_page: Number.parseInt(per_page), - }); - - const users = await db.user.findMany({ - where: { - organizationId, - Vendors: { - some: {}, - }, - }, - select: { - id: true, - name: true, - }, - }); - - if (loadedVendors.length === 0 && !hasFilters) { - return ( - <div className="relative overflow-hidden"> - <FilterToolbar isEmpty={true} users={users} /> - <NoVendors /> - <Loading isEmpty={true} /> - </div> - ); - } - - return ( - <div className="relative space-y-6"> - <FilterToolbar isEmpty={loadedVendors.length === 0} users={users} /> - {loadedVendors.length > 0 ? ( - <DataTable - columnHeaders={columnHeaders} - data={loadedVendors} - pageCount={Math.ceil(total / Number.parseInt(per_page))} - currentPage={Number.parseInt(page)} - /> - ) : ( - <NoResults hasFilters={hasFilters} /> - )} - </div> - ); -} - -const getVendors = unstable_cache( - async function vendors({ - organizationId, - search, - status, - category, - column, - order, - page = 1, - per_page = 10, - }: { - organizationId: string; - search?: string; - status?: VendorStatus; - category?: VendorCategory; - column?: string; - order?: string; - page?: number; - per_page?: number; - }) { - const skip = (page - 1) * per_page; - - const [vendors, total] = await Promise.all([ - db.vendors.findMany({ - where: { - organizationId, - AND: [ - search - ? { - OR: [ - { name: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - } - : {}, - status ? { status } : {}, - category ? { category } : {}, - ], - }, - orderBy: column - ? { - [column]: order === "asc" ? "asc" : "desc", - } - : undefined, - skip, - take: per_page, - include: { - owner: { - select: { - name: true, - image: true, - }, - }, - }, - }), - db.vendors.count({ - where: { - organizationId, - AND: [ - search - ? { - OR: [ - { name: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - } - : {}, - status ? { status } : {}, - category ? { category } : {}, - ], - }, - }), - ]); - - return { vendors, total }; - }, - ["vendors-cache"], -); diff --git a/apps/app/src/app/api/auth/[...nextauth]/route.ts b/apps/app/src/app/api/auth/[...nextauth]/route.ts index b9f925f530..86c9f3daa6 100644 --- a/apps/app/src/app/api/auth/[...nextauth]/route.ts +++ b/apps/app/src/app/api/auth/[...nextauth]/route.ts @@ -1,4 +1,3 @@ import { handlers } from "@/auth"; -export const runtime = "nodejs"; export const { GET, POST } = handlers; diff --git a/apps/app/src/auth/config.ts b/apps/app/src/auth/config.ts index a3210f22b8..39972711c8 100644 --- a/apps/app/src/auth/config.ts +++ b/apps/app/src/auth/config.ts @@ -6,79 +6,77 @@ import GoogleProvider from "next-auth/providers/google"; import Resend from "next-auth/providers/resend"; import { createOrganizationAndConnectUser } from "./org"; -export const runtime = "nodejs"; - declare module "next-auth" { - interface User { - organizationId?: string; - onboarded?: boolean; - full_name?: string; - avatar_url?: string; - } + interface User { + organizationId?: string; + onboarded?: boolean; + full_name?: string; + avatar_url?: string; + } - interface Session extends DefaultSession { - user: { - id: string; - organizationId?: string; - onboarded?: boolean; - full_name?: string; - avatar_url?: string; - } & DefaultSession["user"]; - } + interface Session extends DefaultSession { + user: { + id: string; + organizationId?: string; + onboarded?: boolean; + full_name?: string; + avatar_url?: string; + } & DefaultSession["user"]; + } } export const authConfig: NextAuthConfig = { - providers: [ - GoogleProvider({ - clientId: process.env.AUTH_GOOGLE_ID!, - clientSecret: process.env.AUTH_GOOGLE_SECRET!, - allowDangerousEmailAccountLinking: true, - }), - Resend({ - apiKey: process.env.RESEND_API_KEY!, - from: "noreply@mail.trycomp.ai", - async sendVerificationRequest(params) { - await sendMagicLinkEmail({ - email: params.identifier, - url: params.url, - }); - }, - }), - ], - adapter: PrismaAdapter(db), - callbacks: { - session: ({ session, user }) => ({ - ...session, - user: { - ...session.user, - id: user.id, - organizationId: user.organizationId, - onboarded: user.onboarded, - }, - }), - }, - events: { - signIn: async ({ user, isNewUser }) => { - if (user?.id) { - await db.user.update({ - where: { - id: user.id, - }, - data: { - lastLogin: new Date(), - organizationId: user.organizationId, - }, - }); - } + providers: [ + GoogleProvider({ + clientId: process.env.AUTH_GOOGLE_ID!, + clientSecret: process.env.AUTH_GOOGLE_SECRET!, + allowDangerousEmailAccountLinking: true, + }), + Resend({ + apiKey: process.env.RESEND_API_KEY!, + from: "noreply@mail.trycomp.ai", + async sendVerificationRequest(params) { + await sendMagicLinkEmail({ + email: params.identifier, + url: params.url, + }); + }, + }), + ], + adapter: PrismaAdapter(db), + callbacks: { + session: ({ session, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id, + organizationId: user.organizationId, + onboarded: user.onboarded, + }, + }), + }, + events: { + signIn: async ({ user, isNewUser }) => { + if (user?.id) { + await db.user.update({ + where: { + id: user.id, + }, + data: { + lastLogin: new Date(), + organizationId: user.organizationId, + }, + }); + } - if (isNewUser && user.email && user.id) { - if (!user.organizationId) { - await createOrganizationAndConnectUser({ - userId: user.id, - normalizedEmail: user.email, - }); - } - } - }, - }, + if (isNewUser && user.email && user.id) { + if (!user.organizationId) { + await createOrganizationAndConnectUser({ + userId: user.id, + normalizedEmail: user.email, + }); + } + } + }, + }, } satisfies NextAuthConfig; diff --git a/apps/app/src/auth/index.ts b/apps/app/src/auth/index.ts index b93abe65f8..76c146d34a 100644 --- a/apps/app/src/auth/index.ts +++ b/apps/app/src/auth/index.ts @@ -1,8 +1,7 @@ import NextAuth from "next-auth"; import { cache } from "react"; -import { authConfig } from "./config"; -export const runtime = "nodejs"; +import { authConfig } from "./config"; const { auth: uncachedAuth, handlers, signIn, signOut } = NextAuth(authConfig); diff --git a/apps/app/src/auth/org.ts b/apps/app/src/auth/org.ts index c79c244ad0..0e08985d4e 100644 --- a/apps/app/src/auth/org.ts +++ b/apps/app/src/auth/org.ts @@ -1,82 +1,80 @@ import { db } from "@bubba/db"; import { stripe } from "./stripe"; -export const runtime = "nodejs"; - async function createStripeCustomer(input: { - name: string; - email: string; - organizationId: string; + name: string; + email: string; + organizationId: string; }): Promise<string> { - try { - const customer = await stripe.customers.create({ - name: input.name, - email: input.email, - metadata: { - organizationId: input.organizationId, - }, - }); + try { + const customer = await stripe.customers.create({ + name: input.name, + email: input.email, + metadata: { + organizationId: input.organizationId, + }, + }); - return customer.id; - } catch (error) { - console.error("Error creating Stripe customer", error); - throw error; - } + return customer.id; + } catch (error) { + console.error("Error creating Stripe customer", error); + throw error; + } } export async function createOrganizationAndConnectUser(input: { - userId: string; - normalizedEmail: string; - subdomain?: string; + userId: string; + normalizedEmail: string; + subdomain?: string; }): Promise<string> { - const initialName = "New Organization"; + const initialName = "New Organization"; - const [organization] = await db.$transaction([ - db.organization.create({ - data: { - name: initialName, - tier: "free", - website: "", - subdomain: input.subdomain || "", - members: { - create: { - userId: input.userId, - role: "admin", - }, - }, - }, - select: { - id: true, - }, - }), - db.user.update({ - where: { id: input.userId }, - data: { role: "admin" }, - select: { - id: true, - }, - }), - ]); + const [organization] = await db.$transaction([ + db.organization.create({ + data: { + name: initialName, + tier: "free", + website: "", + subdomain: input.subdomain || "", + members: { + create: { + userId: input.userId, + role: "admin", + }, + }, + }, + select: { + id: true, + }, + }), + db.user.update({ + where: { id: input.userId }, + data: { role: "admin" }, + select: { + id: true, + }, + }), + ]); - const stripeCustomerId = await createStripeCustomer({ - name: initialName, - email: input.normalizedEmail, - organizationId: organization.id, - }); + const stripeCustomerId = await createStripeCustomer({ + name: initialName, + email: input.normalizedEmail, + organizationId: organization.id, + }); - if (!stripeCustomerId) { - console.warn("Stripe customer ID is missing"); - } + if (!stripeCustomerId) { + console.warn("Stripe customer ID is missing"); + } - await db.organization.update({ - where: { id: organization.id }, - data: { stripeCustomerId }, - }); + await db.organization.update({ + where: { id: organization.id }, + data: { stripeCustomerId }, + }); - await db.user.update({ - where: { id: input.userId }, - data: { organizationId: organization.id }, - }); + await db.user.update({ + where: { id: input.userId }, + data: { organizationId: organization.id }, + }); - return organization.id; + return organization.id; } diff --git a/apps/app/src/auth/stripe.ts b/apps/app/src/auth/stripe.ts index 92a58f9984..0613041041 100644 --- a/apps/app/src/auth/stripe.ts +++ b/apps/app/src/auth/stripe.ts @@ -1,17 +1,15 @@ import Stripe from "stripe"; -export const runtime = "nodejs"; - if (!process.env.STRIPE_SECRET_KEY) { - throw new Error("STRIPE_SECRET_KEY is not set"); + throw new Error("STRIPE_SECRET_KEY is not set"); } if (!process.env.STRIPE_WEBHOOK_SECRET) { - throw new Error("STRIPE_WEBHOOK_SECRET is not set"); + throw new Error("STRIPE_WEBHOOK_SECRET is not set"); } export const stripeWebhookSecret = process.env.STRIPE_WEBHOOK_SECRET; export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { - apiVersion: "2025-01-27.acacia", + apiVersion: "2025-02-24.acacia", }); diff --git a/apps/app/src/components/forms/vendors/create-vendor-comment-form.tsx b/apps/app/src/components/forms/vendors/create-vendor-comment-form.tsx deleted file mode 100644 index fd6196bbf1..0000000000 --- a/apps/app/src/components/forms/vendors/create-vendor-comment-form.tsx +++ /dev/null @@ -1,113 +0,0 @@ -"use client"; - -import { createVendorCommentSchema } from "@/actions/schema"; -import { createVendorCommentAction } from "@/actions/vendor/create-vendor-comment-action"; -import { useI18n } from "@/locales/client"; -import type { Vendors } from "@bubba/db"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@bubba/ui/accordion"; -import { Button } from "@bubba/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormMessage, -} from "@bubba/ui/form"; -import { Textarea } from "@bubba/ui/textarea"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { ArrowRightIcon } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useQueryState } from "nuqs"; -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; - -interface CreateVendorCommentFormProps { - vendor: Vendors; -} - -export function CreateVendorCommentForm({ - vendor, -}: CreateVendorCommentFormProps) { - const t = useI18n(); - const [_, setCreateVendorCommentSheet] = useQueryState( - "vendor-comment-sheet", - ); - - const createVendorComment = useAction(createVendorCommentAction, { - onSuccess: () => { - toast.success(t("common.comments.success")); - setCreateVendorCommentSheet(null); - }, - onError: () => { - toast.error(t("common.comments.error")); - }, - }); - - const form = useForm<z.infer<typeof createVendorCommentSchema>>({ - resolver: zodResolver(createVendorCommentSchema), - defaultValues: { - content: "", - vendorId: vendor.id, - }, - }); - - const onSubmit = (data: z.infer<typeof createVendorCommentSchema>) => { - createVendorComment.execute(data); - }; - - return ( - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)}> - <div className="h-[calc(100vh-250px)] scrollbar-hide overflow-auto"> - <div> - <Accordion type="multiple" defaultValue={["comment"]}> - <AccordionItem value="comment"> - <AccordionTrigger>{t("common.comments.new")}</AccordionTrigger> - <AccordionContent> - <div className="space-y-4"> - <FormField - control={form.control} - name="content" - render={({ field }) => ( - <FormItem> - <FormControl> - <Textarea - {...field} - autoFocus - className="mt-3" - placeholder={t("common.comments.placeholder")} - autoCorrect="off" - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - </AccordionContent> - </AccordionItem> - </Accordion> - </div> - - <div className="flex justify-end mt-4"> - <Button - type="submit" - disabled={createVendorComment.status === "executing"} - > - <div className="flex items-center justify-center"> - {t("common.comments.save")} - <ArrowRightIcon className="ml-2 h-4 w-4" /> - </div> - </Button> - </div> - </div> - </form> - </Form> - ); -} diff --git a/apps/app/src/components/forms/vendors/create-vendor-form.tsx b/apps/app/src/components/forms/vendors/create-vendor-form.tsx deleted file mode 100644 index de691316ce..0000000000 --- a/apps/app/src/components/forms/vendors/create-vendor-form.tsx +++ /dev/null @@ -1,349 +0,0 @@ -"use client"; - -import { getOrganizationUsersAction } from "@/actions/organization/get-organization-users-action"; -import { createVendorSchema } from "@/actions/schema"; -import { createVendorAction } from "@/actions/vendor/create-vendor-action"; -import { SelectUser } from "@/components/select-user"; -import { useI18n } from "@/locales/client"; -import { VendorCategory } from "@bubba/db"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@bubba/ui/accordion"; -import { Button } from "@bubba/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@bubba/ui/form"; -import { Input } from "@bubba/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@bubba/ui/select"; -import { Textarea } from "@bubba/ui/textarea"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { ArrowRightIcon, PlusCircle, Trash2, XCircle } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useQueryState } from "nuqs"; -import { useEffect, useState } from "react"; -import { useFieldArray, useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; - -interface User { - id: string; - image?: string | null; - name: string | null; -} - -export function CreateVendor() { - const t = useI18n(); - const [users, setUsers] = useState<User[]>([]); - const [isLoadingUsers, setIsLoadingUsers] = useState(true); - const [_, setCreateVendorSheet] = useQueryState("create-vendor-sheet"); - - useEffect(() => { - async function loadUsers() { - const result = await getOrganizationUsersAction(); - if (result?.data?.success && result?.data?.data) { - setUsers(result.data.data); - } - setIsLoadingUsers(false); - } - - loadUsers(); - }, []); - - const createVendor = useAction(createVendorAction, { - onSuccess: () => { - toast.success(t("risk.vendor.form.create_vendor_success")); - setCreateVendorSheet(null); - }, - onError: () => { - toast.error(t("risk.vendor.form.create_vendor_error")); - }, - }); - - const form = useForm<z.infer<typeof createVendorSchema>>({ - resolver: zodResolver(createVendorSchema), - defaultValues: { - name: "", - website: "", - description: "", - category: VendorCategory.cloud, - contacts: [], - }, - mode: "onChange", - }); - - const { fields, append, remove } = useFieldArray({ - control: form.control, - name: "contacts", - }); - - const onSubmit = (data: z.infer<typeof createVendorSchema>) => { - createVendor.execute(data); - }; - - return ( - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)}> - <div className="h-[calc(100vh-250px)] scrollbar-hide overflow-auto"> - <div> - <Accordion type="multiple" defaultValue={["vendor"]}> - <AccordionItem value="vendor"> - <AccordionTrigger> - {t("risk.vendor.form.vendor_details")} - </AccordionTrigger> - <AccordionContent> - <div className="space-y-4"> - <FormField - control={form.control} - name="name" - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("risk.vendor.form.vendor_name")} - </FormLabel> - <FormControl> - <Input - {...field} - autoFocus - className="mt-3" - placeholder={t( - "risk.vendor.form.vendor_name_placeholder", - )} - autoCorrect="off" - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="website" - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("risk.vendor.form.vendor_website")} - </FormLabel> - <FormControl> - <Input - {...field} - className="mt-3" - placeholder={t( - "risk.vendor.form.vendor_website_placeholder", - )} - autoCorrect="off" - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="description" - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("risk.vendor.form.vendor_description")} - </FormLabel> - <FormControl> - <Textarea - {...field} - className="mt-3 min-h-[80px]" - placeholder={t( - "risk.vendor.form.vendor_description_placeholder", - )} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="category" - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.vendor_category")} - </FormLabel> - <FormControl> - <Select - onValueChange={field.onChange} - defaultValue={field.value} - > - <SelectTrigger> - <SelectValue - placeholder={t( - "vendor.form.vendor_category_placeholder", - )} - /> - </SelectTrigger> - <SelectContent> - {Object.values(VendorCategory).map( - (category) => ( - <SelectItem key={category} value={category}> - {t(`vendor.category.${category}`)} - </SelectItem> - ), - )} - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="ownerId" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("common.assignee.label")}</FormLabel> - <FormControl> - <Select - value={field.value || undefined} - onValueChange={field.onChange} - > - <SelectTrigger> - <SelectValue - placeholder={t("common.assignee.placeholder")} - /> - </SelectTrigger> - <SelectContent> - <SelectUser - users={users} - isLoading={isLoadingUsers} - onSelect={field.onChange} - selectedId={field.value || undefined} - /> - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - </AccordionContent> - </AccordionItem> - <AccordionItem value="contacts"> - <AccordionTrigger>{t("vendor.form.contacts")}</AccordionTrigger> - <AccordionContent> - <FormField - control={form.control} - name="contacts" - render={() => ( - <FormItem> - <div className="space-y-4"> - {fields.map((field, index) => ( - <div key={field.id} className="space-y-4"> - <FormField - control={form.control} - name={`contacts.${index}.name`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_name")} - </FormLabel> - <FormControl> - <Input {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name={`contacts.${index}.email`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_email")} - </FormLabel> - <FormControl> - <Input {...field} type="email" /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name={`contacts.${index}.role`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_role")} - </FormLabel> - <FormControl> - <Input {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - <div className="flex justify-end"> - <Button - type="button" - variant="destructive" - onClick={() => remove(index)} - className="mt-4 items-center justify-end gap-2" - > - <XCircle className="h-4 w-4" /> - {t("common.actions.delete")} - </Button> - </div> - </div> - ))} - - <Button - type="button" - variant="outline" - onClick={() => - append({ name: "", email: "", role: "" }) - } - > - <PlusCircle className="h-4 w-4 mr-2" /> - {t("vendor.form.add_contact")} - </Button> - </div> - <FormMessage /> - </FormItem> - )} - /> - </AccordionContent> - </AccordionItem> - </Accordion> - </div> - - <div className="flex justify-end mt-4"> - <Button - type="submit" - disabled={createVendor.status === "executing"} - > - <div className="flex items-center justify-center"> - {t("common.actions.create")} - <ArrowRightIcon className="ml-2 h-4 w-4" /> - </div> - </Button> - </div> - </div> - </form> - </Form> - ); -} diff --git a/apps/app/src/components/forms/vendors/update-vendor-form.tsx b/apps/app/src/components/forms/vendors/update-vendor-form.tsx deleted file mode 100644 index 6dd94d511f..0000000000 --- a/apps/app/src/components/forms/vendors/update-vendor-form.tsx +++ /dev/null @@ -1,303 +0,0 @@ -"use client"; - -import { updateVendorSchema } from "@/actions/schema"; -import { updateVendorAction } from "@/actions/vendor/update-vendor-action"; -import { SelectUser } from "@/components/select-user"; -import { - VendorStatus as Status, - type VendorStatusType, -} from "@/components/vendor-status"; -import { useI18n } from "@/locales/client"; -import { - type User, - VendorCategory, - type VendorContact, - VendorStatus, - type Vendors, -} from "@bubba/db"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@bubba/ui/accordion"; -import { Button } from "@bubba/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@bubba/ui/form"; -import { Input } from "@bubba/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@bubba/ui/select"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Loader2, PlusCircle, XCircle } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useFieldArray, useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; - -interface UpdateVendorFormProps { - vendor: Vendors & { VendorContact: VendorContact[] }; - users: User[]; -} - -export function UpdateVendorForm({ vendor, users }: UpdateVendorFormProps) { - const t = useI18n(); - - const updateVendor = useAction(updateVendorAction, { - onSuccess: () => { - toast.success(t("risk.vendor.form.update_vendor_success")); - }, - onError: () => { - toast.error(t("risk.vendor.form.update_vendor_error")); - }, - }); - - const form = useForm<z.infer<typeof updateVendorSchema>>({ - resolver: zodResolver(updateVendorSchema), - defaultValues: { - id: vendor.id, - name: vendor.name, - website: vendor.website, - description: vendor.description, - category: vendor.category, - ownerId: vendor.ownerId ?? undefined, - status: vendor.status, - contacts: vendor.VendorContact.map((contact) => ({ - name: contact.name, - email: contact.email, - role: contact.role, - })), - }, - mode: "onChange", - }); - - const { fields, append, remove } = useFieldArray({ - control: form.control, - name: "contacts", - }); - - const handleRemoveContact = (index: number) => { - if (fields.length === 1) { - toast.error(t("vendor.form.min_one_contact_required")); - return; - } - remove(index); - }; - - const onSubmit = (data: z.infer<typeof updateVendorSchema>) => { - updateVendor.execute(data); - }; - - return ( - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)}> - <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> - <FormField - control={form.control} - name="ownerId" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("common.assignee.label")}</FormLabel> - <FormControl> - <Select - value={field.value || undefined} - onValueChange={field.onChange} - onOpenChange={() => form.handleSubmit(onSubmit)} - > - <SelectTrigger> - <SelectValue - placeholder={t("common.assignee.placeholder")} - /> - </SelectTrigger> - <SelectContent> - <SelectUser - isLoading={false} - onSelect={field.onChange} - selectedId={field.value || undefined} - users={users} - /> - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="status" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("risk.vendor.form.vendor_status")}</FormLabel> - <FormControl> - <Select - onValueChange={field.onChange} - defaultValue={field.value} - > - <SelectTrigger> - <SelectValue - placeholder={t( - "risk.vendor.form.vendor_status_placeholder", - )} - > - <Status status={field.value as VendorStatusType} /> - </SelectValue> - </SelectTrigger> - <SelectContent> - {Object.values(VendorStatus).map((status) => ( - <SelectItem key={status} value={status}> - <Status status={status as VendorStatusType} /> - </SelectItem> - ))} - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="category" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("risk.vendor.form.vendor_category")}</FormLabel> - <FormControl> - <Select - onValueChange={field.onChange} - defaultValue={field.value} - > - <SelectTrigger> - <SelectValue - placeholder={t( - "risk.vendor.form.vendor_category_placeholder", - )} - /> - </SelectTrigger> - <SelectContent> - {Object.values(VendorCategory).map((category) => ( - <SelectItem key={category} value={category}> - {t(`vendor.category.${category}`)} - </SelectItem> - ))} - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - <div className="mt-6"> - <div className="space-y-4"> - <Accordion type="multiple" className="space-y-4"> - {fields.map((field, index) => ( - <AccordionItem key={field.id} value={`contact-${index}`}> - <AccordionTrigger className="hover:no-underline"> - <div className="flex items-center gap-2"> - <span> - {form.watch(`contacts.${index}.name`) || - t("vendor.form.new_contact")} - </span> - <span className="text-sm text-muted-foreground"> - {form.watch(`contacts.${index}.email`)} - </span> - </div> - </AccordionTrigger> - <AccordionContent> - <div className="space-y-4 pt-4"> - <FormField - control={form.control} - name={`contacts.${index}.name`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_name")} - </FormLabel> - <FormControl> - <Input {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name={`contacts.${index}.email`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_email")} - </FormLabel> - <FormControl> - <Input {...field} type="email" /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name={`contacts.${index}.role`} - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("vendor.form.contact_role")} - </FormLabel> - <FormControl> - <Input {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <div className="flex justify-end"> - <Button - type="button" - variant="destructive" - onClick={() => handleRemoveContact(index)} - className="items-center justify-end gap-2" - > - <XCircle className="h-4 w-4" /> - {t("common.actions.delete")} - </Button> - </div> - </div> - </AccordionContent> - </AccordionItem> - ))} - </Accordion> - - <Button - type="button" - variant="outline" - onClick={() => append({ name: "", email: "", role: "" })} - > - <PlusCircle className="h-4 w-4 mr-2" /> - {t("vendor.form.add_contact")} - </Button> - </div> - </div> - <div className="flex justify-end mt-4"> - <Button type="submit" disabled={updateVendor.status === "executing"}> - {updateVendor.status === "executing" ? ( - <Loader2 className="h-4 w-4 animate-spin" /> - ) : ( - t("common.actions.save") - )} - </Button> - </div> - </form> - </Form> - ); -} diff --git a/apps/app/src/components/forms/vendors/update-vendor-overview-form.tsx b/apps/app/src/components/forms/vendors/update-vendor-overview-form.tsx deleted file mode 100644 index 453220ce25..0000000000 --- a/apps/app/src/components/forms/vendors/update-vendor-overview-form.tsx +++ /dev/null @@ -1,140 +0,0 @@ -"use client"; - -import { updateVendorSchema } from "@/actions/schema"; -import { updateVendorAction } from "@/actions/vendor/update-vendor-action"; -import { useI18n } from "@/locales/client"; -import type { Vendors } from "@bubba/db"; -import { Button } from "@bubba/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@bubba/ui/form"; -import { Input } from "@bubba/ui/input"; -import { Textarea } from "@bubba/ui/textarea"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Loader2 } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useQueryState } from "nuqs"; -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; - -interface UpdateVendorOverviewFormProps { - vendor: Vendors; -} - -export function UpdateVendorOverviewForm({ - vendor, -}: UpdateVendorOverviewFormProps) { - const t = useI18n(); - const [_, setOpen] = useQueryState("vendor-overview-sheet"); - - const updateVendor = useAction(updateVendorAction, { - onSuccess: () => { - toast.success(t("risk.vendor.form.update_vendor_success")); - setOpen(null); - }, - onError: () => { - toast.error(t("risk.vendor.form.update_vendor_error")); - }, - }); - - const form = useForm<z.infer<typeof updateVendorSchema>>({ - resolver: zodResolver(updateVendorSchema), - defaultValues: { - id: vendor.id, - name: vendor.name, - website: vendor.website, - description: vendor.description, - category: vendor.category, - status: vendor.status, - ownerId: vendor.ownerId ?? undefined, - }, - }); - - const onSubmit = (data: z.infer<typeof updateVendorSchema>) => { - updateVendor.execute(data); - }; - - return ( - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)}> - <div className="space-y-4"> - <FormField - control={form.control} - name="name" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("risk.vendor.form.vendor_name")}</FormLabel> - <FormControl> - <Input - {...field} - autoFocus - className="mt-3" - placeholder={t("risk.vendor.form.vendor_name_placeholder")} - autoCorrect="off" - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="website" - render={({ field }) => ( - <FormItem> - <FormLabel>{t("risk.vendor.form.vendor_website")}</FormLabel> - <FormControl> - <Input - {...field} - className="mt-3" - placeholder={t( - "risk.vendor.form.vendor_website_placeholder", - )} - autoCorrect="off" - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - <FormField - control={form.control} - name="description" - render={({ field }) => ( - <FormItem> - <FormLabel> - {t("risk.vendor.form.vendor_description")} - </FormLabel> - <FormControl> - <Textarea - {...field} - className="mt-3 min-h-[80px]" - placeholder={t( - "risk.vendor.form.vendor_description_placeholder", - )} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - <div className="flex justify-end mt-8"> - <Button type="submit" disabled={updateVendor.status === "executing"}> - {updateVendor.status === "executing" ? ( - <Loader2 className="h-4 w-4 animate-spin" /> - ) : ( - t("common.actions.save") - )} - </Button> - </div> - </form> - </Form> - ); -} diff --git a/apps/app/src/components/sheets/create-vendor-sheet.tsx b/apps/app/src/components/sheets/create-vendor-sheet.tsx deleted file mode 100644 index ade3c8d132..0000000000 --- a/apps/app/src/components/sheets/create-vendor-sheet.tsx +++ /dev/null @@ -1,55 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import { Button } from "@bubba/ui/button"; -import { Drawer, DrawerContent, DrawerTitle } from "@bubba/ui/drawer"; -import { useMediaQuery } from "@bubba/ui/hooks"; -import { ScrollArea } from "@bubba/ui/scroll-area"; -import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@bubba/ui/sheet"; -import { X } from "lucide-react"; -import { useQueryState } from "nuqs"; -import { CreateVendor } from "../forms/vendors/create-vendor-form"; - -export function CreateVendorSheet() { - const t = useI18n(); - const isDesktop = useMediaQuery("(min-width: 768px)"); - const [open, setOpen] = useQueryState("create-vendor-sheet"); - const isOpen = Boolean(open); - - const handleOpenChange = (open: boolean) => { - setOpen(open ? "true" : null); - }; - - if (isDesktop) { - return ( - <Sheet open={isOpen} onOpenChange={handleOpenChange}> - <SheetContent stack> - <SheetHeader className="mb-8 flex justify-between items-center flex-row"> - <SheetTitle>{t("risk.vendor.actions.create")}</SheetTitle> - <Button - size="icon" - variant="ghost" - className="p-0 m-0 size-auto hover:bg-transparent" - onClick={() => setOpen(null)} - > - <X className="h-5 w-5" /> - </Button> - </SheetHeader> - - <ScrollArea className="h-full p-0 pb-[100px]" hideScrollbar> - <CreateVendor /> - </ScrollArea> - </SheetContent> - </Sheet> - ); - } - - return ( - <Drawer open={isOpen} onOpenChange={handleOpenChange}> - <DrawerTitle hidden>{t("risk.vendor.actions.create")}</DrawerTitle> - <DrawerContent className="p-6"> - <CreateVendor /> - </DrawerContent> - </Drawer> - ); -} diff --git a/apps/app/src/components/sheets/vendor-comment-sheet.tsx b/apps/app/src/components/sheets/vendor-comment-sheet.tsx deleted file mode 100644 index 48c1a7768a..0000000000 --- a/apps/app/src/components/sheets/vendor-comment-sheet.tsx +++ /dev/null @@ -1,36 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import type { User, VendorComment, Vendors } from "@bubba/db"; -import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@bubba/ui/sheet"; -import { useQueryState } from "nuqs"; -import { CreateVendorCommentForm } from "../forms/vendors/create-vendor-comment-form"; - -interface VendorCommentSheetProps { - vendor: Vendors & { - VendorComment: (VendorComment & { - owner: User; - })[]; - }; -} - -export function VendorCommentSheet({ vendor }: VendorCommentSheetProps) { - const t = useI18n(); - const [open, setOpen] = useQueryState("vendor-comment-sheet"); - - return ( - <Sheet - open={open === "true"} - onOpenChange={(value) => setOpen(value ? "true" : null)} - > - <SheetContent className="w-full sm:max-w-[600px]"> - <SheetHeader> - <SheetTitle>{t("risk.vendor.form.add_comment")}</SheetTitle> - </SheetHeader> - <div className="mt-8"> - <CreateVendorCommentForm vendor={vendor} /> - </div> - </SheetContent> - </Sheet> - ); -} diff --git a/apps/app/src/components/sheets/vendor-overview-sheet.tsx b/apps/app/src/components/sheets/vendor-overview-sheet.tsx deleted file mode 100644 index 5c0758e05f..0000000000 --- a/apps/app/src/components/sheets/vendor-overview-sheet.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import type { User, Vendors } from "@bubba/db"; -import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@bubba/ui/sheet"; -import { useQueryState } from "nuqs"; -import { UpdateVendorOverviewForm } from "../forms/vendors/update-vendor-overview-form"; - -interface VendorOverviewSheetProps { - vendor: Vendors & { - owner: User | null; - }; -} - -export function VendorOverviewSheet({ vendor }: VendorOverviewSheetProps) { - const t = useI18n(); - const [open, setOpen] = useQueryState("vendor-overview-sheet"); - - return ( - <Sheet - open={open === "true"} - onOpenChange={(value) => setOpen(value ? "true" : null)} - > - <SheetContent className="w-full sm:max-w-[600px]"> - <SheetHeader> - <SheetTitle>{t("risk.vendor.form.update_vendor")}</SheetTitle> - </SheetHeader> - <div className="mt-8"> - <UpdateVendorOverviewForm vendor={vendor} /> - </div> - </SheetContent> - </Sheet> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/columns.tsx b/apps/app/src/components/tables/vendor-register/columns.tsx deleted file mode 100644 index 70d01f4ff5..0000000000 --- a/apps/app/src/components/tables/vendor-register/columns.tsx +++ /dev/null @@ -1,85 +0,0 @@ -"use client"; - -import { AssignedUser } from "@/components/assigned-user"; -import { VendorStatus } from "@/components/vendor-status"; -import { useI18n } from "@/locales/client"; -import type { Vendors } from "@bubba/db"; -import { Badge } from "@bubba/ui/badge"; -import { Button } from "@bubba/ui/button"; -import type { ColumnDef } from "@tanstack/react-table"; -import Link from "next/link"; - -export type VendorRegisterType = Vendors & { - owner: { - name: string | null; - image: string | null; - } | null; -}; - -export function columns(): ColumnDef<VendorRegisterType>[] { - const t = useI18n(); - - return [ - { - id: "name", - accessorKey: "name", - header: t("risk.vendor.table.name"), - cell: ({ row }) => { - return ( - <span className="truncate"> - <Button variant="link" className="p-0" asChild> - <Link href={`/vendors/${row.original.id}`}> - {row.getValue("name")} - </Link> - </Button> - </span> - ); - }, - }, - { - id: "status", - accessorKey: "status", - header: t("risk.vendor.table.status"), - cell: ({ row }) => { - return ( - <div className="flex items-center gap-2"> - <VendorStatus status={row.getValue("status")} /> - </div> - ); - }, - }, - { - id: "category", - accessorKey: "category", - header: t("risk.vendor.table.category"), - cell: ({ row }) => { - const category = row.original.category; - - if (!category) { - return <span className="hidden sm:table-cell">—</span>; - } - - return ( - <div className="hidden sm:table-cell"> - <Badge variant="secondary"> - {category.replace(/_/g, " ").toUpperCase()} - </Badge> - </div> - ); - }, - }, - { - id: "owner", - accessorKey: "owner", - header: t("risk.vendor.table.owner"), - cell: ({ row }) => { - const owner = row.original.owner; - return ( - <div className="hidden sm:table-cell"> - <AssignedUser fullName={owner?.name} avatarUrl={owner?.image} /> - </div> - ); - }, - }, - ]; -} diff --git a/apps/app/src/components/tables/vendor-register/data-table-header.tsx b/apps/app/src/components/tables/vendor-register/data-table-header.tsx deleted file mode 100644 index c126de604b..0000000000 --- a/apps/app/src/components/tables/vendor-register/data-table-header.tsx +++ /dev/null @@ -1,124 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import { Button } from "@bubba/ui/button"; -import { TableHead, TableHeader, TableRow } from "@bubba/ui/table"; -import { ArrowDown, ArrowUp } from "lucide-react"; -import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useCallback } from "react"; - -type Props = { - table?: { - getIsAllPageRowsSelected: () => boolean; - getIsSomePageRowsSelected: () => boolean; - getAllLeafColumns: () => { - id: string; - getIsVisible: () => boolean; - }[]; - toggleAllPageRowsSelected: (value: boolean) => void; - }; - loading?: boolean; -}; - -export function DataTableHeader({ table, loading }: Props) { - const searchParams = useSearchParams(); - const pathname = usePathname(); - const router = useRouter(); - const t = useI18n(); - - const sortParam = searchParams.get("sort"); - const [column, value] = sortParam ? sortParam.split(":") : []; - - const createSortQuery = useCallback( - (name: string) => { - const params = new URLSearchParams(searchParams); - const prevSort = params.get("sort"); - - if (`${name}:asc` === prevSort) { - params.set("sort", `${name}:desc`); - } else if (`${name}:desc` === prevSort) { - params.delete("sort"); - } else { - params.set("sort", `${name}:asc`); - } - - router.replace(`${pathname}?${params.toString()}`); - }, - [searchParams, router, pathname], - ); - - const isVisible = (id: string) => - loading || - table - ?.getAllLeafColumns() - .find((col) => col.id === id) - ?.getIsVisible(); - - return ( - <TableHeader> - <TableRow className="h-[45px] hover:bg-transparent"> - {isVisible("name") && ( - <TableHead className="min-w-[120px] px-3 md:px-4 py-2"> - <Button - className="p-0 hover:bg-transparent space-x-2" - variant="ghost" - onClick={() => createSortQuery("name")} - > - <span>{t("risk.vendor.table.name")}</span> - {"name" === column && value === "asc" && <ArrowDown size={16} />} - {"name" === column && value === "desc" && <ArrowUp size={16} />} - </Button> - </TableHead> - )} - - {isVisible("category") && ( - <TableHead className="min-w-[120px] px-3 md:px-4 py-2 hidden sm:table-cell"> - <Button - className="p-0 hover:bg-transparent space-x-2" - variant="ghost" - onClick={() => createSortQuery("category")} - > - <span>{t("risk.vendor.table.category")}</span> - {"category" === column && value === "asc" && ( - <ArrowDown size={16} /> - )} - {"category" === column && value === "desc" && ( - <ArrowUp size={16} /> - )} - </Button> - </TableHead> - )} - - {isVisible("status") && ( - <TableHead className="min-w-[120px] px-3 md:px-4 py-2"> - <Button - className="p-0 hover:bg-transparent space-x-2" - variant="ghost" - onClick={() => createSortQuery("status")} - > - <span>{t("risk.vendor.table.status")}</span> - {"status" === column && value === "asc" && ( - <ArrowDown size={16} /> - )} - {"status" === column && value === "desc" && <ArrowUp size={16} />} - </Button> - </TableHead> - )} - - {isVisible("owner") && ( - <TableHead className="min-w-[120px] px-3 md:px-4 py-2 hidden sm:table-cell"> - <Button - className="p-0 hover:bg-transparent space-x-2" - variant="ghost" - onClick={() => createSortQuery("owner")} - > - <span>{t("risk.vendor.table.owner")}</span> - {"owner" === column && value === "asc" && <ArrowDown size={16} />} - {"owner" === column && value === "desc" && <ArrowUp size={16} />} - </Button> - </TableHead> - )} - </TableRow> - </TableHeader> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/data-table-pagination.tsx b/apps/app/src/components/tables/vendor-register/data-table-pagination.tsx deleted file mode 100644 index 0a7254600b..0000000000 --- a/apps/app/src/components/tables/vendor-register/data-table-pagination.tsx +++ /dev/null @@ -1,89 +0,0 @@ -"use client"; - -import { Button } from "@bubba/ui/button"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@bubba/ui/select"; -import { ChevronLeft, ChevronRight } from "lucide-react"; -import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useCallback } from "react"; - -interface DataTablePaginationProps { - pageCount: number; - currentPage: number; -} - -export function DataTablePagination({ - pageCount, - currentPage, -}: DataTablePaginationProps) { - const searchParams = useSearchParams(); - const pathname = usePathname(); - const router = useRouter(); - - const createPageQuery = useCallback( - (value: number) => { - const params = new URLSearchParams(searchParams); - params.set("page", value.toString()); - router.replace(`${pathname}?${params.toString()}`); - }, - [searchParams, router, pathname], - ); - - const createPerPageQuery = useCallback( - (value: string) => { - const params = new URLSearchParams(searchParams); - params.set("per_page", value); - params.set("page", "1"); // Reset to first page when changing items per page - router.replace(`${pathname}?${params.toString()}`); - }, - [searchParams, router, pathname], - ); - - return ( - <div className="flex items-center justify-between mt-4"> - <div className="flex items-center space-x-2"> - <Select - value={searchParams.get("per_page") || "10"} - onValueChange={createPerPageQuery} - > - <SelectTrigger className="h-8 w-[70px]"> - <SelectValue placeholder="10" /> - </SelectTrigger> - <SelectContent side="top"> - {[10, 20, 30, 40, 50].map((pageSize) => ( - <SelectItem key={pageSize} value={pageSize.toString()}> - {pageSize} - </SelectItem> - ))} - </SelectContent> - </Select> - </div> - <div className="flex items-center space-x-2"> - <Button - variant="outline" - className="h-8 w-8 p-0" - onClick={() => createPageQuery(currentPage - 1)} - disabled={currentPage <= 1} - > - <ChevronLeft className="h-4 w-4" /> - </Button> - <div className="flex w-[60px] items-center justify-center text-sm font-medium"> - {currentPage} of {pageCount} - </div> - <Button - variant="outline" - className="h-8 w-8 p-0" - onClick={() => createPageQuery(currentPage + 1)} - disabled={currentPage >= pageCount} - > - <ChevronRight className="h-4 w-4" /> - </Button> - </div> - </div> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/data-table.tsx b/apps/app/src/components/tables/vendor-register/data-table.tsx deleted file mode 100644 index 444ec4cef2..0000000000 --- a/apps/app/src/components/tables/vendor-register/data-table.tsx +++ /dev/null @@ -1,96 +0,0 @@ -"use client"; - -import { - type ColumnDef, - flexRender, - getCoreRowModel, - useReactTable, -} from "@tanstack/react-table"; -import { Suspense } from "react"; - -import { cn } from "@bubba/ui/cn"; -import { Table, TableBody, TableCell, TableRow } from "@bubba/ui/table"; -import { type VendorRegisterType, columns as getColumns } from "./columns"; -import { DataTableHeader } from "./data-table-header"; -import { DataTablePagination } from "./data-table-pagination"; -import { Loading } from "./loading"; - -interface DataTableProps<TData, TValue> { - columnHeaders: { - name: string; - category: string; - status: string; - owner: string; - }; - data: TData[]; - pageCount: number; - currentPage: number; -} - -export function DataTable<TData, TValue>({ - columnHeaders, - data, - pageCount, - currentPage, -}: DataTableProps<TData, TValue>) { - const clientColumns = getColumns(); - const columns = clientColumns.map((col) => ({ - ...col, - header: columnHeaders[col.id as keyof typeof columnHeaders], - })); - - const table = useReactTable({ - data: data as VendorRegisterType[], - columns, - getCoreRowModel: getCoreRowModel(), - manualPagination: true, - pageCount, - }); - - return ( - <Suspense fallback={<Loading isEmpty={false} />}> - <div className="w-full overflow-auto"> - <Table> - <DataTableHeader table={table} /> - - <TableBody> - {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - <TableRow - key={row.id} - data-state={row.getIsSelected() && "selected"} - > - {row.getVisibleCells().map((cell) => ( - <TableCell - key={cell.id} - className={cn( - (cell.column.id === "category" || - cell.column.id === "owner") && - "hidden sm:table-cell", - )} - > - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} - </TableCell> - ))} - </TableRow> - )) - ) : ( - <TableRow> - <TableCell - colSpan={columns.length} - className="h-24 text-center" - > - No results. - </TableCell> - </TableRow> - )} - </TableBody> - </Table> - <DataTablePagination pageCount={pageCount} currentPage={currentPage} /> - </div> - </Suspense> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/empty-states.tsx b/apps/app/src/components/tables/vendor-register/empty-states.tsx deleted file mode 100644 index 91fff546eb..0000000000 --- a/apps/app/src/components/tables/vendor-register/empty-states.tsx +++ /dev/null @@ -1,66 +0,0 @@ -"use client"; - -import { CreateVendorSheet } from "@/components/sheets/create-vendor-sheet"; -import { useI18n } from "@/locales/client"; -import { Button } from "@bubba/ui/button"; -import { Icons } from "@bubba/ui/icons"; -import { Plus } from "lucide-react"; -import { useRouter } from "next/navigation"; -import { useQueryState } from "nuqs"; - -export function NoVendors() { - const t = useI18n(); - const router = useRouter(); - - const [open, setOpen] = useQueryState("create-vendor-sheet"); - - return ( - <div className="mt-24 absolute w-full top-0 left-0 flex items-center justify-center z-20"> - <div className="text-center max-w-sm mx-auto flex flex-col items-center justify-center"> - <h2 className="text-xl font-medium mb-2"> - {t("risk.vendor.empty_states.no_vendors.title")} - </h2> - <p className="text-sm text-muted-foreground mb-6"> - {t("risk.vendor.empty_states.no_vendors.description")} - </p> - <Button onClick={() => setOpen("true")} className="hidden sm:flex"> - <Plus className="h-4 w-4 mr-2" /> - {t("common.actions.create")} - </Button> - </div> - - <CreateVendorSheet /> - </div> - ); -} - -export function NoResults({ hasFilters }: { hasFilters: boolean }) { - const t = useI18n(); - const router = useRouter(); - - return ( - <div className="mt-24 flex items-center justify-center"> - <div className="flex flex-col items-center"> - <Icons.Transactions2 className="mb-4" /> - <div className="text-center mb-6 space-y-2"> - <h2 className="font-medium text-lg"> - {t("risk.vendor.empty_states.no_results.title")} - </h2> - <p className="text-muted-foreground text-sm"> - {hasFilters - ? t( - "risk.vendor.empty_states.no_results.description_with_filters", - ) - : t("risk.vendor.empty_states.no_results.description")} - </p> - </div> - - {hasFilters && ( - <Button variant="outline" onClick={() => router.push("/vendors")}> - {t("common.actions.clear")} - </Button> - )} - </div> - </div> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/filter-toolbar.tsx b/apps/app/src/components/tables/vendor-register/filter-toolbar.tsx deleted file mode 100644 index f87180c431..0000000000 --- a/apps/app/src/components/tables/vendor-register/filter-toolbar.tsx +++ /dev/null @@ -1,188 +0,0 @@ -"use client"; - -import { CreateRiskSheet } from "@/components/sheets/create-risk-sheet"; -import { CreateVendorSheet } from "@/components/sheets/create-vendor-sheet"; -import { useI18n } from "@/locales/client"; -import { - Departments, - RiskCategory, - RiskStatus, - type User, - VendorStatus, -} from "@bubba/db"; -import { Button } from "@bubba/ui/button"; -import { cn } from "@bubba/ui/cn"; -import { Input } from "@bubba/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@bubba/ui/select"; -import { Skeleton } from "@bubba/ui/skeleton"; -import { Search, X } from "lucide-react"; -import { Plus } from "lucide-react"; -import { useQueryState } from "nuqs"; -import { useTransition } from "react"; -import { useCallback } from "react"; - -const vendorStatuses = Object.values(VendorStatus); - -type Props = { - isEmpty?: boolean; - users: { - id: string; - name: string | null; - }[]; -}; - -const statusTranslationKeys = { - not_assessed: "common.status.not_assessed", - in_progress: "common.status.in_progress", - assessed: "common.status.assessed", -} as const; - -export function FilterToolbar({ isEmpty, users }: Props) { - const t = useI18n(); - const [isPending, startTransition] = useTransition(); - const [open, setOpen] = useQueryState("create-vendor-sheet"); - - const [search, setSearch] = useQueryState("search", { - shallow: false, - history: "push", - parse: (value) => value || null, - }); - - const [category, setCategory] = useQueryState("category", { - shallow: false, - history: "push", - parse: (value) => value || null, - }); - - const [status, setStatus] = useQueryState("status", { - shallow: false, - history: "push", - parse: (value) => value || null, - }); - - const [ownerId, setOwnerId] = useQueryState("ownerId", { - shallow: false, - history: "push", - parse: (value) => value || null, - }); - - const handleReset = useCallback(() => { - startTransition(() => { - Promise.all([ - setSearch(null), - setCategory(null), - setStatus(null), - setOwnerId(null), - ]); - }); - }, [setSearch, setCategory, setStatus, setOwnerId]); - - const hasFilters = search || category || status || ownerId; - - if (isEmpty) { - return ( - <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between mb-4 opacity-20 pointer-events-none blur-[7px]"> - <div className="relative flex-1 md:max-w-sm"> - <Skeleton className={cn("h-10", isEmpty && "animate-none")} /> - </div> - - <div className="md:flex gap-2 md:flex-row md:items-center hidden"> - <Skeleton - className={cn("h-10 w-[200px]", isEmpty && "animate-none")} - /> - <Skeleton - className={cn("h-10 w-[200px]", isEmpty && "animate-none")} - /> - <Skeleton - className={cn("h-9 w-[120px]", isEmpty && "animate-none")} - /> - </div> - </div> - ); - } - - return ( - <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between mb-4"> - <div className="relative flex-1 sm:max-w-sm"> - <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" /> - <Input - placeholder={t("common.filters.search")} - className="pl-8" - value={search || ""} - onChange={(e) => setSearch(e.target.value || null)} - /> - </div> - - <div className="flex gap-2 items-center flex-wrap"> - <div className="sm:flex gap-2 sm:flex-row sm:items-center hidden"> - <Select - value={status || ""} - onValueChange={(value) => setStatus(value || null)} - > - <SelectTrigger className="w-[200px] min-w-[200px]"> - <SelectValue placeholder={t("common.filters.status")} /> - </SelectTrigger> - <SelectContent> - {vendorStatuses.map((stat) => ( - <SelectItem key={stat} value={stat}> - {t( - statusTranslationKeys[ - stat.toLowerCase() as keyof typeof statusTranslationKeys - ], - )} - </SelectItem> - ))} - </SelectContent> - </Select> - - <Select - value={ownerId || ""} - onValueChange={(value) => setOwnerId(value || null)} - > - <SelectTrigger className="w-[200px] min-w-[200px]"> - <SelectValue - placeholder={t("common.filters.owner.placeholder")} - /> - </SelectTrigger> - <SelectContent> - {users.map((user) => ( - <SelectItem key={user.id} value={user.id}> - {user.name} - </SelectItem> - ))} - </SelectContent> - </Select> - </div> - - {hasFilters && ( - <Button - variant="ghost" - size="sm" - onClick={handleReset} - disabled={isPending} - > - <X className="h-4 w-4 mr-2" /> - {t("common.actions.clear")} - </Button> - )} - - <Button - onClick={() => setOpen("true")} - variant="outline" - size="icon" - className="hidden sm:flex" - > - <Plus className="h-4 w-4" /> - </Button> - </div> - - <CreateVendorSheet /> - </div> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/loading.tsx b/apps/app/src/components/tables/vendor-register/loading.tsx deleted file mode 100644 index b71ac4249c..0000000000 --- a/apps/app/src/components/tables/vendor-register/loading.tsx +++ /dev/null @@ -1,57 +0,0 @@ -"use client"; - -import { cn } from "@bubba/ui/cn"; -import { Skeleton } from "@bubba/ui/skeleton"; -import { Table, TableBody, TableCell, TableRow } from "@bubba/ui/table"; -import { Suspense } from "react"; -import { DataTableHeader } from "./data-table-header"; - -const data = [...Array(10)].map((_, i) => ({ id: i.toString() })); - -export function Loading({ - isEmpty, -}: { - isEmpty: boolean; -}) { - return ( - <Suspense fallback={<Loading isEmpty={false} />}> - <div className="w-full overflow-auto"> - <Table - className={cn(isEmpty && "opacity-20 pointer-events-none blur-[7px]")} - > - <DataTableHeader loading /> - - <TableBody> - {data?.map((row) => ( - <TableRow key={row.id} className="h-[45px]"> - <TableCell className="w-[300px]"> - <Skeleton - className={cn("h-3.5 w-[80%]", isEmpty && "animate-none")} - /> - </TableCell> - <TableCell className="hidden sm:table-cell w-[200px]"> - <Skeleton - className={cn("h-3.5 w-[70%]", isEmpty && "animate-none")} - /> - </TableCell> - <TableCell className="w-[150px]"> - <Skeleton - className={cn("h-3.5 w-[60%]", isEmpty && "animate-none")} - /> - </TableCell> - <TableCell className="hidden sm:table-cell w-[100px]"> - <Skeleton - className={cn( - "h-[20px] w-[20px] rounded-full", - isEmpty && "animate-none", - )} - /> - </TableCell> - </TableRow> - ))} - </TableBody> - </Table> - </div> - </Suspense> - ); -} diff --git a/apps/app/src/components/tables/vendor-register/server-columns.tsx b/apps/app/src/components/tables/vendor-register/server-columns.tsx deleted file mode 100644 index c60034f665..0000000000 --- a/apps/app/src/components/tables/vendor-register/server-columns.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { getI18n } from "@/locales/server"; - -export async function getServerColumnHeaders() { - const t = await getI18n(); - - return { - name: t("risk.vendor.table.name"), - category: t("risk.vendor.table.category"), - status: t("risk.vendor.table.status"), - owner: t("risk.vendor.table.owner"), - }; -} diff --git a/apps/app/src/components/upload/FileCard.tsx b/apps/app/src/components/upload/FileCard.tsx index 33fbd21518..4914f5e9be 100644 --- a/apps/app/src/components/upload/FileCard.tsx +++ b/apps/app/src/components/upload/FileCard.tsx @@ -59,7 +59,6 @@ export function FileCard({ const isImage = /\.(jpg|jpeg|png|gif|webp)$/i.test(fileName); const isPdf = /\.pdf$/i.test(fileName); - // Load preview automatically when component mounts const [hasLoadedPreview, setHasLoadedPreview] = useState(false); useEffect(() => { @@ -130,7 +129,7 @@ export function FileCard({ variant="ghost" className="text-xs text-muted-foreground hover:text-foreground" > - {t("upload.fileCard.preview")} + {t("common.upload.fileCard.preview")} </Button> </DialogTrigger> </div> @@ -152,7 +151,9 @@ export function FileCard({ <DialogContent className="max-w-4xl w-full"> <DialogTitle className="flex items-center justify-between mb-4"> - <span>{t("upload.fileCard.filePreview", { fileName })}</span> + <span> + {t("common.upload.fileCard.filePreview", { fileName })} + </span> </DialogTitle> {previewState.url ? ( @@ -176,7 +177,7 @@ export function FileCard({ ) : ( <div className="flex items-center justify-center h-full"> <p className="text-muted-foreground"> - {t("upload.fileCard.previewNotAvailable")} + {t("common.upload.fileCard.previewNotAvailable")} </p> </div> )} @@ -216,7 +217,7 @@ export function FileCard({ </Button> </TooltipTrigger> <TooltipContent> - <p>{t("upload.fileCard.openFile")}</p> + <p>{t("common.upload.fileCard.openFile")}</p> </TooltipContent> </Tooltip> </TooltipProvider> @@ -236,17 +237,17 @@ export function FileCard({ </AlertDialogTrigger> </TooltipTrigger> <TooltipContent> - <p>{t("upload.fileCard.deleteFile")}</p> + <p>{t("common.upload.fileCard.deleteFile")}</p> </TooltipContent> </Tooltip> </TooltipProvider> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle> - {t("upload.fileCard.deleteFileConfirmTitle")} + {t("common.upload.fileCard.deleteFileConfirmTitle")} </AlertDialogTitle> <AlertDialogDescription> - {t("upload.fileCard.deleteFileConfirmDescription")} + {t("common.upload.fileCard.deleteFileConfirmDescription")} </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> diff --git a/apps/app/src/components/upload/FileSection.tsx b/apps/app/src/components/upload/FileSection.tsx index 0b0b70aef3..5ecdda6111 100644 --- a/apps/app/src/components/upload/FileSection.tsx +++ b/apps/app/src/components/upload/FileSection.tsx @@ -107,7 +107,7 @@ export function FileSection({ <div className="space-y-6"> <div className="flex items-center justify-between"> <span className="text-xs text-muted-foreground"> - {t("upload.fileSection.filesUploaded", { + {t("common.upload.fileSection.filesUploaded", { count: fileUrls.length, })} </span> diff --git a/apps/app/src/components/upload/FileUpload.tsx b/apps/app/src/components/upload/FileUpload.tsx index ab66407085..7c2346fad4 100644 --- a/apps/app/src/components/upload/FileUpload.tsx +++ b/apps/app/src/components/upload/FileUpload.tsx @@ -90,7 +90,7 @@ export function FileUpload({ <Upload className="h-6 w-6 text-primary animate-pulse" /> </div> <p className="text-sm font-medium text-center"> - {t("upload.fileUpload.uploadingText")} + {t("common.upload.fileUpload.uploadingText")} </p> </div> ) : isDragActive ? ( @@ -99,10 +99,10 @@ export function FileUpload({ <Cloud className="h-6 w-6 text-primary" /> </div> <p className="text-sm font-medium text-center"> - {t("upload.fileUpload.dropFileHere")} + {t("common.upload.fileUpload.dropFileHere")} </p> <p className="text-xs text-muted-foreground mt-1 text-center"> - {t("upload.fileUpload.releaseToUpload")} + {t("common.upload.fileUpload.releaseToUpload")} </p> </div> ) : ( @@ -111,13 +111,13 @@ export function FileUpload({ <Plus className="h-6 w-6 text-primary" /> </div> <p className="text-sm font-medium text-center"> - {t("upload.fileUpload.addFiles")} + {t("common.upload.fileUpload.addFiles")} </p> <p className="text-xs text-muted-foreground mt-1 text-center"> - {t("upload.fileUpload.uploadAdditionalEvidence")} + {t("common.upload.fileUpload.uploadAdditionalEvidence")} </p> <p className="text-xs text-muted-foreground mt-2 text-center"> - {t("upload.fileUpload.dragDropOrClick")} + {t("common.upload.fileUpload.dragDropOrClick")} </p> </> )} @@ -146,18 +146,20 @@ export function FileUpload({ {isUploading ? ( <> <Loader2 className="h-6 w-6 animate-spin text-primary" /> - <p className="mt-2">{t("upload.fileUpload.uploadingFile")}</p> + <p className="mt-2"> + {t("common.upload.fileUpload.uploadingFile")} + </p> </> ) : ( <> <Cloud className="h-6 w-6 text-primary" /> <p className="mt-2"> {isDragActive - ? t("upload.fileUpload.dropFileHereAlt") - : t("upload.fileUpload.dragDropOrClickToSelect")} + ? t("common.upload.fileUpload.dropFileHereAlt") + : t("common.upload.fileUpload.dragDropOrClickToSelect")} </p> <p className="mt-1"> - {t("upload.fileUpload.maxFileSize", { + {t("common.upload.fileUpload.maxFileSize", { size: Math.round(maxSize / 1024 / 1024), })} </p> diff --git a/apps/app/src/components/vendors/charts/category-chart.tsx b/apps/app/src/components/vendors/charts/category-chart.tsx deleted file mode 100644 index d9576afd2c..0000000000 --- a/apps/app/src/components/vendors/charts/category-chart.tsx +++ /dev/null @@ -1,145 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { - type ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@bubba/ui/chart"; -import { Bar, BarChart, Cell, LabelList, XAxis, YAxis } from "recharts"; - -interface CategoryChartProps { - data: Array<{ - name: string; - value: number; - }>; -} - -export function CategoryChart({ data }: CategoryChartProps) { - const t = useI18n(); - - const config: ChartConfig = { - cloud: { - label: t("vendor.category.cloud"), - color: "hsl(var(--chart-1))", - }, - infrastructure: { - label: t("vendor.category.infrastructure"), - color: "hsl(var(--chart-2))", - }, - software_as_a_service: { - label: t("vendor.category.software_as_a_service"), - color: "hsl(var(--chart-3))", - }, - finance: { - label: t("vendor.category.finance"), - color: "hsl(var(--chart-4))", - }, - marketing: { - label: t("vendor.category.marketing"), - color: "hsl(var(--chart-4))", - }, - sales: { - label: t("vendor.category.sales"), - color: "hsl(var(--chart-4))", - }, - hr: { - label: t("vendor.category.hr"), - color: "hsl(var(--chart-4))", - }, - other: { - label: t("vendor.category.other"), - color: "hsl(var(--chart-4))", - }, - } satisfies ChartConfig; - - const defaultData = { - cloud: 0, - infrastructure: 0, - software_as_a_service: 0, - finance: 0, - marketing: 0, - sales: 0, - hr: 0, - other: 0, - }; - - const dataMap = Object.fromEntries( - data.map((item) => [item.name.toLowerCase(), item.value]), - ); - - const formattedData = Object.entries(defaultData).map(([key]) => ({ - name: config[key as keyof typeof config].label, - value: dataMap[key] ?? 0, - category: key, - })); - - // Calculate the maximum label width to set left margin - const maxLabelLength = Math.max( - ...formattedData.map((item) => item.name?.toLocaleString.length ?? 0), - ); - - const leftMargin = Math.max(maxLabelLength * 8, 50); // 8px per character, minimum 100px - - return ( - <Card> - <CardHeader> - <CardTitle>{t("vendor.dashboard.vendor_category")}</CardTitle> - </CardHeader> - <CardContent> - <ChartContainer config={config}> - <BarChart - accessibilityLayer - data={formattedData} - layout="vertical" - margin={{ - left: 45, - right: 16, - }} - > - <YAxis - dataKey="name" - type="category" - tickLine={false} - tickMargin={10} - axisLine={false} - width={leftMargin} - style={{ - fontSize: "12px", - }} - /> - <XAxis dataKey="value" type="number" hide /> - <ChartTooltip - cursor={false} - content={<ChartTooltipContent indicator="line" />} - /> - <Bar - dataKey="value" - layout="vertical" - fill="hsl(var(--chart-1))" - maxBarSize={30} - > - <LabelList - dataKey="value" - position="right" - offset={8} - className="fill-foreground" - fontSize={12} - /> - {formattedData.map((entry, index) => ( - <Cell - name="Total" - key={entry.category} - fill={config[entry.category as keyof typeof config].color} - radius={8} - /> - ))} - </Bar> - </BarChart> - </ChartContainer> - </CardContent> - </Card> - ); -} diff --git a/apps/app/src/components/vendors/charts/status-chart.tsx b/apps/app/src/components/vendors/charts/status-chart.tsx deleted file mode 100644 index 3c0406c512..0000000000 --- a/apps/app/src/components/vendors/charts/status-chart.tsx +++ /dev/null @@ -1,129 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { - type ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@bubba/ui/chart"; -import { Cell, Pie, PieChart } from "recharts"; - -interface StatusChartProps { - data: Array<{ - name: string; - value: number; - }>; -} - -export function StatusChart({ data }: StatusChartProps) { - const t = useI18n(); - - const config: ChartConfig = { - assessed: { - label: t("common.status.assessed"), - color: "hsl(var(--chart-1))", - }, - in_progress: { - label: t("common.status.in_progress"), - color: "hsl(var(--chart-2))", - }, - not_assessed: { - label: t("common.status.not_assessed"), - color: "hsl(var(--chart-3))", - }, - }; - - const defaultData = { - assessed: 0, - in_progress: 0, - not_assessed: 0, - }; - - const dataMap = Object.fromEntries( - data.map((item) => [item.name.toLowerCase(), item.value]), - ); - - const formattedData = Object.entries(defaultData) - .map(([key]) => ({ - name: config[key as keyof typeof config].label, - value: dataMap[key] ?? 0, - status: key, - })) - .filter((item) => item.value > 0); - - if (formattedData.length === 0) { - return ( - <Card> - <CardHeader> - <CardTitle>{t("vendor.dashboard.vendor_status")}</CardTitle> - </CardHeader> - <CardContent className="flex h-[300px] items-center justify-center text-muted-foreground"> - No data - </CardContent> - </Card> - ); - } - - return ( - <Card> - <CardHeader> - <CardTitle>{t("vendor.dashboard.vendor_status")}</CardTitle> - </CardHeader> - <CardContent> - <ChartContainer config={config}> - <PieChart - margin={{ - top: 20, - right: 80, - bottom: 20, - left: 80, - }} - width={400} - height={300} - > - <Pie - data={formattedData} - dataKey="value" - nameKey="name" - cx="50%" - cy="50%" - innerRadius={50} - outerRadius={70} - paddingAngle={4} - label={({ name, value, x, y, cx, cy }) => ( - <text - x={x} - y={y} - dy={y > cy ? 15 : -5} - fill="currentColor" - textAnchor={x > cx ? "start" : "end"} - className="text-xs" - dx={x > cx ? 5 : -5} - > - {`${name}: ${value}`} - </text> - )} - labelLine={{ - strokeWidth: 1, - }} - > - {formattedData.map((entry) => ( - <Cell - key={entry.status} - fill={config[entry.status as keyof typeof config].color} - radius={8} - /> - ))} - </Pie> - <ChartTooltip - cursor={false} - content={<ChartTooltipContent indicator="line" />} - /> - </PieChart> - </ChartContainer> - </CardContent> - </Card> - ); -} diff --git a/apps/app/src/components/vendors/charts/vendor-overview.tsx b/apps/app/src/components/vendors/charts/vendor-overview.tsx deleted file mode 100644 index 4d55ae23a6..0000000000 --- a/apps/app/src/components/vendors/charts/vendor-overview.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { VendorsByAssignee } from "./vendors-by-assignee"; -import { VendorsByCategory } from "./vendors-by-category"; -import { VendorsByStatus } from "./vendors-by-status"; - -interface VendorOverviewProps { - organizationId: string; -} - -export function VendorOverview({ organizationId }: VendorOverviewProps) { - return ( - <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> - <VendorsByStatus organizationId={organizationId} /> - <VendorsByCategory organizationId={organizationId} /> - <div className="md:col-span-1"> - <VendorsByAssignee organizationId={organizationId} /> - </div> - </div> - ); -} diff --git a/apps/app/src/components/vendors/charts/vendors-by-assignee.tsx b/apps/app/src/components/vendors/charts/vendors-by-assignee.tsx deleted file mode 100644 index 77a863254b..0000000000 --- a/apps/app/src/components/vendors/charts/vendors-by-assignee.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { getInitials } from "@/lib/utils"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import { Avatar, AvatarFallback, AvatarImage } from "@bubba/ui/avatar"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { ScrollArea } from "@bubba/ui/scroll-area"; -import Link from "next/link"; - -interface Props { - organizationId: string; -} - -interface UserVendorStats { - user: { - id: string; - name: string | null; - image: string | null; - }; - totalVendors: number; - notAssessedVendors: number; - inProgressVendors: number; - assessedVendors: number; -} - -export async function VendorsByAssignee({ organizationId }: Props) { - const t = await getI18n(); - - const userStats = await userData(organizationId); - - const stats: UserVendorStats[] = userStats.map((user) => ({ - user: { - id: user.id, - name: user.name, - image: user.image, - }, - totalVendors: user.Vendors.length, - notAssessedVendors: user.Vendors.filter( - (vendor) => vendor.status === "not_assessed", - ).length, - inProgressVendors: user.Vendors.filter( - (vendor) => vendor.status === "in_progress", - ).length, - assessedVendors: user.Vendors.filter( - (vendor) => vendor.status === "assessed", - ).length, - })); - - stats.sort((a, b) => b.totalVendors - a.totalVendors); - - return ( - <Card> - <CardHeader> - <CardTitle>{t("vendor.dashboard.vendors_by_assignee")}</CardTitle> - </CardHeader> - <CardContent> - <ScrollArea> - <div className="space-y-4"> - {stats.map((stat) => ( - <Link - href={`/vendors/register?ownerId=${stat.user.id}`} - key={stat.user.id} - > - <div className="flex items-center gap-4 p-3 rounded-lg hover:bg-muted/50"> - <Avatar> - <AvatarImage src={stat.user.image || undefined} /> - <AvatarFallback> - {getInitials(stat.user.name || "Unknown User")} - </AvatarFallback> - </Avatar> - - <div className="flex-1 min-w-0"> - <div className="flex items-center justify-between"> - <p className="text-sm font-medium leading-none truncate"> - {stat.user.name || "Unknown User"} - </p> - <span className="text-sm text-muted-foreground"> - {stat.totalVendors} {t("vendor.vendors")} - </span> - </div> - - <div className="mt-2 w-full bg-muted rounded-full h-2 overflow-hidden"> - {stat.totalVendors > 0 && ( - <div className="h-full flex"> - {stat.notAssessedVendors > 0 && ( - <div - className="bg-yellow-500 h-full" - style={{ - width: `${(stat.notAssessedVendors / stat.totalVendors) * 100}%`, - }} - title={`${t("common.status.not_assessed")}: ${stat.notAssessedVendors}`} - /> - )} - {stat.inProgressVendors > 0 && ( - <div - className="bg-blue-500 h-full" - style={{ - width: `${(stat.inProgressVendors / stat.totalVendors) * 100}%`, - }} - title={`${t("common.status.in_progress")}: ${stat.inProgressVendors}`} - /> - )} - {stat.assessedVendors > 0 && ( - <div - className="bg-green-500 h-full" - style={{ - width: `${(stat.assessedVendors / stat.totalVendors) * 100}%`, - }} - title={`${t("common.status.assessed")}: ${stat.assessedVendors}`} - /> - )} - </div> - )} - </div> - - <div className="mt-1.5 hidden lg:flex items-center gap-3 text-xs text-muted-foreground"> - {stat.notAssessedVendors > 0 && ( - <div className="flex items-center gap-1"> - <div className="size-2 rounded-full bg-yellow-500" /> - <span> - {t("common.status.not_assessed")} ( - {stat.notAssessedVendors}) - </span> - </div> - )} - {stat.inProgressVendors > 0 && ( - <div className="flex items-center gap-1"> - <div className="size-2 rounded-full bg-blue-500" /> - <span> - {t("common.status.in_progress")} ( - {stat.inProgressVendors}) - </span> - </div> - )} - {stat.assessedVendors > 0 && ( - <div className="flex items-center gap-1"> - <div className="size-2 rounded-full bg-green-500" /> - <span> - {t("common.status.assessed")} ( - {stat.assessedVendors}) - </span> - </div> - )} - </div> - </div> - </div> - </Link> - ))} - </div> - </ScrollArea> - </CardContent> - </Card> - ); -} - -async function userData(organizationId: string) { - return await db.user.findMany({ - where: { - organizationId, - Vendors: { - some: {}, - }, - }, - select: { - id: true, - name: true, - image: true, - Vendors: { - select: { - status: true, - }, - }, - }, - }); -} diff --git a/apps/app/src/components/vendors/charts/vendors-by-category.tsx b/apps/app/src/components/vendors/charts/vendors-by-category.tsx deleted file mode 100644 index 369b069e07..0000000000 --- a/apps/app/src/components/vendors/charts/vendors-by-category.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { db } from "@bubba/db"; -import { CategoryChart } from "./category-chart"; - -interface Props { - organizationId: string; -} - -export async function VendorsByCategory({ organizationId }: Props) { - const vendors = await getVendorsByCategory(organizationId); - - const data = vendors.map((vendor) => ({ - name: vendor.category, - value: vendor._count, - })); - - return <CategoryChart data={data} />; -} - -async function getVendorsByCategory(organizationId: string) { - return await db.vendors.groupBy({ - by: ["category"], - where: { organizationId }, - _count: true, - }); -} diff --git a/apps/app/src/components/vendors/charts/vendors-by-status.tsx b/apps/app/src/components/vendors/charts/vendors-by-status.tsx deleted file mode 100644 index c5103cfcdd..0000000000 --- a/apps/app/src/components/vendors/charts/vendors-by-status.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { db } from "@bubba/db"; -import { StatusChart } from "./status-chart"; - -interface Props { - organizationId: string; -} - -export async function VendorsByStatus({ organizationId }: Props) { - const vendors = await getVendorsByStatus(organizationId); - - const data = vendors.map((vendor) => ({ - name: vendor.status, - value: vendor._count, - })); - - return <StatusChart data={data} />; -} - -async function getVendorsByStatus(organizationId: string) { - return await db.vendors.groupBy({ - by: ["status"], - where: { organizationId }, - _count: true, - }); -} diff --git a/apps/app/src/components/vendors/vendor-assessment.tsx b/apps/app/src/components/vendors/vendor-assessment.tsx deleted file mode 100644 index 8046e54fab..0000000000 --- a/apps/app/src/components/vendors/vendor-assessment.tsx +++ /dev/null @@ -1,110 +0,0 @@ -"use client"; - -import { updateVendorRiskAction } from "@/actions/vendor/update-vendor-risk-action"; -import { useI18n } from "@/locales/client"; -import type { Vendors } from "@bubba/db"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { cn } from "@bubba/ui/cn"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@bubba/ui/select"; -import { useAction } from "next-safe-action/hooks"; -import { toast } from "sonner"; - -interface VendorAssessmentProps { - vendor: Vendors; -} - -export function VendorAssessment({ vendor }: VendorAssessmentProps) { - const t = useI18n(); - - const updateRisk = useAction(updateVendorRiskAction, { - onSuccess: () => { - toast.success(t("risk.vendor.assessment.update_success")); - }, - onError: () => { - toast.error(t("risk.vendor.assessment.update_error")); - }, - }); - - return ( - <Card> - <CardHeader> - <CardTitle>{t("risk.vendor.assessment.title")}</CardTitle> - </CardHeader> - <CardContent> - <div className="space-y-4"> - <div> - {t("risk.vendor.assessment.inherent_risk")} - <Select - value={vendor.inherent_risk} - onValueChange={(value) => - updateRisk.execute({ - id: vendor.id, - inherent_risk: value as "low" | "medium" | "high" | "unknown", - }) - } - > - <SelectTrigger - className={cn( - "mt-2", - vendor.inherent_risk === "high" && "text-destructive", - )} - > - <SelectValue /> - </SelectTrigger> - <SelectContent> - <SelectItem value="low"> - {t("risk.vendor.risk_level.low")} - </SelectItem> - <SelectItem value="medium"> - {t("risk.vendor.risk_level.medium")} - </SelectItem> - <SelectItem value="high" className="text-destructive"> - {t("risk.vendor.risk_level.high")} - </SelectItem> - </SelectContent> - </Select> - </div> - - <div> - {t("risk.vendor.assessment.residual_risk")} - <Select - value={vendor.residual_risk} - onValueChange={(value) => - updateRisk.execute({ - id: vendor.id, - residual_risk: value as "low" | "medium" | "high" | "unknown", - }) - } - > - <SelectTrigger - className={cn( - "mt-2", - vendor.residual_risk === "high" && "text-destructive", - )} - > - <SelectValue /> - </SelectTrigger> - <SelectContent> - <SelectItem value="low"> - {t("risk.vendor.risk_level.low")} - </SelectItem> - <SelectItem value="medium"> - {t("risk.vendor.risk_level.medium")} - </SelectItem> - <SelectItem value="high" className="text-destructive"> - {t("risk.vendor.risk_level.high")} - </SelectItem> - </SelectContent> - </Select> - </div> - </div> - </CardContent> - </Card> - ); -} diff --git a/apps/app/src/components/vendors/vendor-comments.tsx b/apps/app/src/components/vendors/vendor-comments.tsx deleted file mode 100644 index 42fbdefd0b..0000000000 --- a/apps/app/src/components/vendors/vendor-comments.tsx +++ /dev/null @@ -1,72 +0,0 @@ -"use client"; - -import { AssignedUser } from "@/components/assigned-user"; -import { useI18n } from "@/locales/client"; -import type { User, VendorComment, Vendors } from "@bubba/db"; -import { Button } from "@bubba/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { EmptyCard } from "@bubba/ui/empty-card"; -import { format } from "date-fns"; -import { MessageSquare } from "lucide-react"; -import { useQueryState } from "nuqs"; -import { VendorCommentSheet } from "../sheets/vendor-comment-sheet"; - -interface VendorCommentsProps { - vendor: Vendors & { - VendorComment: (VendorComment & { - owner: User; - })[]; - }; - users: User[]; -} - -export function VendorComments({ vendor, users }: VendorCommentsProps) { - const t = useI18n(); - const [open, setOpen] = useQueryState("vendor-comment-sheet"); - - return ( - <Card> - <CardHeader> - <CardTitle> - <div className="flex items-center justify-between gap-2"> - {t("common.comments.title")} - <Button variant="outline" onClick={() => setOpen("true")}> - {t("common.comments.add")} - </Button> - </div> - </CardTitle> - </CardHeader> - <CardContent> - {vendor.VendorComment.length > 0 ? ( - <div className="flex flex-col gap-2"> - {vendor.VendorComment.map((comment) => ( - <div key={comment.id} className="flex flex-col gap-2 border p-4"> - <div className="flex items-center gap-2">{comment.content}</div> - <div className="flex items-center gap-2"> - <div className="flex items-center gap-2"> - <AssignedUser - fullName={comment.owner.name} - avatarUrl={comment.owner.image} - /> - <span className="text-sm text-muted-foreground"> - ({format(comment.createdAt, "MMM d, yyyy")}) - </span> - </div> - </div> - </div> - ))} - </div> - ) : ( - <EmptyCard - title={t("common.empty_states.no_items.title")} - icon={MessageSquare} - description={t("common.empty_states.no_items.description")} - className="w-full" - /> - )} - </CardContent> - - <VendorCommentSheet vendor={vendor} /> - </Card> - ); -} diff --git a/apps/app/src/components/vendors/vendor-overview.tsx b/apps/app/src/components/vendors/vendor-overview.tsx deleted file mode 100644 index 68ecad6b5d..0000000000 --- a/apps/app/src/components/vendors/vendor-overview.tsx +++ /dev/null @@ -1,64 +0,0 @@ -"use client"; - -import { useI18n } from "@/locales/client"; -import type { User, VendorContact, Vendors } from "@bubba/db"; -import { Alert, AlertDescription, AlertTitle } from "@bubba/ui/alert"; -import { Button } from "@bubba/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { PencilIcon, ShieldAlert } from "lucide-react"; -import { useQueryState } from "nuqs"; -import { UpdateVendorForm } from "../forms/vendors/update-vendor-form"; -import { VendorOverviewSheet } from "../sheets/vendor-overview-sheet"; -import { Icons } from "@bubba/ui/icons"; - -interface VendorOverviewProps { - vendor: Vendors & { - owner: User | null; - VendorContact: VendorContact[]; - }; - users: User[]; -} - -export function VendorOverview({ vendor, users }: VendorOverviewProps) { - const t = useI18n(); - const [open, setOpen] = useQueryState("vendor-overview-sheet"); - - return ( - <div className="space-y-4"> - <Alert> - <Icons.Vendors className="h-4 w-4" /> - <AlertTitle> - <div className="flex items-center justify-between gap-2"> - {vendor.name} - <Button - size="icon" - variant="ghost" - className="p-0 m-0 size-auto" - onClick={() => setOpen("true")} - > - <PencilIcon className="h-3 w-3" /> - </Button> - </div> - </AlertTitle> - <AlertDescription className="mt-4"> - {vendor.description} - </AlertDescription> - </Alert> - - <Card> - <CardHeader> - <CardTitle> - <div className="flex items-center justify-between gap-2"> - {t("risk.vendor.dashboard.overview")} - </div> - </CardTitle> - </CardHeader> - <CardContent> - <UpdateVendorForm vendor={vendor} users={users} /> - </CardContent> - </Card> - - <VendorOverviewSheet vendor={vendor} /> - </div> - ); -} diff --git a/apps/app/src/locales/en.ts b/apps/app/src/locales/en.ts index fc223e30e0..9b598feb8c 100644 --- a/apps/app/src/locales/en.ts +++ b/apps/app/src/locales/en.ts @@ -1,947 +1,986 @@ export default { - language: { - title: "Languages", - description: "Change the language used in the user interface.", - placeholder: "Select language", - }, - languages: { - en: "English", - es: "Spanish", - fr: "French", - no: "Norwegian", - pt: "Portuguese", - }, - common: { - frequency: { - daily: "Daily", - weekly: "Weekly", - monthly: "Monthly", - quarterly: "Quarterly", - yearly: "Yearly", - }, - notifications: { - inbox: "Inbox", - archive: "Archive", - archive_all: "Archive all", - no_notifications: "No new notifications", - }, - actions: { - save: "Save", - edit: "Edit", - delete: "Delete", - cancel: "Cancel", - clear: "Clear", - create: "Create", - addNew: "Add New", - send: "Send", - return: "Return", - success: "Success", - error: "Error", - next: "Next", - complete: "Complete", - }, - assignee: { - label: "Assignee", - placeholder: "Select assignee", - }, - date: { - pick: "Pick a date", - due_date: "Due Date", - }, - status: { - open: "Open", - pending: "Pending", - closed: "Closed", - archived: "Archived", - compliant: "Compliant", - non_compliant: "Non Compliant", - not_started: "Not Started", - in_progress: "In Progress", - published: "Published", - needs_review: "Needs Review", - draft: "Draft", - not_assessed: "Not Assessed", - assessed: "Assessed", - active: "Active", - inactive: "Inactive", - title: "Status", - }, - filters: { - clear: "Clear filters", - search: "Search...", - status: "Status", - department: "Department", - owner: { - label: "Assignee", - placeholder: "Filter by assignee", - }, - }, - table: { - title: "Title", - status: "Status", - assigned_to: "Assigned To", - due_date: "Due Date", - last_updated: "Last Updated", - no_results: "No results found", - }, - empty_states: { - no_results: { - title: "No results found", - title_tasks: "No tasks found", - title_risks: "No risks found", - description: "Try another search, or adjusting the filters", - description_filters: "Try another search, or adjusting the filters", - description_no_tasks: "Create a task to get started", - description_no_risks: "Create a risk to get started", - }, - no_items: { - title: "No items found", - description: "Try adjusting your search or filters", - }, - }, - pagination: { - of: "of", - items_per_page: "Items per page", - rows_per_page: "Rows per page", - page_x_of_y: "Page {{current}} of {{total}}", - go_to_first_page: "Go to first page", - go_to_previous_page: "Go to previous page", - go_to_next_page: "Go to next page", - go_to_last_page: "Go to last page", - }, - comments: { - title: "Comments", - description: "Add a comment using the form below.", - add: "New Comment", - new: "New Comment", - save: "Save Comment", - success: "Comment added successfully", - error: "Failed to add comment", - placeholder: "Write your comment here...", - empty: { - title: "No comments yet", - description: "Be the first to add a comment", - }, - }, - attachments: { - title: "Attachments", - description: "Add a file by clicking 'Add Attachment'.", - upload: "Upload attachment", - upload_description: - "Upload an attachment or add a link to an external resource.", - drop: "Drop the files here", - drop_description: - "Drop files here or click to choose files from your device.", - drop_files_description: "Files can be up to ", - empty: { - title: "No attachments", - description: "Add a file by clicking 'Add Attachment'.", - }, - toasts: { - error: "Something went wrong, please try again.", - error_uploading_files: "Cannot upload more than 1 file at a time", - error_uploading_files_multiple: "Cannot upload more than 10 files", - error_no_files_selected: "No files selected", - error_file_rejected: "File {file} was rejected", - error_failed_to_upload_files: "Failed to upload files", - error_failed_to_upload_files_multiple: "Failed to upload files", - error_failed_to_upload_files_single: "Failed to upload file", - success_uploading_files: "Files uploaded successfully", - success_uploading_files_multiple: "Files uploaded successfully", - success_uploading_files_single: "File uploaded successfully", - success_uploading_files_target: "Files uploaded", - uploading_files: "Uploading {target}...", - remove_file: "Remove file", - }, - }, - edit: "Edit", - errors: { - unexpected_error: "An unexpected error occurred", - }, - description: "Description", - last_updated: "Last Updated", - }, - header: { - discord: { - button: "Join us on Discord", - }, - feedback: { - button: "Feedback", - title: "Thank you for your feedback!", - description: "We will be back with you as soon as possible", - placeholder: "Ideas to improve this page or issues you are experiencing.", - success: "Thank you for your feedback!", - error: "Error sending feedback - try again?", - send: "Send Feedback", - }, - }, - not_found: { - title: "404 - Page not found", - description: "The page you are looking for does not exist.", - return: "Return to dashboard", - }, - theme: { - options: { - light: "Light", - dark: "Dark", - system: "System", - }, - }, - sidebar: { - overview: "Overview", - policies: "Policies", - risk: "Risk Management", - vendors: "Vendors", - integrations: "Integrations", - settings: "Settings", - evidence: "Evidence Tasks", - people: "People", - tests: "Cloud Tests", - }, - sub_pages: { - evidence: { - title: "Evidence", - list: "Evidence List", - overview: "Evidence Overview", - }, - risk: { - overview: "Risk Management", - register: "Risk Register", - risk_overview: "Risk Overview", - risk_comments: "Risk Comments", - tasks: { - task_overview: "Task Overview", - }, - }, - policies: { - all: "All Policies", - editor: "Policy Editor", - policy_details: "Policy Details", - }, - people: { - all: "People", - employee_details: "Employee Details", - }, - settings: { - members: "Team Members", - }, - frameworks: { - overview: "Frameworks", - }, - }, - auth: { - title: "Automate SOC 2, ISO 27001 and GDPR compliance with AI.", - description: - "Create a free account or log in with an existing account to continue.", - options: "More options", - google: "Continue with Google", - email: { - description: "Enter your email address to continue.", - placeholder: "Enter email address", - button: "Continue with email", - magic_link_sent: "Magic link sent", - magic_link_description: "Check your inbox for a magic link.", - magic_link_try_again: "Try again.", - success: "Email sent - check your inbox!", - error: "Error sending email - try again?", - }, - terms: - "By clicking continue, you acknowledge that you have read and agree to the Terms of Service and Privacy Policy.", - }, - onboarding: { - title: "Create an organization", - setup: "Setup", - description: "Tell us a bit about your organization.", - fields: { - fullName: { - label: "Your Name", - placeholder: "Your full name", - }, - name: { - label: "Organization Name", - placeholder: "Your organization name", - }, - subdomain: { - label: "Subdomain", - placeholder: "example", - }, - website: { - label: "Website", - placeholder: "Your organization website", - }, - }, - success: "Thanks, you're all set!", - error: "Something went wrong, please try again.", - check_availability: "Checking availability", - available: "Available", - unavailable: "Unavailable", - }, - overview: { - title: "Overview", - framework_chart: { - title: "Framework Progress", - }, - requirement_chart: { - title: "Compliance Status", - }, - }, - policies: { - dashboard: { - title: "Dashboard", - all: "All Policies", - policy_status: "Policy by Status", - policies_by_assignee: "Policies by Assignee", - policies_by_framework: "Policies by Framework", - sub_pages: { - overview: "Overview", - edit_policy: "Edit Policy", - }, - }, - overview: { - title: "Policy Overview", - form: { - update_policy: "Update Policy", - update_policy_description: "Update the policy title or description.", - update_policy_success: "Policy updated successfully", - update_policy_error: "Failed to update policy", - update_policy_title: "Policy Name", - review_frequency: "Review Frequency", - review_frequency_placeholder: "Select a review frequency", - review_date: "Review Date", - review_date_placeholder: "Select a review date", - required_to_sign: "Required to be signed by employees", - signature_required: "Require employees signature", - signature_not_required: "Do not ask employees to sign", - signature_requirement: "Signature Requirement", - signature_requirement_placeholder: "Select signature requirement", - }, - }, - table: { - name: "Policy Name", - statuses: { - draft: "Draft", - published: "Published", - archived: "Archived", - }, - filters: { - owner: { - label: "Assignee", - placeholder: "Filter by assignee", - }, - }, - }, - filters: { - search: "Search policies...", - all: "All Policies", - }, - status: { - draft: "Draft", - published: "Published", - needs_review: "Needs Review", - archived: "Archived", - }, - policies: "policies", - title: "Policies", - create_new: "Create New Policy", - search_placeholder: "Search policies...", - status_filter: "Filter by status", - all_statuses: "All statuses", - no_policies_title: "No policies yet", - no_policies_description: "Get started by creating your first policy", - create_first: "Create first policy", - no_description: "No description provided", - last_updated: "Last updated: {{date}}", - save: "Save", - saving: "Saving...", - saved_success: "Policy saved successfully", - saved_error: "Failed to save policy", - }, - evidence_tasks: { - evidence_tasks: "Evidence Tasks", - overview: "Overview", - }, - risk: { - risks: "risks", - overview: "Overview", - create: "Create New Risk", - vendor: { - title: "Vendor Management", - dashboard: { - title: "Vendor Dashboard", - overview: "Vendor Overview", - vendor_status: "Vendor Status", - vendor_category: "Vendor Categories", - vendors_by_assignee: "Vendors by Assignee", - inherent_risk_description: - "Initial risk level before any controls are applied", - residual_risk_description: - "Remaining risk level after controls are applied", - }, - register: { - title: "Vendor Register", - table: { - name: "Name", - category: "Category", - status: "Status", - owner: "Owner", - }, - }, - assessment: { - title: "Vendor Assessment", - update_success: "Vendor risk assessment updated successfully", - update_error: "Failed to update vendor risk assessment", - inherent_risk: "Inherent Risk", - residual_risk: "Residual Risk", - }, - form: { - vendor_details: "Vendor Details", - vendor_name: "Name", - vendor_name_placeholder: "Enter vendor name", - vendor_website: "Website", - vendor_website_placeholder: "Enter vendor website", - vendor_description: "Description", - vendor_description_placeholder: "Enter vendor description", - vendor_category: "Category", - vendor_category_placeholder: "Select category", - vendor_status: "Status", - vendor_status_placeholder: "Select status", - create_vendor_success: "Vendor created successfully", - create_vendor_error: "Failed to create vendor", - update_vendor: "Update Vendor", - update_vendor_success: "Vendor updated successfully", - update_vendor_error: "Failed to update vendor", - add_comment: "Add Comment", - }, - table: { - name: "Name", - category: "Category", - status: "Status", - owner: "Owner", - }, - filters: { - search_placeholder: "Search vendors...", - status_placeholder: "Filter by status", - category_placeholder: "Filter by category", - owner_placeholder: "Filter by owner", - }, - empty_states: { - no_vendors: { - title: "No vendors yet", - description: "Get started by creating your first vendor", - }, - no_results: { - title: "No results found", - description: "No vendors match your search", - description_with_filters: "Try adjusting your filters", - }, - }, - actions: { - create: "Create Vendor", - }, - status: { - not_assessed: "Not Assessed", - in_progress: "In Progress", - assessed: "Assessed", - }, - category: { - cloud: "Cloud", - infrastructure: "Infrastructure", - software_as_a_service: "Software as a Service", - finance: "Finance", - marketing: "Marketing", - sales: "Sales", - hr: "HR", - other: "Other", - }, - risk_level: { - low: "Low Risk", - medium: "Medium Risk", - high: "High Risk", - unknown: "Unknown Risk", - }, - }, - dashboard: { - title: "Dashboard", - overview: "Risk Overview", - risk_status: "Risk Status", - risks_by_department: "Risks by Department", - risks_by_assignee: "Risks by Assignee", - inherent_risk_description: - "Inherent risk is calculated as likelihood * impact. Calculated before any controls are applied.", - residual_risk_description: - "Residual risk is calculated as likelihood * impact. This is the risk level after controls are applied.", - risk_assessment_description: "Compare inherent and residual risk levels", - }, - register: { - title: "Risk Register", - table: { - risk: "Risk", - }, - empty: { - no_risks: { - title: "Create a risk to get started", - description: - "Track and score risks, create and assign mitigation tasks for your team, and manage your risk register all in one simple interface.", - }, - create_risk: "Create a risk", - }, - }, - metrics: { - probability: "Probability", - impact: "Impact", - inherentRisk: "Inherent Risk", - residualRisk: "Residual Risk", - }, - form: { - update_inherent_risk: "Save Inherent Risk", - update_inherent_risk_description: - "Update the inherent risk of the risk. This is the risk level before any controls are applied.", - update_inherent_risk_success: "Inherent risk updated successfully", - update_inherent_risk_error: "Failed to update inherent risk", - update_residual_risk: "Save Residual Risk", - update_residual_risk_description: - "Update the residual risk of the risk. This is the risk level after controls are applied.", - update_residual_risk_success: "Residual risk updated successfully", - update_residual_risk_error: "Failed to update residual risk", - update_risk: "Update Risk", - update_risk_description: "Update the risk title or description.", - update_risk_success: "Risk updated successfully", - update_risk_error: "Failed to update risk", - create_risk_success: "Risk created successfully", - create_risk_error: "Failed to create risk", - risk_details: "Risk Details", - risk_title: "Risk Title", - risk_title_description: "Enter a name for the risk", - risk_description: "Description", - risk_description_description: "Enter a description for the risk", - risk_category: "Category", - risk_category_placeholder: "Select a category", - risk_department: "Department", - risk_department_placeholder: "Select a department", - risk_status: "Risk Status", - risk_status_placeholder: "Select a risk status", - }, - tasks: { - title: "Tasks", - attachments: "Attachments", - overview: "Task Overview", - form: { - title: "Task Details", - task_title: "Task Title", - status: "Task Status", - status_placeholder: "Select a task status", - task_title_description: "Enter a name for the task", - description: "Description", - description_description: "Enter a description for the task", - due_date: "Due Date", - due_date_description: "Select the due date for the task", - success: "Task created successfully", - error: "Failed to create task", - }, - sheet: { - title: "Create Task", - update: "Update Task", - update_description: "Update the task title or description.", - }, - empty: { - description_create: - "Create a mitigation task for this risk, add a treatment plan, and assign it to a team member.", - }, - }, - }, - people: { - title: "People", - details: { - taskProgress: "Task Progress", - tasks: "Tasks", - noTasks: "No tasks assigned yet", - }, - description: "Manage your team members and their roles.", - filters: { - search: "Search people...", - role: "Filter by role", - }, - actions: { - invite: "Add Employee", - clear: "Clear filters", - }, - table: { - name: "Name", - email: "Email", - department: "Department", - externalId: "External ID", - }, - empty: { - no_employees: { - title: "No employees yet", - description: "Get started by inviting your first team member.", - }, - no_results: { - title: "No results found", - description: "No employees match your search", - description_with_filters: "Try adjusting your filters", - }, - }, - invite: { - title: "Add Employee", - description: "Add an employee to your organization.", - email: { - label: "Email address", - placeholder: "Enter email address", - }, - role: { - label: "Role", - placeholder: "Select a role", - }, - name: { - label: "Name", - placeholder: "Enter name", - }, - department: { - label: "Department", - placeholder: "Select a department", - }, - submit: "Add Employee", - success: "Employee added successfully", - error: "Failed to add employee", - }, - }, - settings: { - general: { - title: "General", - org_name: "Organization name", - org_name_description: - "This is your organizations visible name. You should use the legal name of your organization.", - org_name_tip: "Please use 32 characters at maximum.", - org_website: "Organization Website", - org_website_description: - "This is your organization's official website URL. Make sure to include the full URL with https://.", - org_website_tip: "Please enter a valid URL including https://", - org_website_error: "Error updating organization website", - org_website_updated: "Organization website updated", - org_delete: "Delete organization", - org_delete_description: - "Permanently remove your organization and all of its contents from the Comp AI platform. This action is not reversible - please continue with caution.", - org_delete_alert_title: "Are you absolutely sure?", - org_delete_alert_description: - "This action cannot be undone. This will permanently delete your organization and remove your data from our servers.", - org_delete_error: "Error deleting organization", - org_delete_success: "Organization deleted", - org_name_updated: "Organization name updated", - org_name_error: "Error updating organization name", - save_button: "Save", - delete_button: "Delete", - delete_confirm: "DELETE", - delete_confirm_tip: "Type DELETE to confirm.", - cancel_button: "Cancel", - }, - members: { - title: "Members", - }, - api_keys: { - title: "API Keys", - description: - "Manage API keys for programmatic access to your organization's data.", - list_title: "API Keys", - list_description: - "API keys allow secure access to your organization's data via our API.", - create: "Create API Key", - create_title: "Create API Key", - create_description: - "Create a new API key for programmatic access to your organization's data.", - created_title: "API Key Created", - created_description: - "Your API key has been created. Make sure to copy it now as you won't be able to see it again.", - name: "Name", - name_label: "Name", - name_placeholder: "Enter a name for this API key", - expiration: "Expiration", - expiration_placeholder: "Select expiration", - expires_label: "Expires", - expires_placeholder: "Select expiration", - expires_30days: "30 days", - expires_90days: "90 days", - expires_1year: "1 year", - expires_never: "Never", - thirty_days: "30 days", - ninety_days: "90 days", - one_year: "1 year", - your_key: "Your API Key", - api_key: "API Key", - save_warning: - "This key will only be shown once. Make sure to copy it now.", - copied: "API key copied to clipboard", - close_confirm: - "Are you sure you want to close? You won't be able to see this API key again.", - revoke_confirm: - "Are you sure you want to revoke this API key? This action cannot be undone.", - revoke_title: "Revoke API Key", - revoke: "Revoke", - created: "Created", - expires: "Expires", - last_used: "Last Used", - actions: "Actions", - never: "Never", - never_used: "Never used", - no_keys: "No API keys found. Create one to get started.", - security_note: - "API keys provide full access to your organization's data. Keep them secure and rotate them regularly.", - fetch_error: "Failed to fetch API keys", - create_error: "Failed to create API key", - revoked_success: "API key revoked successfully", - revoked_error: "Failed to revoke API key", - done: "Done", - }, - billing: { - title: "Billing", - }, - }, - tests: { - name: "Cloud Tests", - title: "Cloud Tests", - actions: { - create: "Add Cloud Test", - clear: "Clear filters", - refresh: "Refresh", - }, - empty: { - no_tests: { - title: "No cloud tests yet", - description: "Get started by creating your first cloud test.", - }, - no_results: { - title: "No results found", - description: "No tests match your search", - description_with_filters: "Try adjusting your filters", - }, - }, - filters: { - search: "Search tests...", - role: "Filter by vendor", - }, - register: { - title: "Add Cloud Test", - description: "Configure a new cloud compliance test.", - submit: "Create Test", - success: "Test created successfully", - invalid_json: "Invalid JSON configuration provided", - - title_field: { - label: "Test Title", - placeholder: "Enter test title" - }, - description_field: { - label: "Description", - placeholder: "Enter test description" - }, - provider: { - label: "Cloud Provider", - placeholder: "Select cloud provider" - }, - config: { - label: "Test Configuration", - placeholder: "Enter JSON configuration for the test" - }, - auth_config: { - label: "Authentication Configuration", - placeholder: "Enter JSON authentication configuration" - } - }, - table: { - title: "Title", - provider: "Provider", - status: "Status", - severity: "Severity", - result: "Result", - createdAt: "Created At", - assignedUser: "Assigned User", - assignedUserEmpty: "Not Assigned", - no_results: "No results found", - }, - }, - user_menu: { - theme: "Theme", - language: "Language", - sign_out: "Sign out", - account: "Account", - support: "Support", - settings: "Settings", - teams: "Teams", - }, - frameworks: { - title: "Frameworks", - overview: { - error: "Failed to load frameworks", - loading: "Loading frameworks...", - empty: { - title: "No frameworks selected", - description: - "Select frameworks to get started with your compliance journey", - }, - progress: { - title: "Framework Progress", - empty: { - title: "No frameworks yet", - description: - "Get started by adding a compliance framework to track your progress", - action: "Add Framework", - }, - }, - grid: { - welcome: { - title: "Welcome to Comp AI", - description: - "Get started by selecting the compliance frameworks you would like to implement. We'll help you manage and track your compliance journey across multiple standards.", - action: "Get Started", - }, - title: "Select Frameworks", - version: "Version", - actions: { - clear: "Clear", - confirm: "Confirm Selection", - }, - }, - }, - controls: { - title: "Controls", - description: "Review and manage compliance controls", - table: { - status: "Status", - control: "Control", - artifacts: "Artifacts", - actions: "Actions", - }, - statuses: { - completed: "Completed", - in_progress: "In Progress", - not_started: "Not Started", - }, - }, - }, - vendor: { - title: "Dashboard", - register_title: "Vendor Management", - dashboard: { - title: "Dashboard", - overview: "Vendor Overview", - vendor_status: "Vendor Status", - vendor_category: "Vendor Categories", - vendors_by_assignee: "Vendors by Assignee", - inherent_risk_description: - "Initial risk level before any controls are applied", - residual_risk_description: - "Remaining risk level after controls are applied", - }, - register: { - title: "Vendor Register", - table: { - name: "Name", - category: "Category", - status: "Status", - owner: "Owner", - }, - }, - category: { - cloud: "Cloud", - infrastructure: "Infrastructure", - software_as_a_service: "SaaS", - finance: "Finance", - marketing: "Marketing", - sales: "Sales", - hr: "HR", - other: "Other", - }, - vendors: "vendors", - form: { - vendor_details: "Vendor Details", - vendor_name: "Name", - vendor_name_placeholder: "Enter vendor name", - vendor_website: "Website", - vendor_website_placeholder: "Enter vendor website", - vendor_description: "Description", - vendor_description_placeholder: "Enter vendor description", - vendor_category: "Category", - vendor_category_placeholder: "Select category", - vendor_status: "Status", - vendor_status_placeholder: "Select status", - create_vendor_success: "Vendor created successfully", - create_vendor_error: "Failed to create vendor", - update_vendor_success: "Vendor updated successfully", - update_vendor_error: "Failed to update vendor", - contacts: "Vendor Contacts", - contact_name: "Contact Name", - contact_email: "Contact Email", - contact_role: "Contact Role", - add_contact: "Add Contact", - new_contact: "New Contact", - min_one_contact_required: "A vendor must have at least one contact", - }, - empty_states: { - no_vendors: { - title: "No vendors yet", - description: "Get started by creating your first vendor", - }, - no_results: { - title: "No results found", - description: "No vendors match your search", - description_with_filters: "Try adjusting your filters", - }, - }, - }, - errors: { - unexpected: "Something went wrong, please try again", - }, - editor: { - ai: { - thinking: "AI is thinking", - thinking_spinner: "AI is thinking", - edit_or_generate: "Edit or generate...", - tell_ai_what_to_do_next: "Tell AI what to do next", - request_limit_reached: "You have reached your request limit for the day.", - }, - ai_selector: { - improve: "Improve writing", - fix: "Fix grammar", - shorter: "Make shorter", - longer: "Make longer", - continue: "Continue writing", - replace: "Replace selection", - insert: "Insert below", - discard: "Discard", - }, - }, - evidence: { - title: "Evidence", - list: "All Evidence", - overview: "Evidence Overview", - edit: "Edit Evidence", - dashboard: { - layout: "Dashboard", - layout_back_button: "Back", - title: "Evidence Dashboard", - by_department: "By Department", - by_assignee: "By Assignee", - by_framework: "By Framework", - }, - items: "items", - status: { - up_to_date: "Up to Date", - needs_review: "Needs Review", - draft: "Draft", - empty: "Empty", - }, - departments: { - none: "Uncategorized", - admin: "Administration", - gov: "Governance", - hr: "Human Resources", - it: "Information Technology", - itsm: "IT Service Management", - qms: "Quality Management", - }, - details: { - review_section: "Review Information", - content: "Evidence Content", - }, - }, + language: { + title: "Languages", + description: "Change the language used in the user interface.", + placeholder: "Select language", + }, + languages: { + en: "English", + es: "Spanish", + fr: "French", + no: "Norwegian", + pt: "Portuguese", + }, + common: { + frequency: { + daily: "Daily", + weekly: "Weekly", + monthly: "Monthly", + quarterly: "Quarterly", + yearly: "Yearly", + }, + notifications: { + inbox: "Inbox", + archive: "Archive", + archive_all: "Archive all", + no_notifications: "No new notifications", + }, + actions: { + save: "Save", + edit: "Edit", + delete: "Delete", + cancel: "Cancel", + clear: "Clear", + create: "Create", + addNew: "Add New", + send: "Send", + return: "Return", + success: "Success", + error: "Error", + next: "Next", + complete: "Complete", + }, + assignee: { + label: "Assignee", + placeholder: "Select assignee", + }, + date: { + pick: "Pick a date", + due_date: "Due Date", + }, + status: { + open: "Open", + pending: "Pending", + closed: "Closed", + archived: "Archived", + compliant: "Compliant", + non_compliant: "Non Compliant", + not_started: "Not Started", + in_progress: "In Progress", + published: "Published", + needs_review: "Needs Review", + draft: "Draft", + not_assessed: "Not Assessed", + assessed: "Assessed", + active: "Active", + inactive: "Inactive", + title: "Status", + }, + filters: { + clear: "Clear filters", + search: "Search...", + status: "Status", + department: "Department", + owner: { + label: "Assignee", + placeholder: "Filter by assignee", + }, + }, + table: { + title: "Title", + status: "Status", + assigned_to: "Assigned To", + due_date: "Due Date", + last_updated: "Last Updated", + no_results: "No results found", + }, + empty_states: { + no_results: { + title: "No results found", + title_tasks: "No tasks found", + title_risks: "No risks found", + description: "Try another search, or adjusting the filters", + description_filters: "Try another search, or adjusting the filters", + description_no_tasks: "Create a task to get started", + description_no_risks: "Create a risk to get started", + }, + no_items: { + title: "No items found", + description: "Try adjusting your search or filters", + }, + }, + pagination: { + of: "of", + items_per_page: "Items per page", + rows_per_page: "Rows per page", + page_x_of_y: "Page {{current}} of {{total}}", + go_to_first_page: "Go to first page", + go_to_previous_page: "Go to previous page", + go_to_next_page: "Go to next page", + go_to_last_page: "Go to last page", + }, + comments: { + title: "Comments", + description: "Add a comment using the form below.", + add: "New Comment", + new: "New Comment", + save: "Save Comment", + success: "Comment added successfully", + error: "Failed to add comment", + placeholder: "Write your comment here...", + empty: { + title: "No comments yet", + description: "Be the first to add a comment", + }, + }, + upload: { + fileUpload: { + uploadingText: "Uploading...", + uploadingFile: "Uploading file...", + dropFileHere: "Drop file here", + dropFileHereAlt: "Drop file here", + releaseToUpload: "Release to upload", + addFiles: "Add Files", + uploadAdditionalEvidence: "Upload a file or document", + dragDropOrClick: "Drag and drop or click to browse", + dragDropOrClickToSelect: "Drag and drop or click to select file", + maxFileSize: "Max file size: {size}MB", + }, + fileUrl: { + additionalLinks: "Additional Links", + add: "Add", + linksAdded: "{count} link{s} added", + enterUrl: "Enter URL", + addAnotherLink: "Add Another Link", + saveLinks: "Save Links", + urlBadge: "URL", + copyLink: "Copy Link", + openLink: "Open Link", + deleteLink: "Delete Link", + }, + fileCard: { + preview: "Preview", + filePreview: "File Preview: {fileName}", + previewNotAvailable: "Preview not available for this file type", + openFile: "Open File", + deleteFile: "Delete File", + deleteFileConfirmTitle: "Delete File", + deleteFileConfirmDescription: + "This action cannot be undone. The file will be permanently deleted.", + }, + fileSection: { + filesUploaded: "{count} files uploaded", + }, + }, + attachments: { + title: "Attachments", + description: "Add a file by clicking 'Add Attachment'.", + upload: "Upload attachment", + upload_description: + "Upload an attachment or add a link to an external resource.", + drop: "Drop the files here", + drop_description: + "Drop files here or click to choose files from your device.", + drop_files_description: "Files can be up to ", + empty: { + title: "No attachments", + description: "Add a file by clicking 'Add Attachment'.", + }, + toasts: { + error: "Something went wrong, please try again.", + error_uploading_files: "Cannot upload more than 1 file at a time", + error_uploading_files_multiple: "Cannot upload more than 10 files", + error_no_files_selected: "No files selected", + error_file_rejected: "File {file} was rejected", + error_failed_to_upload_files: "Failed to upload files", + error_failed_to_upload_files_multiple: "Failed to upload files", + error_failed_to_upload_files_single: "Failed to upload file", + success_uploading_files: "Files uploaded successfully", + success_uploading_files_multiple: "Files uploaded successfully", + success_uploading_files_single: "File uploaded successfully", + success_uploading_files_target: "Files uploaded", + uploading_files: "Uploading {target}...", + remove_file: "Remove file", + }, + }, + edit: "Edit", + errors: { + unexpected_error: "An unexpected error occurred", + }, + description: "Description", + last_updated: "Last Updated", + }, + header: { + discord: { + button: "Join us on Discord", + }, + feedback: { + button: "Feedback", + title: "Thank you for your feedback!", + description: "We will be back with you as soon as possible", + placeholder: "Ideas to improve this page or issues you are experiencing.", + success: "Thank you for your feedback!", + error: "Error sending feedback - try again?", + send: "Send Feedback", + }, + }, + not_found: { + title: "404 - Page not found", + description: "The page you are looking for does not exist.", + return: "Return to dashboard", + }, + theme: { + options: { + light: "Light", + dark: "Dark", + system: "System", + }, + }, + sidebar: { + overview: "Overview", + policies: "Policies", + risk: "Risk Management", + vendors: "Vendors", + integrations: "Integrations", + settings: "Settings", + evidence: "Evidence Tasks", + people: "People", + tests: "Cloud Tests", + }, + sub_pages: { + evidence: { + title: "Evidence", + list: "Evidence List", + overview: "Evidence Overview", + }, + risk: { + overview: "Risk Management", + register: "Risk Register", + risk_overview: "Risk Overview", + risk_comments: "Risk Comments", + tasks: { + task_overview: "Task Overview", + }, + }, + policies: { + all: "All Policies", + editor: "Policy Editor", + policy_details: "Policy Details", + }, + people: { + all: "People", + employee_details: "Employee Details", + }, + settings: { + members: "Team Members", + }, + frameworks: { + overview: "Frameworks", + }, + }, + auth: { + title: "Automate SOC 2, ISO 27001 and GDPR compliance with AI.", + description: + "Create a free account or log in with an existing account to continue.", + options: "More options", + google: "Continue with Google", + email: { + description: "Enter your email address to continue.", + placeholder: "Enter email address", + button: "Continue with email", + magic_link_sent: "Magic link sent", + magic_link_description: "Check your inbox for a magic link.", + magic_link_try_again: "Try again.", + success: "Email sent - check your inbox!", + error: "Error sending email - try again?", + }, + terms: + "By clicking continue, you acknowledge that you have read and agree to the Terms of Service and Privacy Policy.", + }, + onboarding: { + title: "Create an organization", + setup: "Setup", + description: "Tell us a bit about your organization.", + fields: { + fullName: { + label: "Your Name", + placeholder: "Your full name", + }, + name: { + label: "Organization Name", + placeholder: "Your organization name", + }, + subdomain: { + label: "Subdomain", + placeholder: "example", + }, + website: { + label: "Website", + placeholder: "Your organization website", + }, + }, + success: "Thanks, you're all set!", + error: "Something went wrong, please try again.", + check_availability: "Checking availability", + available: "Available", + unavailable: "Unavailable", + }, + overview: { + title: "Overview", + framework_chart: { + title: "Framework Progress", + }, + requirement_chart: { + title: "Compliance Status", + }, + }, + policies: { + dashboard: { + title: "Dashboard", + all: "All Policies", + policy_status: "Policy by Status", + policies_by_assignee: "Policies by Assignee", + policies_by_framework: "Policies by Framework", + sub_pages: { + overview: "Overview", + edit_policy: "Edit Policy", + }, + }, + overview: { + title: "Policy Overview", + form: { + update_policy: "Update Policy", + update_policy_description: "Update the policy title or description.", + update_policy_success: "Policy updated successfully", + update_policy_error: "Failed to update policy", + update_policy_title: "Policy Name", + review_frequency: "Review Frequency", + review_frequency_placeholder: "Select a review frequency", + review_date: "Review Date", + review_date_placeholder: "Select a review date", + required_to_sign: "Required to be signed by employees", + signature_required: "Require employees signature", + signature_not_required: "Do not ask employees to sign", + signature_requirement: "Signature Requirement", + signature_requirement_placeholder: "Select signature requirement", + }, + }, + table: { + name: "Policy Name", + statuses: { + draft: "Draft", + published: "Published", + archived: "Archived", + }, + filters: { + owner: { + label: "Assignee", + placeholder: "Filter by assignee", + }, + }, + }, + filters: { + search: "Search policies...", + all: "All Policies", + }, + status: { + draft: "Draft", + published: "Published", + needs_review: "Needs Review", + archived: "Archived", + }, + policies: "policies", + title: "Policies", + create_new: "Create New Policy", + search_placeholder: "Search policies...", + status_filter: "Filter by status", + all_statuses: "All statuses", + no_policies_title: "No policies yet", + no_policies_description: "Get started by creating your first policy", + create_first: "Create first policy", + no_description: "No description provided", + last_updated: "Last updated: {{date}}", + save: "Save", + saving: "Saving...", + saved_success: "Policy saved successfully", + saved_error: "Failed to save policy", + }, + evidence_tasks: { + evidence_tasks: "Evidence Tasks", + overview: "Overview", + }, + risk: { + risks: "risks", + overview: "Overview", + create: "Create New Risk", + vendor: { + title: "Vendor Management", + dashboard: { + title: "Vendor Dashboard", + overview: "Vendor Overview", + vendor_status: "Vendor Status", + vendor_category: "Vendor Categories", + vendors_by_assignee: "Vendors by Assignee", + inherent_risk_description: + "Initial risk level before any controls are applied", + residual_risk_description: + "Remaining risk level after controls are applied", + }, + register: { + title: "Vendor Register", + table: { + name: "Name", + category: "Category", + status: "Status", + owner: "Owner", + }, + }, + assessment: { + title: "Vendor Assessment", + update_success: "Vendor risk assessment updated successfully", + update_error: "Failed to update vendor risk assessment", + inherent_risk: "Inherent Risk", + residual_risk: "Residual Risk", + }, + form: { + vendor_details: "Vendor Details", + vendor_name: "Name", + vendor_name_placeholder: "Enter vendor name", + vendor_website: "Website", + vendor_website_placeholder: "Enter vendor website", + vendor_description: "Description", + vendor_description_placeholder: "Enter vendor description", + vendor_category: "Category", + vendor_category_placeholder: "Select category", + vendor_status: "Status", + vendor_status_placeholder: "Select status", + create_vendor_success: "Vendor created successfully", + create_vendor_error: "Failed to create vendor", + update_vendor: "Update Vendor", + update_vendor_success: "Vendor updated successfully", + update_vendor_error: "Failed to update vendor", + add_comment: "Add Comment", + }, + table: { + name: "Name", + category: "Category", + status: "Status", + owner: "Owner", + }, + filters: { + search_placeholder: "Search vendors...", + status_placeholder: "Filter by status", + category_placeholder: "Filter by category", + owner_placeholder: "Filter by owner", + }, + empty_states: { + no_vendors: { + title: "No vendors yet", + description: "Get started by creating your first vendor", + }, + no_results: { + title: "No results found", + description: "No vendors match your search", + description_with_filters: "Try adjusting your filters", + }, + }, + actions: { + create: "Create Vendor", + }, + status: { + not_assessed: "Not Assessed", + in_progress: "In Progress", + assessed: "Assessed", + }, + category: { + cloud: "Cloud", + infrastructure: "Infrastructure", + software_as_a_service: "Software as a Service", + finance: "Finance", + marketing: "Marketing", + sales: "Sales", + hr: "HR", + other: "Other", + }, + risk_level: { + low: "Low Risk", + medium: "Medium Risk", + high: "High Risk", + unknown: "Unknown Risk", + }, + }, + dashboard: { + title: "Dashboard", + overview: "Risk Overview", + risk_status: "Risk Status", + risks_by_department: "Risks by Department", + risks_by_assignee: "Risks by Assignee", + inherent_risk_description: + "Inherent risk is calculated as likelihood * impact. Calculated before any controls are applied.", + residual_risk_description: + "Residual risk is calculated as likelihood * impact. This is the risk level after controls are applied.", + risk_assessment_description: "Compare inherent and residual risk levels", + }, + register: { + title: "Risk Register", + table: { + risk: "Risk", + }, + empty: { + no_risks: { + title: "Create a risk to get started", + description: + "Track and score risks, create and assign mitigation tasks for your team, and manage your risk register all in one simple interface.", + }, + create_risk: "Create a risk", + }, + }, + metrics: { + probability: "Probability", + impact: "Impact", + inherentRisk: "Inherent Risk", + residualRisk: "Residual Risk", + }, + form: { + update_inherent_risk: "Save Inherent Risk", + update_inherent_risk_description: + "Update the inherent risk of the risk. This is the risk level before any controls are applied.", + update_inherent_risk_success: "Inherent risk updated successfully", + update_inherent_risk_error: "Failed to update inherent risk", + update_residual_risk: "Save Residual Risk", + update_residual_risk_description: + "Update the residual risk of the risk. This is the risk level after controls are applied.", + update_residual_risk_success: "Residual risk updated successfully", + update_residual_risk_error: "Failed to update residual risk", + update_risk: "Update Risk", + update_risk_description: "Update the risk title or description.", + update_risk_success: "Risk updated successfully", + update_risk_error: "Failed to update risk", + create_risk_success: "Risk created successfully", + create_risk_error: "Failed to create risk", + risk_details: "Risk Details", + risk_title: "Risk Title", + risk_title_description: "Enter a name for the risk", + risk_description: "Description", + risk_description_description: "Enter a description for the risk", + risk_category: "Category", + risk_category_placeholder: "Select a category", + risk_department: "Department", + risk_department_placeholder: "Select a department", + risk_status: "Risk Status", + risk_status_placeholder: "Select a risk status", + }, + tasks: { + title: "Tasks", + attachments: "Attachments", + overview: "Task Overview", + form: { + title: "Task Details", + task_title: "Task Title", + status: "Task Status", + status_placeholder: "Select a task status", + task_title_description: "Enter a name for the task", + description: "Description", + description_description: "Enter a description for the task", + due_date: "Due Date", + due_date_description: "Select the due date for the task", + success: "Task created successfully", + error: "Failed to create task", + }, + sheet: { + title: "Create Task", + update: "Update Task", + update_description: "Update the task title or description.", + }, + empty: { + description_create: + "Create a mitigation task for this risk, add a treatment plan, and assign it to a team member.", + }, + }, + }, + people: { + title: "People", + details: { + taskProgress: "Task Progress", + tasks: "Tasks", + noTasks: "No tasks assigned yet", + }, + description: "Manage your team members and their roles.", + filters: { + search: "Search people...", + role: "Filter by role", + }, + actions: { + invite: "Add Employee", + clear: "Clear filters", + }, + table: { + name: "Name", + email: "Email", + department: "Department", + externalId: "External ID", + }, + empty: { + no_employees: { + title: "No employees yet", + description: "Get started by inviting your first team member.", + }, + no_results: { + title: "No results found", + description: "No employees match your search", + description_with_filters: "Try adjusting your filters", + }, + }, + invite: { + title: "Add Employee", + description: "Add an employee to your organization.", + email: { + label: "Email address", + placeholder: "Enter email address", + }, + role: { + label: "Role", + placeholder: "Select a role", + }, + name: { + label: "Name", + placeholder: "Enter name", + }, + department: { + label: "Department", + placeholder: "Select a department", + }, + submit: "Add Employee", + success: "Employee added successfully", + error: "Failed to add employee", + }, + }, + settings: { + general: { + title: "General", + org_name: "Organization name", + org_name_description: + "This is your organizations visible name. You should use the legal name of your organization.", + org_name_tip: "Please use 32 characters at maximum.", + org_website: "Organization Website", + org_website_description: + "This is your organization's official website URL. Make sure to include the full URL with https://.", + org_website_tip: "Please enter a valid URL including https://", + org_website_error: "Error updating organization website", + org_website_updated: "Organization website updated", + org_delete: "Delete organization", + org_delete_description: + "Permanently remove your organization and all of its contents from the Comp AI platform. This action is not reversible - please continue with caution.", + org_delete_alert_title: "Are you absolutely sure?", + org_delete_alert_description: + "This action cannot be undone. This will permanently delete your organization and remove your data from our servers.", + org_delete_error: "Error deleting organization", + org_delete_success: "Organization deleted", + org_name_updated: "Organization name updated", + org_name_error: "Error updating organization name", + save_button: "Save", + delete_button: "Delete", + delete_confirm: "DELETE", + delete_confirm_tip: "Type DELETE to confirm.", + cancel_button: "Cancel", + }, + members: { + title: "Members", + }, + api_keys: { + title: "API Keys", + description: + "Manage API keys for programmatic access to your organization's data.", + list_title: "API Keys", + list_description: + "API keys allow secure access to your organization's data via our API.", + create: "Create API Key", + create_title: "Create API Key", + create_description: + "Create a new API key for programmatic access to your organization's data.", + created_title: "API Key Created", + created_description: + "Your API key has been created. Make sure to copy it now as you won't be able to see it again.", + name: "Name", + name_label: "Name", + name_placeholder: "Enter a name for this API key", + expiration: "Expiration", + expiration_placeholder: "Select expiration", + expires_label: "Expires", + expires_placeholder: "Select expiration", + expires_30days: "30 days", + expires_90days: "90 days", + expires_1year: "1 year", + expires_never: "Never", + thirty_days: "30 days", + ninety_days: "90 days", + one_year: "1 year", + your_key: "Your API Key", + api_key: "API Key", + save_warning: + "This key will only be shown once. Make sure to copy it now.", + copied: "API key copied to clipboard", + close_confirm: + "Are you sure you want to close? You won't be able to see this API key again.", + revoke_confirm: + "Are you sure you want to revoke this API key? This action cannot be undone.", + revoke_title: "Revoke API Key", + revoke: "Revoke", + created: "Created", + expires: "Expires", + last_used: "Last Used", + actions: "Actions", + never: "Never", + never_used: "Never used", + no_keys: "No API keys found. Create one to get started.", + security_note: + "API keys provide full access to your organization's data. Keep them secure and rotate them regularly.", + fetch_error: "Failed to fetch API keys", + create_error: "Failed to create API key", + revoked_success: "API key revoked successfully", + revoked_error: "Failed to revoke API key", + done: "Done", + }, + billing: { + title: "Billing", + }, + }, + tests: { + name: "Cloud Tests", + title: "Cloud Tests", + actions: { + create: "Add Cloud Test", + clear: "Clear filters", + refresh: "Refresh", + }, + empty: { + no_tests: { + title: "No cloud tests yet", + description: "Get started by creating your first cloud test.", + }, + no_results: { + title: "No results found", + description: "No tests match your search", + description_with_filters: "Try adjusting your filters", + }, + }, + filters: { + search: "Search tests...", + role: "Filter by vendor", + }, + register: { + title: "Add Cloud Test", + description: "Configure a new cloud compliance test.", + submit: "Create Test", + success: "Test created successfully", + invalid_json: "Invalid JSON configuration provided", + + title_field: { + label: "Test Title", + placeholder: "Enter test title", + }, + description_field: { + label: "Description", + placeholder: "Enter test description", + }, + provider: { + label: "Cloud Provider", + placeholder: "Select cloud provider", + }, + config: { + label: "Test Configuration", + placeholder: "Enter JSON configuration for the test", + }, + auth_config: { + label: "Authentication Configuration", + placeholder: "Enter JSON authentication configuration", + }, + }, + table: { + title: "Title", + provider: "Provider", + status: "Status", + severity: "Severity", + result: "Result", + createdAt: "Created At", + assignedUser: "Assigned User", + assignedUserEmpty: "Not Assigned", + no_results: "No results found", + }, + }, + user_menu: { + theme: "Theme", + language: "Language", + sign_out: "Sign out", + account: "Account", + support: "Support", + settings: "Settings", + teams: "Teams", + }, + frameworks: { + title: "Frameworks", + overview: { + error: "Failed to load frameworks", + loading: "Loading frameworks...", + empty: { + title: "No frameworks selected", + description: + "Select frameworks to get started with your compliance journey", + }, + progress: { + title: "Framework Progress", + empty: { + title: "No frameworks yet", + description: + "Get started by adding a compliance framework to track your progress", + action: "Add Framework", + }, + }, + grid: { + welcome: { + title: "Welcome to Comp AI", + description: + "Get started by selecting the compliance frameworks you would like to implement. We'll help you manage and track your compliance journey across multiple standards.", + action: "Get Started", + }, + title: "Select Frameworks", + version: "Version", + actions: { + clear: "Clear", + confirm: "Confirm Selection", + }, + }, + }, + controls: { + title: "Controls", + description: "Review and manage compliance controls", + table: { + status: "Status", + control: "Control", + artifacts: "Artifacts", + actions: "Actions", + }, + statuses: { + completed: "Completed", + in_progress: "In Progress", + not_started: "Not Started", + }, + }, + }, + vendor: { + title: "Dashboard", + register_title: "Vendor Management", + dashboard: { + title: "Dashboard", + overview: "Vendor Overview", + vendor_status: "Vendor Status", + vendor_category: "Vendor Categories", + vendors_by_assignee: "Vendors by Assignee", + inherent_risk_description: + "Initial risk level before any controls are applied", + residual_risk_description: + "Remaining risk level after controls are applied", + }, + register: { + title: "Vendor Register", + table: { + name: "Name", + category: "Category", + status: "Status", + owner: "Owner", + }, + }, + category: { + cloud: "Cloud", + infrastructure: "Infrastructure", + software_as_a_service: "SaaS", + finance: "Finance", + marketing: "Marketing", + sales: "Sales", + hr: "HR", + other: "Other", + }, + vendors: "vendors", + form: { + vendor_details: "Vendor Details", + vendor_name: "Name", + vendor_name_placeholder: "Enter vendor name", + vendor_website: "Website", + vendor_website_placeholder: "Enter vendor website", + vendor_description: "Description", + vendor_description_placeholder: "Enter vendor description", + vendor_category: "Category", + vendor_category_placeholder: "Select category", + vendor_status: "Status", + vendor_status_placeholder: "Select status", + create_vendor_success: "Vendor created successfully", + create_vendor_error: "Failed to create vendor", + update_vendor_success: "Vendor updated successfully", + update_vendor_error: "Failed to update vendor", + contacts: "Vendor Contacts", + contact_name: "Contact Name", + contact_email: "Contact Email", + contact_role: "Contact Role", + add_contact: "Add Contact", + new_contact: "New Contact", + min_one_contact_required: "A vendor must have at least one contact", + }, + empty_states: { + no_vendors: { + title: "No vendors yet", + description: "Get started by creating your first vendor", + }, + no_results: { + title: "No results found", + description: "No vendors match your search", + description_with_filters: "Try adjusting your filters", + }, + }, + }, + errors: { + unexpected: "Something went wrong, please try again", + }, + editor: { + ai: { + thinking: "AI is thinking", + thinking_spinner: "AI is thinking", + edit_or_generate: "Edit or generate...", + tell_ai_what_to_do_next: "Tell AI what to do next", + request_limit_reached: "You have reached your request limit for the day.", + }, + ai_selector: { + improve: "Improve writing", + fix: "Fix grammar", + shorter: "Make shorter", + longer: "Make longer", + continue: "Continue writing", + replace: "Replace selection", + insert: "Insert below", + discard: "Discard", + }, + }, + evidence: { + title: "Evidence", + list: "All Evidence", + overview: "Evidence Overview", + edit: "Edit Evidence", + dashboard: { + layout: "Dashboard", + layout_back_button: "Back", + title: "Evidence Dashboard", + by_department: "By Department", + by_assignee: "By Assignee", + by_framework: "By Framework", + }, + items: "items", + status: { + up_to_date: "Up to Date", + needs_review: "Needs Review", + draft: "Draft", + empty: "Empty", + }, + departments: { + none: "Uncategorized", + admin: "Administration", + gov: "Governance", + hr: "Human Resources", + it: "Information Technology", + itsm: "IT Service Management", + qms: "Quality Management", + }, + details: { + review_section: "Review Information", + content: "Evidence Content", + }, + }, } as const; diff --git a/apps/app/src/locales/es.ts b/apps/app/src/locales/es.ts index 4c91997e29..14ec874158 100644 --- a/apps/app/src/locales/es.ts +++ b/apps/app/src/locales/es.ts @@ -157,6 +157,44 @@ export default { monthly: "Mensual", quarterly: "Trimestral", yearly: "Anual" + }, + upload: { + fileUpload: { + uploadingText: "Subiendo...", + uploadingFile: "Subiendo archivo...", + dropFileHere: "Suelta el archivo aquí", + dropFileHereAlt: "Suelta el archivo aquí", + releaseToUpload: "Suelta para subir", + addFiles: "Agregar archivos", + uploadAdditionalEvidence: "Sube un archivo o documento", + dragDropOrClick: "Arrastra y suelta o haz clic para buscar", + dragDropOrClickToSelect: "Arrastra y suelta o haz clic para seleccionar archivo", + maxFileSize: "Tamaño máximo del archivo: {size}MB" + }, + fileUrl: { + additionalLinks: "Enlaces adicionales", + add: "Agregar", + linksAdded: "{count} enlace{s} añadidos", + enterUrl: "Ingresa URL", + addAnotherLink: "Agregar otro enlace", + saveLinks: "Guardar enlaces", + urlBadge: "URL", + copyLink: "Copiar enlace", + openLink: "Abrir enlace", + deleteLink: "Eliminar enlace" + }, + fileCard: { + preview: "Vista previa", + filePreview: "Vista previa del archivo: {fileName}", + previewNotAvailable: "Vista previa no disponible para este tipo de archivo", + openFile: "Abrir archivo", + deleteFile: "Eliminar archivo", + deleteFileConfirmTitle: "Eliminar archivo", + deleteFileConfirmDescription: "Esta acción no se puede deshacer. El archivo será eliminado permanentemente." + }, + fileSection: { + filesUploaded: "{count} archivos subidos" + } } }, header: { diff --git a/apps/app/src/locales/fr.ts b/apps/app/src/locales/fr.ts index ddb807c6aa..891e7609b2 100644 --- a/apps/app/src/locales/fr.ts +++ b/apps/app/src/locales/fr.ts @@ -157,6 +157,44 @@ export default { monthly: "Mensuel", quarterly: "Trimestriel", yearly: "Annuel" + }, + upload: { + fileUpload: { + uploadingText: "Téléchargement...", + uploadingFile: "Téléchargement du fichier...", + dropFileHere: "Déposez le fichier ici", + dropFileHereAlt: "Déposez le fichier ici", + releaseToUpload: "Relâchez pour télécharger", + addFiles: "Ajouter des fichiers", + uploadAdditionalEvidence: "Téléchargez un fichier ou un document", + dragDropOrClick: "Faites glisser et déposez ou cliquez pour parcourir", + dragDropOrClickToSelect: "Faites glisser et déposez ou cliquez pour sélectionner le fichier", + maxFileSize: "Taille maximale du fichier : {size} Mo" + }, + fileUrl: { + additionalLinks: "Liens supplémentaires", + add: "Ajouter", + linksAdded: "{count} lien{s} ajouté{s}", + enterUrl: "Entrez l'URL", + addAnotherLink: "Ajouter un autre lien", + saveLinks: "Enregistrer les liens", + urlBadge: "URL", + copyLink: "Copier le lien", + openLink: "Ouvrir le lien", + deleteLink: "Supprimer le lien" + }, + fileCard: { + preview: "Aperçu", + filePreview: "Aperçu du fichier : {fileName}", + previewNotAvailable: "Aperçu non disponible pour ce type de fichier", + openFile: "Ouvrir le fichier", + deleteFile: "Supprimer le fichier", + deleteFileConfirmTitle: "Supprimer le fichier", + deleteFileConfirmDescription: "Cette action ne peut pas être annulée. Le fichier sera définitivement supprimé." + }, + fileSection: { + filesUploaded: "{count} fichiers téléchargés" + } } }, header: { diff --git a/apps/app/src/locales/no.ts b/apps/app/src/locales/no.ts index d503f13684..12968a1b38 100644 --- a/apps/app/src/locales/no.ts +++ b/apps/app/src/locales/no.ts @@ -157,6 +157,44 @@ export default { monthly: "Månedlig", quarterly: "Kvartalsvis", yearly: "Årlig" + }, + upload: { + fileUpload: { + uploadingText: "Laster opp...", + uploadingFile: "Laster opp fil...", + dropFileHere: "Slipp fil her", + dropFileHereAlt: "Slipp fil her", + releaseToUpload: "Slipp for å laste opp", + addFiles: "Legg til filer", + uploadAdditionalEvidence: "Last opp en fil eller dokument", + dragDropOrClick: "Dra og slipp eller klikk for å bla", + dragDropOrClickToSelect: "Dra og slipp eller klikk for å velge fil", + maxFileSize: "Maks filstørrelse: {size}MB" + }, + fileUrl: { + additionalLinks: "Ytterligere lenker", + add: "Legg til", + linksAdded: "{count} lenke{S} lagt til", + enterUrl: "Skriv inn URL", + addAnotherLink: "Legg til en annen lenke", + saveLinks: "Lagre lenker", + urlBadge: "URL", + copyLink: "Kopier lenke", + openLink: "Åpne lenke", + deleteLink: "Slett lenke" + }, + fileCard: { + preview: "Forhåndsvisning", + filePreview: "Filforhåndsvisning: {fileName}", + previewNotAvailable: "Forhåndsvisning ikke tilgjengelig for denne filtypen", + openFile: "Åpne fil", + deleteFile: "Slett fil", + deleteFileConfirmTitle: "Slett fil", + deleteFileConfirmDescription: "Denne handlingen kan ikke angres. Filen vil bli permanent slettet." + }, + fileSection: { + filesUploaded: "{count} filer lastet opp" + } } }, header: { diff --git a/apps/app/src/locales/pt.ts b/apps/app/src/locales/pt.ts index 92e77b56cf..54bf9de6ae 100644 --- a/apps/app/src/locales/pt.ts +++ b/apps/app/src/locales/pt.ts @@ -157,6 +157,44 @@ export default { monthly: "Mensal", quarterly: "Trimestral", yearly: "Anual" + }, + upload: { + fileUpload: { + uploadingText: "Carregando...", + uploadingFile: "Carregando arquivo...", + dropFileHere: "Solte o arquivo aqui", + dropFileHereAlt: "Solte o arquivo aqui", + releaseToUpload: "Solte para carregar", + addFiles: "Adicionar Arquivos", + uploadAdditionalEvidence: "Carregue um arquivo ou documento", + dragDropOrClick: "Arraste e solte ou clique para navegar", + dragDropOrClickToSelect: "Arraste e solte ou clique para selecionar o arquivo", + maxFileSize: "Tamanho máximo do arquivo: {size}MB" + }, + fileUrl: { + additionalLinks: "Links Adicionais", + add: "Adicionar", + linksAdded: "{count} link{s} adicionado{s}", + enterUrl: "Digite a URL", + addAnotherLink: "Adicionar Outro Link", + saveLinks: "Salvar Links", + urlBadge: "URL", + copyLink: "Copiar Link", + openLink: "Abrir Link", + deleteLink: "Excluir Link" + }, + fileCard: { + preview: "Pré-visualização", + filePreview: "Pré-visualização do Arquivo: {fileName}", + previewNotAvailable: "Pré-visualização não disponível para este tipo de arquivo", + openFile: "Abrir Arquivo", + deleteFile: "Excluir Arquivo", + deleteFileConfirmTitle: "Excluir Arquivo", + deleteFileConfirmDescription: "Esta ação não pode ser desfeita. O arquivo será excluído permanentemente." + }, + fileSection: { + filesUploaded: "{count} arquivos carregados" + } } }, header: { diff --git a/apps/app/src/middleware.ts b/apps/app/src/middleware.ts index 7bd11444bc..f1d96ad4ab 100644 --- a/apps/app/src/middleware.ts +++ b/apps/app/src/middleware.ts @@ -1,49 +1,31 @@ -import { auth as authMiddleware } from "@/auth"; import { createI18nMiddleware } from "next-international/middleware"; import { type NextRequest, NextResponse } from "next/server"; const I18nMiddleware = createI18nMiddleware({ - locales: ["en", "es", "fr", "no", "pt"], - defaultLocale: "en", - urlMappingStrategy: "rewrite", + locales: ["en", "es", "fr", "no", "pt"], + defaultLocale: "en", + urlMappingStrategy: "rewrite", }); export async function middleware(request: NextRequest) { - const session = await authMiddleware(); - const response = await I18nMiddleware(request); - const nextUrl = request.nextUrl; + const response = await I18nMiddleware(request); + const nextUrl = request.nextUrl; - const pathnameLocale = nextUrl.pathname.split("/", 2)?.[1]; + const pathnameLocale = nextUrl.pathname.split("/", 2)?.[1]; - const pathnameWithoutLocale = pathnameLocale - ? nextUrl.pathname.slice(pathnameLocale.length + 1) - : nextUrl.pathname; + const pathnameWithoutLocale = pathnameLocale + ? nextUrl.pathname.slice(pathnameLocale.length + 1) + : nextUrl.pathname; - const newUrl = new URL(pathnameWithoutLocale || "/", request.url); + const newUrl = new URL(pathnameWithoutLocale || "/", request.url); - if (!session && newUrl.pathname !== "/auth") { - const url = new URL("/auth", request.url); + response.headers.set("x-pathname", request.nextUrl.pathname); - return NextResponse.redirect(url); - } - - if ( - session && - newUrl.pathname !== "/setup" && - session.user.onboarded === false - ) { - const url = new URL("/setup", request.url); - - return NextResponse.redirect(url); - } - - response.headers.set("x-pathname", request.nextUrl.pathname); - - return response; + return response; } export const config = { - matcher: [ - "/((?!api|_next/static|_next/image|favicon.ico|monitoring|ingest).*)", - ], + matcher: [ + "/((?!api|_next/static|_next/image|favicon.ico|monitoring|ingest).*)", + ], }; diff --git a/package.json b/package.json index 19a739a51c..503690d5d2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@biomejs/biome": "1.9.4", - "@types/lodash": "^4.17.15", + "@types/lodash": "^4.17.16", "turbo": "^2.4.4", "typescript": "5.7.3" }, @@ -27,7 +27,7 @@ ], "dependencies": { "@aws-sdk/client-s3": "^3.758.0", - "@aws-sdk/client-securityhub": "^3.751.0", + "@aws-sdk/client-securityhub": "^3.758.0", "@manypkg/cli": "^0.23.0", "@nangohq/node": "^0.53.2", "@types/d3": "^7.4.3", diff --git a/packages/db/prisma/migrations/20250306115054_test_mig/migration.sql b/packages/db/prisma/migrations/20250306115054_test_mig/migration.sql new file mode 100644 index 0000000000..1e5a58fb6e --- /dev/null +++ b/packages/db/prisma/migrations/20250306115054_test_mig/migration.sql @@ -0,0 +1,99 @@ +/* + Warnings: + + - You are about to drop the `VendorComment` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorContact` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorMitigationTask` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorRiskAssessment` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorTaskAssignment` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorTaskAttachment` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VendorTaskComments` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Vendors` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "VendorComment" DROP CONSTRAINT "VendorComment_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorComment" DROP CONSTRAINT "VendorComment_ownerId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorComment" DROP CONSTRAINT "VendorComment_vendorId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorContact" DROP CONSTRAINT "VendorContact_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorContact" DROP CONSTRAINT "VendorContact_vendorId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorMitigationTask" DROP CONSTRAINT "VendorMitigationTask_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorMitigationTask" DROP CONSTRAINT "VendorMitigationTask_ownerId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorMitigationTask" DROP CONSTRAINT "VendorMitigationTask_vendorId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorRiskAssessment" DROP CONSTRAINT "VendorRiskAssessment_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorRiskAssessment" DROP CONSTRAINT "VendorRiskAssessment_ownerId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorRiskAssessment" DROP CONSTRAINT "VendorRiskAssessment_vendorId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskAssignment" DROP CONSTRAINT "VendorTaskAssignment_employeeId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskAssignment" DROP CONSTRAINT "VendorTaskAssignment_taskId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskAttachment" DROP CONSTRAINT "VendorTaskAttachment_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskAttachment" DROP CONSTRAINT "VendorTaskAttachment_ownerId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskAttachment" DROP CONSTRAINT "VendorTaskAttachment_vendorMitigationTaskId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskComments" DROP CONSTRAINT "VendorTaskComments_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskComments" DROP CONSTRAINT "VendorTaskComments_ownerId_fkey"; + +-- DropForeignKey +ALTER TABLE "VendorTaskComments" DROP CONSTRAINT "VendorTaskComments_vendorMitigationTaskId_fkey"; + +-- DropForeignKey +ALTER TABLE "Vendors" DROP CONSTRAINT "Vendors_organizationId_fkey"; + +-- DropForeignKey +ALTER TABLE "Vendors" DROP CONSTRAINT "Vendors_ownerId_fkey"; + +-- DropTable +DROP TABLE "VendorComment"; + +-- DropTable +DROP TABLE "VendorContact"; + +-- DropTable +DROP TABLE "VendorMitigationTask"; + +-- DropTable +DROP TABLE "VendorRiskAssessment"; + +-- DropTable +DROP TABLE "VendorTaskAssignment"; + +-- DropTable +DROP TABLE "VendorTaskAttachment"; + +-- DropTable +DROP TABLE "VendorTaskComments"; + +-- DropTable +DROP TABLE "Vendors"; diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma deleted file mode 100644 index 4f093b9b51..0000000000 --- a/packages/db/prisma/schema.prisma +++ /dev/null @@ -1,1079 +0,0 @@ -generator client { - provider = "prisma-client-js" - previewFeatures = ["driverAdapters", "postgresqlExtensions"] - binaryTargets = ["native", "debian-openssl-3.0.x"] -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -model Account { - id String @id @default(cuid()) - userId String - type String - provider String - providerAccountId String - refresh_token String? - access_token String? - expires_at Int? - token_type String? - scope String? - id_token String? - session_state String? - refresh_token_expires_in Int? - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([provider, providerAccountId]) - @@index([userId]) -} - -model Session { - id String @id @default(cuid()) - sessionToken String @unique - userId String - expires DateTime - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) -} - -model User { - id String @id @default(cuid()) - name String? - full_name String? - email String? @unique - role Role @default(member) - onboarded Boolean @default(false) - emailVerified DateTime? - image String? - lastLogin DateTime? - organizationId String? - accounts Account[] - Artifact Artifact[] - AuditLog AuditLog[] - Employee Employee[] - AssignedEvidence OrganizationEvidence[] - organizationMemberships OrganizationMember[] - Risk Risk[] - RiskAttachment RiskAttachment[] - RiskComment RiskComment[] - RiskMitigationTask RiskMitigationTask[] - sessions Session[] - TaskAttachment TaskAttachment[] - TaskComments TaskComments[] - PolicyComments PolicyComments[] - organization Organization? @relation("CurrentOrganization", fields: [organizationId], references: [id]) - VendorComment VendorComment[] - VendorMitigationTask VendorMitigationTask[] - VendorRiskAssessment VendorRiskAssessment[] - VendorTaskAttachment VendorTaskAttachment[] - VendorTaskComments VendorTaskComments[] - Vendors Vendors[] - OrganizationPolicy OrganizationPolicy[] - integrationResults OrganizationIntegrationResults[] - - @@index([email]) - @@index([organizationId]) -} - -model Organization { - id String @id @default(cuid()) - stripeCustomerId String? - name String - subdomain String @unique - website String - tier Tier @default(free) - policiesCreated Boolean @default(false) - frameworkId String? - Artifact Artifact[] - AuditLog AuditLog[] - employees Employee[] - Framework Framework? @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - OrganizationCategory OrganizationCategory[] - OrganizationControl OrganizationControl[] - OrganizationEvidence OrganizationEvidence[] - OrganizationFramework OrganizationFramework[] - OrganizationIntegrations OrganizationIntegrations[] - members OrganizationMember[] - OrganizationPolicy OrganizationPolicy[] - Risk Risk[] - RiskAttachment RiskAttachment[] - RiskComment RiskComment[] - RiskMitigationTask RiskMitigationTask[] - TaskAttachment TaskAttachment[] - TaskComments TaskComments[] - PolicyComments PolicyComments[] - users User[] @relation("CurrentOrganization") - VendorComment VendorComment[] - VendorContact VendorContact[] - VendorMitigationTask VendorMitigationTask[] - VendorRiskAssessment VendorRiskAssessment[] - VendorTaskAttachment VendorTaskAttachment[] - VendorTaskComments VendorTaskComments[] - Vendors Vendors[] - PortalUser PortalUser[] - apiKeys OrganizationApiKey[] - OrganizationIntegrationResults OrganizationIntegrationResults[] - - @@index([stripeCustomerId]) -} - -model OrganizationIntegrations { - id String @id @default(cuid()) - name String @unique - integration_id String - settings Json - user_settings Json - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - results OrganizationIntegrationResults[] - - @@index([organizationId]) -} - -model OrganizationIntegrationResults { - id String @id @default(cuid()) - title String? - status String - label String? // PASS, FAIL, ERROR - resultDetails Json? // Stores detailed test results - completedAt DateTime? @default(now()) - organizationIntegrationId String - organizationId String - assignedUserId String? - - assignedUser User? @relation(fields: [assignedUserId], references: [id], onDelete: Cascade) - organizationIntegration OrganizationIntegrations @relation(fields: [organizationIntegrationId], references: [id], onDelete: Cascade) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - - @@index([assignedUserId]) - @@index([organizationIntegrationId]) - @@index([organizationId]) - @@map("Organization_integration_results") -} - -model AuditLog { - id String @id @default(cuid()) - timestamp DateTime @default(now()) - userId String - organizationId String - data Json - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([organizationId]) -} - -model VerificationToken { - identifier String - token String @unique - expires DateTime - - @@unique([identifier, token]) -} - -model Framework { - id String @id @default(cuid()) - name String @unique - description String? - version String - categories FrameworkCategory[] - organizations Organization[] - OrganizationCategory OrganizationCategory[] - OrganizationFramework OrganizationFramework[] - PolicyFramework PolicyFramework[] - OrganizationEvidence OrganizationEvidence[] - - @@index([id]) -} - -model OrganizationFramework { - id String @id @default(cuid()) - organizationId String - frameworkId String - status FrameworkStatus @default(not_started) - adoptedAt DateTime @default(now()) - lastAssessed DateTime? - nextAssessment DateTime? - organizationControl OrganizationControl[] - framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - - @@unique([organizationId, frameworkId]) -} - -model FrameworkCategory { - id String @id @default(cuid()) - name String - code String @unique - description String? - frameworkId String - controls Control[] - framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - - @@index([frameworkId]) -} - -model Control { - id String @id @default(cuid()) - code String @unique - name String - description String? - domain String? - frameworkCategoryId String? - frameworkCategory FrameworkCategory? @relation(fields: [frameworkCategoryId], references: [id]) - requirements ControlRequirement[] - organizationControls OrganizationControl[] - PolicyControl PolicyControl[] - - @@index([frameworkCategoryId]) -} - -model OrganizationControl { - id String @id @default(cuid()) - organizationId String - controlId String - status ComplianceStatus @default(not_started) - lastReviewDate DateTime? - nextReviewDate DateTime? - organizationFrameworkId String? - organizationCategoryId String? - artifacts ControlArtifact[] - control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) - OrganizationCategory OrganizationCategory? @relation(fields: [organizationCategoryId], references: [id]) - OrganizationFramework OrganizationFramework? @relation(fields: [organizationFrameworkId], references: [id]) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - OrganizationControlRequirement OrganizationControlRequirement[] - - @@index([organizationId]) - @@index([organizationFrameworkId]) - @@index([controlId]) -} - -model Artifact { - id String @id @default(cuid()) - name String - published Boolean @default(false) - needsReview Boolean @default(true) - department Departments @default(none) - type ArtifactType - content Json? - fileUrl String? - version Int @default(1) - lastUpdated DateTime? - organizationId String - ownerId String? - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - controls ControlArtifact[] - - @@index([organizationId]) - @@index([type]) -} - -model ControlArtifact { - id String @id @default(cuid()) - organizationControlId String - artifactId String - artifact Artifact @relation(fields: [artifactId], references: [id], onDelete: Cascade) - organizationControl OrganizationControl @relation(fields: [organizationControlId], references: [id], onDelete: Cascade) - - @@index([organizationControlId]) - @@index([artifactId]) -} - -model Risk { - id String @id @default(cuid()) - title String - description String - category RiskCategory - department Departments? - status RiskStatus @default(open) - probability Int @default(0) - impact Int @default(0) - residual_probability Int @default(0) - residual_impact Int @default(0) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organizationId String - ownerId String? - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - attachments RiskAttachment[] - comments RiskComment[] - mitigationTasks RiskMitigationTask[] - treatmentStrategy RiskTreatmentStrategy? - TaskComments TaskComments[] - - @@index([organizationId]) - @@index([ownerId]) - @@index([category]) - @@index([status]) -} - -model RiskComment { - id String @id @default(cuid()) - riskId String - ownerId String - organizationId String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) - - @@index([riskId]) - @@index([ownerId]) - @@index([organizationId]) -} - -model RiskMitigationTask { - id String @id @default(cuid()) - title String - description String - status RiskTaskStatus @default(open) - dueDate DateTime? - notifiedAt DateTime? - completedAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - riskId String - ownerId String? - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) - assignments RiskTaskAssignment[] - TaskAttachment TaskAttachment[] - TaskComments TaskComments[] - - @@index([riskId]) - @@index([ownerId]) - @@index([organizationId]) -} - -model TaskComments { - id String @id @default(cuid()) - riskId String - riskMitigationTaskId String - ownerId String - organizationId String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) - riskMitigationTask RiskMitigationTask @relation(fields: [riskMitigationTaskId], references: [id], onDelete: Cascade) - - @@index([riskId]) - @@index([riskMitigationTaskId]) - @@index([organizationId]) -} - -model TaskAttachment { - id String @id @default(cuid()) - riskMitigationTaskId String - name String - fileUrl String - fileKey String? - type RiskAttachmentType @default(file) - uploadedAt DateTime @default(now()) - ownerId String? - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - riskMitigationTask RiskMitigationTask @relation(fields: [riskMitigationTaskId], references: [id], onDelete: Cascade) - - @@index([riskMitigationTaskId]) - @@index([organizationId]) -} - -model RiskTreatmentStrategy { - id String @id @default(cuid()) - type TreatmentType - description String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - riskId String @unique - risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) - - @@index([riskId]) -} - -model Vendors { - id String @id @default(cuid()) - name String - website String - description String - category VendorCategory - status VendorStatus @default(not_assessed) - inherent_risk VendorInherentRisk @default(unknown) - residual_risk VendorResidualRisk @default(unknown) - lastAssessed DateTime? - nextAssessment DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - ownerId String? - organizationId String - VendorComment VendorComment[] - VendorContact VendorContact[] - VendorMitigationTask VendorMitigationTask[] - VendorRiskAssessment VendorRiskAssessment[] - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - - @@index([organizationId]) - @@index([ownerId]) - @@index([category]) - @@index([status]) -} - -model VendorContact { - id String @id @default(cuid()) - vendorId String - name String - email String - role String - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - vendor Vendors @relation(fields: [vendorId], references: [id], onDelete: Cascade) - - @@index([vendorId]) - @@index([organizationId]) -} - -model VendorComment { - id String @id @default(cuid()) - vendorId String - ownerId String - organizationId String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - vendor Vendors @relation(fields: [vendorId], references: [id], onDelete: Cascade) - - @@index([vendorId]) - @@index([ownerId]) - @@index([organizationId]) -} - -model VendorMitigationTask { - id String @id @default(cuid()) - title String - description String - status RiskTaskStatus @default(open) - dueDate DateTime? - completedAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - ownerId String? - vendorId String - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - vendor Vendors @relation(fields: [vendorId], references: [id], onDelete: Cascade) - assignments VendorTaskAssignment[] - VendorTaskAttachment VendorTaskAttachment[] - VendorTaskComments VendorTaskComments[] - - @@index([vendorId]) - @@index([ownerId]) - @@index([organizationId]) -} - -model VendorTaskComments { - id String @id @default(cuid()) - vendorMitigationTaskId String - ownerId String - organizationId String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - vendorMitigationTask VendorMitigationTask @relation(fields: [vendorMitigationTaskId], references: [id], onDelete: Cascade) - - @@index([vendorMitigationTaskId]) - @@index([organizationId]) -} - -model VendorTaskAttachment { - id String @id @default(cuid()) - vendorMitigationTaskId String - name String - fileUrl String - fileKey String? - type RiskAttachmentType @default(file) - uploadedAt DateTime @default(now()) - ownerId String? - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - vendorMitigationTask VendorMitigationTask @relation(fields: [vendorMitigationTaskId], references: [id], onDelete: Cascade) - - @@index([vendorMitigationTaskId]) - @@index([organizationId]) -} - -model VendorRiskAssessment { - id String @id @default(cuid()) - vendorId String - ownerId String? - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - vendor Vendors @relation(fields: [vendorId], references: [id], onDelete: Cascade) - - @@index([vendorId]) - @@index([organizationId]) -} - -model RiskAttachment { - id String @id @default(cuid()) - riskId String - name String - fileUrl String - fileKey String? - type RiskAttachmentType @default(file) - uploadedAt DateTime @default(now()) - ownerId String? - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User? @relation(fields: [ownerId], references: [id]) - risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) - - @@index([riskId]) - @@index([organizationId]) -} - -model OrganizationMember { - id String @id @default(cuid()) - role MembershipRole @default(member) - invitedEmail String? - accepted Boolean @default(false) - department Departments @default(none) - joinedAt DateTime @default(now()) - lastActive DateTime? - userId String - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([userId, organizationId]) - @@index([organizationId]) - @@index([userId]) -} - -model RiskTaskAssignment { - id String @id @default(cuid()) - assignedAt DateTime @default(now()) - taskId String - employeeId String - employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) - task RiskMitigationTask @relation(fields: [taskId], references: [id], onDelete: Cascade) - - @@unique([taskId, employeeId]) - @@index([taskId]) - @@index([employeeId]) -} - -model VendorTaskAssignment { - id String @id @default(cuid()) - assignedAt DateTime @default(now()) - taskId String - employeeId String - employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) - task VendorMitigationTask @relation(fields: [taskId], references: [id], onDelete: Cascade) - - @@unique([taskId, employeeId]) - @@index([taskId]) - @@index([employeeId]) -} - -model EmployeeRequiredTask { - id String @id @default(cuid()) - code String @unique - name String - description String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - employeeTasks EmployeeTask[] -} - -model EmployeeTask { - id String @id @default(cuid()) - employeeId String - requiredTaskId String - status EmployeeTaskStatus @default(assigned) - completedAt DateTime? - overrideCompliant Boolean @default(false) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) - requiredTask EmployeeRequiredTask @relation(fields: [requiredTaskId], references: [id], onDelete: Cascade) - - @@unique([employeeId, requiredTaskId]) -} - -model Employee { - id String @id @default(cuid()) - name String - email String - department Departments @default(none) - isActive Boolean @default(true) - externalEmployeeId String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organizationId String - userId String? - linkId String? - link PortalUser? @relation(fields: [linkId], references: [id]) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - user User? @relation(fields: [userId], references: [id]) - EmployeePolicyAcceptance EmployeePolicyAcceptance[] - employeeTasks EmployeeTask[] - RiskTaskAssignment RiskTaskAssignment[] - VendorTaskAssignment VendorTaskAssignment[] - - @@unique([email, organizationId]) - @@index([organizationId]) - @@index([userId]) - @@index([department]) -} - -model Policy { - id String @id @default(cuid()) - slug String @unique - name String - description String? - content Json[] - version String? - usedBy Json - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - frequency Frequency? - isRequiredToSign Boolean @default(false) - ControlRequirement ControlRequirement[] - employeeAcceptances EmployeePolicyAcceptance[] - OrganizationPolicy OrganizationPolicy[] - PolicyControl PolicyControl[] - policyFiles PolicyFile[] - policyFrameworks PolicyFramework[] -} - -model PolicyFile { - id String @id @default(cuid()) - policyId String - fileName String - fileUrl String - fileType String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) -} - -model PolicyFramework { - id String @id @default(cuid()) - policyId String - frameworkId String - framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) - - @@unique([policyId, frameworkId]) -} - -model EmployeePolicyAcceptance { - id String @id @default(cuid()) - employeeId String - policyId String - readAt DateTime? - acceptedAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) - policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) - - @@unique([employeeId, policyId]) -} - -model PolicyControl { - id String @id @default(cuid()) - policyId String - controlId String - control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) - policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) - - @@unique([policyId, controlId]) -} - -model ControlRequirement { - id String @id @default(cuid()) - controlId String - type RequirementType - description String? - policyId String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - name String @default("") - evidenceId String? - frequency Frequency? - control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) - evidence Evidence? @relation(fields: [evidenceId], references: [id]) - policy Policy? @relation(fields: [policyId], references: [id]) - OrganizationControlRequirement OrganizationControlRequirement[] - - @@index([controlId]) -} - -model OrganizationControlRequirement { - id String @id @default(cuid()) - organizationControlId String - controlRequirementId String - content Json? - createdAt DateTime @default(now()) - description String? - fileUrl String? - published Boolean @default(false) - type RequirementType - updatedAt DateTime @updatedAt - - organizationPolicyId String? - organizationEvidenceId String? - controlRequirement ControlRequirement @relation(fields: [controlRequirementId], references: [id], onDelete: Cascade) - organizationControl OrganizationControl @relation(fields: [organizationControlId], references: [id], onDelete: Cascade) - organizationEvidence OrganizationEvidence? @relation(fields: [organizationEvidenceId], references: [id], onDelete: Cascade) - organizationPolicy OrganizationPolicy? @relation(fields: [organizationPolicyId], references: [id], onDelete: Cascade) - - @@unique([organizationControlId, controlRequirementId]) -} - -model OrganizationPolicy { - id String @id @default(cuid()) - organizationId String - status PolicyStatus @default(draft) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - policyId String - content Json[] - frequency Frequency? - lastPublishedAt DateTime? - OrganizationControlRequirement OrganizationControlRequirement[] - PolicyComments PolicyComments[] - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) - ownerId String? - owner User? @relation(fields: [ownerId], references: [id]) - department Departments? - reviewDate DateTime? - - @@unique([organizationId, policyId]) - @@index([organizationId]) - @@index([policyId]) -} - -model OrganizationCategory { - id String @id @unique @default(cuid()) - name String - description String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organizationId String - frameworkId String - framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - organizationControl OrganizationControl[] - - @@index([organizationId]) -} - -model Evidence { - id String @id @unique @default(cuid()) - name String - description String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - frequency Frequency? - ControlRequirement ControlRequirement[] - OrganizationEvidence OrganizationEvidence[] -} - -model OrganizationEvidence { - id String @id @unique @default(cuid()) - name String - description String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - published Boolean @default(false) - organizationId String - additionalUrls String[] - evidenceId String - fileUrls String[] - frequency Frequency? - lastPublishedAt DateTime? - assigneeId String? - department Departments? @default(none) - isNotRelevant Boolean @default(false) - - frameworkId String - framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) - - OrganizationControlRequirement OrganizationControlRequirement[] - assignee User? @relation(fields: [assigneeId], references: [id]) - evidence Evidence @relation(fields: [evidenceId], references: [id], onDelete: Cascade) - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - - @@index([organizationId]) - @@index([assigneeId]) -} - -model PortalUser { - id String @id - name String - email String @unique - emailVerified Boolean - image String? - createdAt DateTime - updatedAt DateTime - organizationId String? - employees Employee[] - accounts PortalAccount[] - sessions PortalSession[] - organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade) - - @@map("portal_user") -} - -model PortalSession { - id String @id - expiresAt DateTime - token String @unique - createdAt DateTime - updatedAt DateTime - ipAddress String? - userAgent String? - userId String - user PortalUser @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@map("portal_session") -} - -model PortalAccount { - id String @id - accountId String - providerId String - userId String - accessToken String? - refreshToken String? - idToken String? - accessTokenExpiresAt DateTime? - refreshTokenExpiresAt DateTime? - scope String? - password String? - createdAt DateTime - updatedAt DateTime - user PortalUser @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@map("portal_account") -} - -model PortalVerification { - id String @id - identifier String - value String - expiresAt DateTime - createdAt DateTime? - updatedAt DateTime? - - @@map("portal_verification") -} - -model OrganizationApiKey { - id String @id @default(cuid()) - name String // A friendly name for the API key - key String @unique // The hashed API key - salt String? // Salt used for hashing the API key (nullable for backward compatibility) - createdAt DateTime @default(now()) - expiresAt DateTime? // Optional expiration date - lastUsedAt DateTime? // Track when the key was last used - organizationId String - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - isActive Boolean @default(true) - - @@index([organizationId]) - @@index([key]) -} - -model PolicyComments { - id String @id @default(cuid()) - organizationPolicyId String - ownerId String - organizationId String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - organizationPolicy OrganizationPolicy @relation(fields: [organizationPolicyId], references: [id], onDelete: Cascade) - - @@index([organizationPolicyId]) - @@index([organizationId]) -} - -enum Tier { - free - pro -} - -enum Role { - member - admin -} - -enum Departments { - none - admin - gov - hr - it - itsm - qms -} - -enum RequirementType { - policy - file - link - procedure - evidence - training -} - -enum Frequency { - monthly - quarterly - yearly -} - -enum FrameworkStatus { - not_started - in_progress - compliant - non_compliant -} - -enum ComplianceStatus { - not_started - in_progress - compliant - non_compliant -} - -enum ArtifactType { - policy - evidence - procedure - training -} - -enum RiskLevel { - low - medium - high -} - -enum RiskCategory { - customer - governance - operations - other - people - regulatory - reporting - resilience - technology - vendor_management -} - -enum TreatmentType { - accept - avoid - mitigate - transfer -} - -enum RiskStatus { - open - pending - closed - archived -} - -enum RiskTaskStatus { - open - pending - closed -} - -enum RiskAttachmentType { - file - url -} - -enum VendorCategory { - cloud - infrastructure - software_as_a_service - finance - marketing - sales - hr - other -} - -enum VendorStatus { - not_assessed - in_progress - assessed -} - -enum VendorInherentRisk { - low - medium - high - unknown -} - -enum VendorResidualRisk { - low - medium - high - unknown -} - -enum MembershipRole { - owner - admin - member - viewer -} - -enum EmployeeTaskStatus { - assigned - in_progress - completed - overdue -} - -enum PolicyStatus { - draft - published - archived - needs_review -} diff --git a/packages/db/prisma/schema/cloud.prisma b/packages/db/prisma/schema/cloud.prisma new file mode 100644 index 0000000000..2ebb59b81d --- /dev/null +++ b/packages/db/prisma/schema/cloud.prisma @@ -0,0 +1,20 @@ +model OrganizationIntegrationResults { + id String @id @default(cuid()) + title String? + status String + label String? + resultDetails Json? + completedAt DateTime? @default(now()) + organizationIntegrationId String + organizationId String + assignedUserId String? + + assignedUser User? @relation(fields: [assignedUserId], references: [id], onDelete: Cascade) + organizationIntegration OrganizationIntegrations @relation(fields: [organizationIntegrationId], references: [id], onDelete: Cascade) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([assignedUserId]) + @@index([organizationIntegrationId]) + @@index([organizationId]) + @@map("Organization_integration_results") +} diff --git a/packages/db/prisma/schema/employee.prisma b/packages/db/prisma/schema/employee.prisma new file mode 100644 index 0000000000..c22488c279 --- /dev/null +++ b/packages/db/prisma/schema/employee.prisma @@ -0,0 +1,63 @@ +model EmployeeRequiredTask { + id String @id @default(cuid()) + code String @unique + name String + description String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + employeeTasks EmployeeTask[] +} + +model EmployeeTask { + id String @id @default(cuid()) + employeeId String + requiredTaskId String + status EmployeeTaskStatus @default(assigned) + completedAt DateTime? + overrideCompliant Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) + requiredTask EmployeeRequiredTask @relation(fields: [requiredTaskId], references: [id], onDelete: Cascade) + + @@unique([employeeId, requiredTaskId]) +} + +model Employee { + id String @id @default(cuid()) + name String + email String + department Departments @default(none) + isActive Boolean @default(true) + externalEmployeeId String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organizationId String + userId String? + linkId String? + link PortalUser? @relation(fields: [linkId], references: [id]) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id]) + EmployeePolicyAcceptance EmployeePolicyAcceptance[] + employeeTasks EmployeeTask[] + RiskTaskAssignment RiskTaskAssignment[] + + @@unique([email, organizationId]) + @@index([organizationId]) + @@index([userId]) + @@index([department]) +} + +model EmployeePolicyAcceptance { + id String @id @default(cuid()) + employeeId String + policyId String + readAt DateTime? + acceptedAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) + policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) + + @@unique([employeeId, policyId]) +} diff --git a/packages/db/prisma/schema/framework.prisma b/packages/db/prisma/schema/framework.prisma new file mode 100644 index 0000000000..81b4db832b --- /dev/null +++ b/packages/db/prisma/schema/framework.prisma @@ -0,0 +1,205 @@ +model Framework { + id String @id @default(cuid()) + name String @unique + description String? + version String + categories FrameworkCategory[] + organizations Organization[] + OrganizationCategory OrganizationCategory[] + OrganizationFramework OrganizationFramework[] + PolicyFramework PolicyFramework[] + OrganizationEvidence OrganizationEvidence[] + + @@index([id]) +} + +model OrganizationFramework { + id String @id @default(cuid()) + organizationId String + frameworkId String + status FrameworkStatus @default(not_started) + adoptedAt DateTime @default(now()) + lastAssessed DateTime? + nextAssessment DateTime? + organizationControl OrganizationControl[] + framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@unique([organizationId, frameworkId]) +} + +model FrameworkCategory { + id String @id @default(cuid()) + name String + code String @unique + description String? + frameworkId String + controls Control[] + framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + + @@index([frameworkId]) +} + +model Control { + id String @id @default(cuid()) + code String @unique + name String + description String? + domain String? + frameworkCategoryId String? + frameworkCategory FrameworkCategory? @relation(fields: [frameworkCategoryId], references: [id]) + requirements ControlRequirement[] + organizationControls OrganizationControl[] + PolicyControl PolicyControl[] + + @@index([frameworkCategoryId]) +} + +model OrganizationControl { + id String @id @default(cuid()) + organizationId String + controlId String + status ComplianceStatus @default(not_started) + lastReviewDate DateTime? + nextReviewDate DateTime? + organizationFrameworkId String? + organizationCategoryId String? + artifacts ControlArtifact[] + control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) + OrganizationCategory OrganizationCategory? @relation(fields: [organizationCategoryId], references: [id]) + OrganizationFramework OrganizationFramework? @relation(fields: [organizationFrameworkId], references: [id]) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + OrganizationControlRequirement OrganizationControlRequirement[] + + @@index([organizationId]) + @@index([organizationFrameworkId]) + @@index([controlId]) +} + +model Artifact { + id String @id @default(cuid()) + name String + published Boolean @default(false) + needsReview Boolean @default(true) + department Departments @default(none) + type ArtifactType + content Json? + fileUrl String? + version Int @default(1) + lastUpdated DateTime? + organizationId String + ownerId String? + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User? @relation(fields: [ownerId], references: [id]) + controls ControlArtifact[] + + @@index([organizationId]) + @@index([type]) +} + +model ControlArtifact { + id String @id @default(cuid()) + organizationControlId String + artifactId String + artifact Artifact @relation(fields: [artifactId], references: [id], onDelete: Cascade) + organizationControl OrganizationControl @relation(fields: [organizationControlId], references: [id], onDelete: Cascade) + + @@index([organizationControlId]) + @@index([artifactId]) +} + +model ControlRequirement { + id String @id @default(cuid()) + controlId String + type RequirementType + description String? + policyId String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + name String @default("") + evidenceId String? + frequency Frequency? + control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) + evidence Evidence? @relation(fields: [evidenceId], references: [id]) + policy Policy? @relation(fields: [policyId], references: [id]) + OrganizationControlRequirement OrganizationControlRequirement[] + + @@index([controlId]) +} + +model OrganizationControlRequirement { + id String @id @default(cuid()) + organizationControlId String + controlRequirementId String + content Json? + createdAt DateTime @default(now()) + description String? + fileUrl String? + published Boolean @default(false) + type RequirementType + updatedAt DateTime @updatedAt + + organizationPolicyId String? + organizationEvidenceId String? + controlRequirement ControlRequirement @relation(fields: [controlRequirementId], references: [id], onDelete: Cascade) + organizationControl OrganizationControl @relation(fields: [organizationControlId], references: [id], onDelete: Cascade) + organizationEvidence OrganizationEvidence? @relation(fields: [organizationEvidenceId], references: [id], onDelete: Cascade) + organizationPolicy OrganizationPolicy? @relation(fields: [organizationPolicyId], references: [id], onDelete: Cascade) + + @@unique([organizationControlId, controlRequirementId]) +} + +model OrganizationCategory { + id String @id @unique @default(cuid()) + name String + description String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organizationId String + frameworkId String + framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + organizationControl OrganizationControl[] + + @@index([organizationId]) +} + +model Evidence { + id String @id @unique @default(cuid()) + name String + description String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + frequency Frequency? + ControlRequirement ControlRequirement[] + OrganizationEvidence OrganizationEvidence[] +} + +model OrganizationEvidence { + id String @id @unique @default(cuid()) + name String + description String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + published Boolean @default(false) + organizationId String + additionalUrls String[] + evidenceId String + fileUrls String[] + frequency Frequency? + lastPublishedAt DateTime? + assigneeId String? + department Departments? @default(none) + isNotRelevant Boolean @default(false) + + frameworkId String + framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + + OrganizationControlRequirement OrganizationControlRequirement[] + assignee User? @relation(fields: [assigneeId], references: [id]) + evidence Evidence @relation(fields: [evidenceId], references: [id], onDelete: Cascade) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([assigneeId]) +} diff --git a/packages/db/prisma/schema/policy.prisma b/packages/db/prisma/schema/policy.prisma new file mode 100644 index 0000000000..f59e4f72a1 --- /dev/null +++ b/packages/db/prisma/schema/policy.prisma @@ -0,0 +1,90 @@ +model OrganizationPolicy { + id String @id @default(cuid()) + organizationId String + status PolicyStatus @default(draft) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + policyId String + content Json[] + frequency Frequency? + lastPublishedAt DateTime? + OrganizationControlRequirement OrganizationControlRequirement[] + PolicyComments PolicyComments[] + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) + ownerId String? + owner User? @relation(fields: [ownerId], references: [id]) + department Departments? + reviewDate DateTime? + + @@unique([organizationId, policyId]) + @@index([organizationId]) + @@index([policyId]) +} + +model Policy { + id String @id @default(cuid()) + slug String @unique + name String + description String? + content Json[] + version String? + usedBy Json + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + frequency Frequency? + isRequiredToSign Boolean @default(false) + ControlRequirement ControlRequirement[] + employeeAcceptances EmployeePolicyAcceptance[] + OrganizationPolicy OrganizationPolicy[] + PolicyControl PolicyControl[] + policyFiles PolicyFile[] + policyFrameworks PolicyFramework[] +} + +model PolicyFile { + id String @id @default(cuid()) + policyId String + fileName String + fileUrl String + fileType String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) +} + +model PolicyFramework { + id String @id @default(cuid()) + policyId String + frameworkId String + framework Framework @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) + + @@unique([policyId, frameworkId]) +} + +model PolicyComments { + id String @id @default(cuid()) + organizationPolicyId String + ownerId String + organizationId String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) + organizationPolicy OrganizationPolicy @relation(fields: [organizationPolicyId], references: [id], onDelete: Cascade) + + @@index([organizationPolicyId]) + @@index([organizationId]) +} + +model PolicyControl { + id String @id @default(cuid()) + policyId String + controlId String + control Control @relation(fields: [controlId], references: [id], onDelete: Cascade) + policy Policy @relation(fields: [policyId], references: [id], onDelete: Cascade) + + @@unique([policyId, controlId]) +} diff --git a/packages/db/prisma/schema/portal.prisma b/packages/db/prisma/schema/portal.prisma new file mode 100644 index 0000000000..0ef35ab745 --- /dev/null +++ b/packages/db/prisma/schema/portal.prisma @@ -0,0 +1,60 @@ +model PortalUser { + id String @id + name String + email String @unique + emailVerified Boolean + image String? + createdAt DateTime + updatedAt DateTime + organizationId String? + employees Employee[] + accounts PortalAccount[] + sessions PortalSession[] + organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@map("portal_user") +} + +model PortalSession { + id String @id + expiresAt DateTime + token String @unique + createdAt DateTime + updatedAt DateTime + ipAddress String? + userAgent String? + userId String + user PortalUser @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@map("portal_session") +} + +model PortalAccount { + id String @id + accountId String + providerId String + userId String + accessToken String? + refreshToken String? + idToken String? + accessTokenExpiresAt DateTime? + refreshTokenExpiresAt DateTime? + scope String? + password String? + createdAt DateTime + updatedAt DateTime + user PortalUser @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@map("portal_account") +} + +model PortalVerification { + id String @id + identifier String + value String + expiresAt DateTime + createdAt DateTime? + updatedAt DateTime? + + @@map("portal_verification") +} diff --git a/packages/db/prisma/schema/risk.prisma b/packages/db/prisma/schema/risk.prisma new file mode 100644 index 0000000000..52550109c3 --- /dev/null +++ b/packages/db/prisma/schema/risk.prisma @@ -0,0 +1,150 @@ +model Risk { + id String @id @default(cuid()) + title String + description String + category RiskCategory + department Departments? + status RiskStatus @default(open) + probability Int @default(0) + impact Int @default(0) + residual_probability Int @default(0) + residual_impact Int @default(0) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organizationId String + ownerId String? + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User? @relation(fields: [ownerId], references: [id]) + attachments RiskAttachment[] + comments RiskComment[] + mitigationTasks RiskMitigationTask[] + treatmentStrategy RiskTreatmentStrategy? + TaskComments TaskComments[] + + @@index([organizationId]) + @@index([ownerId]) + @@index([category]) + @@index([status]) +} + +model RiskComment { + id String @id @default(cuid()) + riskId String + ownerId String + organizationId String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) + risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) + + @@index([riskId]) + @@index([ownerId]) + @@index([organizationId]) +} + +model RiskMitigationTask { + id String @id @default(cuid()) + title String + description String + status RiskTaskStatus @default(open) + dueDate DateTime? + notifiedAt DateTime? + completedAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + riskId String + ownerId String? + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User? @relation(fields: [ownerId], references: [id]) + risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) + assignments RiskTaskAssignment[] + TaskAttachment TaskAttachment[] + TaskComments TaskComments[] + + @@index([riskId]) + @@index([ownerId]) + @@index([organizationId]) +} + +model TaskComments { + id String @id @default(cuid()) + riskId String + riskMitigationTaskId String + ownerId String + organizationId String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) + risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) + riskMitigationTask RiskMitigationTask @relation(fields: [riskMitigationTaskId], references: [id], onDelete: Cascade) + + @@index([riskId]) + @@index([riskMitigationTaskId]) + @@index([organizationId]) +} + +model TaskAttachment { + id String @id @default(cuid()) + riskMitigationTaskId String + name String + fileUrl String + fileKey String? + type RiskAttachmentType @default(file) + uploadedAt DateTime @default(now()) + ownerId String? + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User? @relation(fields: [ownerId], references: [id]) + riskMitigationTask RiskMitigationTask @relation(fields: [riskMitigationTaskId], references: [id], onDelete: Cascade) + + @@index([riskMitigationTaskId]) + @@index([organizationId]) +} + +model RiskTreatmentStrategy { + id String @id @default(cuid()) + type TreatmentType + description String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + riskId String @unique + risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) + + @@index([riskId]) +} + +model RiskAttachment { + id String @id @default(cuid()) + riskId String + name String + fileUrl String + fileKey String? + type RiskAttachmentType @default(file) + uploadedAt DateTime @default(now()) + ownerId String? + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + owner User? @relation(fields: [ownerId], references: [id]) + risk Risk @relation(fields: [riskId], references: [id], onDelete: Cascade) + + @@index([riskId]) + @@index([organizationId]) +} + +model RiskTaskAssignment { + id String @id @default(cuid()) + assignedAt DateTime @default(now()) + taskId String + employeeId String + employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) + task RiskMitigationTask @relation(fields: [taskId], references: [id], onDelete: Cascade) + + @@unique([taskId, employeeId]) + @@index([taskId]) + @@index([employeeId]) +} diff --git a/packages/db/prisma/schema/schema.prisma b/packages/db/prisma/schema/schema.prisma new file mode 100644 index 0000000000..4bb6f4fef2 --- /dev/null +++ b/packages/db/prisma/schema/schema.prisma @@ -0,0 +1,328 @@ +generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters", "postgresqlExtensions", "prismaSchemaFolder"] + binaryTargets = ["native", "debian-openssl-3.0.x"] +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model Account { + id String @id @default(cuid()) + userId String + type String + provider String + providerAccountId String + refresh_token String? + access_token String? + expires_at Int? + token_type String? + scope String? + id_token String? + session_state String? + refresh_token_expires_in Int? + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([provider, providerAccountId]) + @@index([userId]) +} + +model Session { + id String @id @default(cuid()) + sessionToken String @unique + userId String + expires DateTime + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) +} + +model User { + id String @id @default(cuid()) + name String? + full_name String? + email String? @unique + role Role @default(member) + onboarded Boolean @default(false) + emailVerified DateTime? + image String? + lastLogin DateTime? + organizationId String? + accounts Account[] + Artifact Artifact[] + AuditLog AuditLog[] + Employee Employee[] + AssignedEvidence OrganizationEvidence[] + organizationMemberships OrganizationMember[] + Risk Risk[] + RiskAttachment RiskAttachment[] + RiskComment RiskComment[] + RiskMitigationTask RiskMitigationTask[] + sessions Session[] + TaskAttachment TaskAttachment[] + TaskComments TaskComments[] + PolicyComments PolicyComments[] + organization Organization? @relation("CurrentOrganization", fields: [organizationId], references: [id]) + OrganizationPolicy OrganizationPolicy[] + OrganizationIntegrationResults OrganizationIntegrationResults[] + + @@index([email]) + @@index([organizationId]) +} + +model Organization { + id String @id @default(cuid()) + stripeCustomerId String? + name String + subdomain String @unique + website String + tier Tier @default(free) + policiesCreated Boolean @default(false) + frameworkId String? + Artifact Artifact[] + AuditLog AuditLog[] + employees Employee[] + Framework Framework? @relation(fields: [frameworkId], references: [id], onDelete: Cascade) + OrganizationCategory OrganizationCategory[] + OrganizationControl OrganizationControl[] + OrganizationEvidence OrganizationEvidence[] + OrganizationFramework OrganizationFramework[] + OrganizationIntegrations OrganizationIntegrations[] + members OrganizationMember[] + OrganizationPolicy OrganizationPolicy[] + Risk Risk[] + RiskAttachment RiskAttachment[] + RiskComment RiskComment[] + RiskMitigationTask RiskMitigationTask[] + TaskAttachment TaskAttachment[] + TaskComments TaskComments[] + PolicyComments PolicyComments[] + users User[] @relation("CurrentOrganization") + PortalUser PortalUser[] + apiKeys OrganizationApiKey[] + OrganizationIntegrationResults OrganizationIntegrationResults[] + + @@index([stripeCustomerId]) +} + +model VerificationToken { + identifier String + token String @unique + expires DateTime + + @@unique([identifier, token]) +} + +model OrganizationMember { + id String @id @default(cuid()) + role MembershipRole @default(member) + invitedEmail String? + accepted Boolean @default(false) + department Departments @default(none) + joinedAt DateTime @default(now()) + lastActive DateTime? + userId String + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([userId, organizationId]) + @@index([organizationId]) + @@index([userId]) +} + +model OrganizationApiKey { + id String @id @default(cuid()) + name String + key String @unique + salt String? + createdAt DateTime @default(now()) + expiresAt DateTime? + lastUsedAt DateTime? + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + isActive Boolean @default(true) + + @@index([organizationId]) + @@index([key]) +} + +model OrganizationIntegrations { + id String @id @default(cuid()) + name String @unique + integration_id String + settings Json + user_settings Json + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + results OrganizationIntegrationResults[] + + @@index([organizationId]) +} + +model AuditLog { + id String @id @default(cuid()) + timestamp DateTime @default(now()) + userId String + organizationId String + data Json + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) + @@index([organizationId]) +} + +enum Tier { + free + pro +} + +enum Role { + member + admin +} + +enum Departments { + none + admin + gov + hr + it + itsm + qms +} + +enum RequirementType { + policy + file + link + procedure + evidence + training +} + +enum Frequency { + monthly + quarterly + yearly +} + +enum FrameworkStatus { + not_started + in_progress + compliant + non_compliant +} + +enum ComplianceStatus { + not_started + in_progress + compliant + non_compliant +} + +enum ArtifactType { + policy + evidence + procedure + training +} + +enum RiskLevel { + low + medium + high +} + +enum RiskCategory { + customer + governance + operations + other + people + regulatory + reporting + resilience + technology + vendor_management +} + +enum TreatmentType { + accept + avoid + mitigate + transfer +} + +enum RiskStatus { + open + pending + closed + archived +} + +enum RiskTaskStatus { + open + pending + closed +} + +enum RiskAttachmentType { + file + url +} + +enum VendorCategory { + cloud + infrastructure + software_as_a_service + finance + marketing + sales + hr + other +} + +enum VendorStatus { + not_assessed + in_progress + assessed +} + +enum VendorInherentRisk { + low + medium + high + unknown +} + +enum VendorResidualRisk { + low + medium + high + unknown +} + +enum MembershipRole { + owner + admin + member + viewer +} + +enum EmployeeTaskStatus { + assigned + in_progress + completed + overdue +} + +enum PolicyStatus { + draft + published + archived + needs_review +} diff --git a/packages/db/prisma/schema/vendor.prisma b/packages/db/prisma/schema/vendor.prisma new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/packages/db/prisma/schema/vendor.prisma @@ -0,0 +1 @@ + diff --git a/yarn.lock b/yarn.lock index 4e95b9dc8c..bfd3a6e663 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,6 +1,6 @@ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 -# bun ./bun.lockb --hash: BDF775C6849D1834-9d535bffb01c7474-72044ACA9DF1720C-4f2b9a9d9e5d8414 +# bun ./bun.lockb --hash: 0000000000000000-0000000000000000-0000000000000000-0000000000000000 "@ai-sdk/openai@^0.0.66": @@ -45,20 +45,20 @@ resolved "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.20.tgz" integrity sha512-ngg/RGpnA00eNOWEtXHenpX1MsM2QshQh4QJFjUfwcqHpM5kTfG7je7Rc3HcEDP+OkRVv2GF+X4fC1Vfcnl8Ow== dependencies: - nanoid "3.3.6" "@ai-sdk/provider" "0.0.24" - secure-json-parse "2.7.0" eventsource-parser "1.1.2" + nanoid "3.3.6" + secure-json-parse "2.7.0" "@ai-sdk/provider-utils@1.0.22": version "1.0.22" resolved "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz" integrity sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ== dependencies: - nanoid "^3.3.7" "@ai-sdk/provider" "0.0.26" - secure-json-parse "^2.7.0" eventsource-parser "^1.1.2" + nanoid "^3.3.7" + secure-json-parse "^2.7.0" "@ai-sdk/provider-utils@2.1.11": version "2.1.11" @@ -75,10 +75,10 @@ resolved "https://registry.npmjs.org/@ai-sdk/react/-/react-0.0.70.tgz" integrity sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ== dependencies: + "@ai-sdk/provider-utils" "1.0.22" + "@ai-sdk/ui-utils" "0.0.50" swr "^2.2.5" throttleit "2.1.0" - "@ai-sdk/ui-utils" "0.0.50" - "@ai-sdk/provider-utils" "1.0.22" "@ai-sdk/react@1.1.21": version "1.1.21" @@ -95,28 +95,28 @@ resolved "https://registry.npmjs.org/@ai-sdk/solid/-/solid-0.0.54.tgz" integrity sha512-96KWTVK+opdFeRubqrgaJXoNiDP89gNxFRWUp0PJOotZW816AbhUf4EnDjBjXTLjXL1n0h8tGSE9sZsRkj9wQQ== dependencies: - "@ai-sdk/ui-utils" "0.0.50" "@ai-sdk/provider-utils" "1.0.22" + "@ai-sdk/ui-utils" "0.0.50" "@ai-sdk/svelte@0.0.57": version "0.0.57" resolved "https://registry.npmjs.org/@ai-sdk/svelte/-/svelte-0.0.57.tgz" integrity sha512-SyF9ItIR9ALP9yDNAD+2/5Vl1IT6kchgyDH8xkmhysfJI6WrvJbtO1wdQ0nylvPLcsPoYu+cAlz1krU4lFHcYw== dependencies: - sswr "^2.1.0" - "@ai-sdk/ui-utils" "0.0.50" "@ai-sdk/provider-utils" "1.0.22" + "@ai-sdk/ui-utils" "0.0.50" + sswr "^2.1.0" "@ai-sdk/ui-utils@0.0.50": version "0.0.50" resolved "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.50.tgz" integrity sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw== dependencies: - json-schema "^0.4.0" "@ai-sdk/provider" "0.0.26" + "@ai-sdk/provider-utils" "1.0.22" + json-schema "^0.4.0" secure-json-parse "^2.7.0" zod-to-json-schema "^3.23.3" - "@ai-sdk/provider-utils" "1.0.22" "@ai-sdk/ui-utils@1.1.17": version "1.1.17" @@ -132,9 +132,9 @@ resolved "https://registry.npmjs.org/@ai-sdk/vue/-/vue-0.0.59.tgz" integrity sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw== dependencies: - swrv "^1.0.4" - "@ai-sdk/ui-utils" "0.0.50" "@ai-sdk/provider-utils" "1.0.22" + "@ai-sdk/ui-utils" "0.0.50" + swrv "^1.0.4" "@alloc/quick-lru@^5.2.0": version "5.2.0" @@ -154,23 +154,23 @@ resolved "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz" integrity sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw== dependencies: - lru-cache "^10.4.3" "@csstools/css-calc" "^2.1.1" - "@csstools/css-tokenizer" "^3.0.3" "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" + "@csstools/css-tokenizer" "^3.0.3" + lru-cache "^10.4.3" "@auth/core@0.37.2": version "0.37.2" resolved "https://registry.npmjs.org/@auth/core/-/core-0.37.2.tgz" integrity sha512-kUvzyvkcd6h1vpeMAojK2y7+PAV5H+0Cc9+ZlKYDFhDY31AlvsB+GW5vNO4qE3Y07KeQgvNO9U0QUx/fN62kBw== dependencies: - jose "^5.9.3" - cookie "0.7.1" - preact "10.11.3" "@panva/hkdf" "^1.2.1" - oauth4webapi "^3.0.0" "@types/cookie" "0.6.0" + cookie "0.7.1" + jose "^5.9.3" + oauth4webapi "^3.0.0" + preact "10.11.3" preact-render-to-string "5.2.3" "@auth/core@0.38.0": @@ -821,9 +821,9 @@ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== dependencies: + "@babel/helper-validator-identifier" "^7.25.9" js-tokens "^4.0.0" picocolors "^1.0.0" - "@babel/helper-validator-identifier" "^7.25.9" "@babel/compat-data@^7.26.5": version "7.26.8" @@ -835,60 +835,60 @@ resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz" integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA== dependencies: - debug "^4.1.0" - json5 "^2.2.3" - semver "^6.3.1" - gensync "^1.0.0-beta.2" - "@babel/types" "^7.24.5" - "@babel/parser" "^7.24.5" + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.24.5" "@babel/helpers" "^7.24.5" + "@babel/parser" "^7.24.5" "@babel/template" "^7.24.0" "@babel/traverse" "^7.24.5" - "@babel/generator" "^7.24.5" - "@babel/code-frame" "^7.24.2" + "@babel/types" "^7.24.5" convert-source-map "^2.0.0" - "@ampproject/remapping" "^2.2.0" - "@babel/helper-module-transforms" "^7.24.5" - "@babel/helper-compilation-targets" "^7.23.6" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" "@babel/generator@^7.24.5", "@babel/generator@^7.26.9": version "7.26.9" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz" integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== dependencies: - jsesc "^3.0.2" - "@babel/types" "^7.26.9" "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" "@babel/helper-compilation-targets@^7.23.6": version "7.26.5" resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz" integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== dependencies: - semver "^6.3.1" - lru-cache "^5.1.1" - browserslist "^4.24.0" "@babel/compat-data" "^7.26.5" "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" "@babel/helper-module-imports@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz" integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== dependencies: - "@babel/types" "^7.25.9" "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" "@babel/helper-module-transforms@^7.24.5": version "7.26.0" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz" integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== dependencies: - "@babel/traverse" "^7.25.9" "@babel/helper-module-imports" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" "@babel/helper-string-parser@^7.25.9": version "7.25.9" @@ -910,8 +910,8 @@ resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz" integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== dependencies: - "@babel/types" "^7.26.9" "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" "@babel/parser@7.24.5", "@babel/parser@^7.24.5": version "7.24.5" @@ -937,22 +937,22 @@ resolved "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz" integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== dependencies: - "@babel/types" "^7.26.9" - "@babel/parser" "^7.26.9" "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" "@babel/traverse@^7.24.5", "@babel/traverse@^7.25.9": version "7.26.9" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz" integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== dependencies: - debug "^4.3.1" - globals "^11.1.0" - "@babel/types" "^7.26.9" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" "@babel/parser" "^7.26.9" "@babel/template" "^7.26.9" - "@babel/generator" "^7.26.9" - "@babel/code-frame" "^7.26.2" + "@babel/types" "^7.26.9" + debug "^4.3.1" + globals "^11.1.0" "@babel/types@^7.24.5", "@babel/types@^7.25.9", "@babel/types@^7.26.9": version "7.26.9" @@ -979,14 +979,14 @@ resolved "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz" integrity sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog== optionalDependencies: - "@biomejs/cli-linux-x64" "1.9.4" - "@biomejs/cli-win32-x64" "1.9.4" + "@biomejs/cli-darwin-arm64" "1.9.4" "@biomejs/cli-darwin-x64" "1.9.4" "@biomejs/cli-linux-arm64" "1.9.4" - "@biomejs/cli-win32-arm64" "1.9.4" - "@biomejs/cli-darwin-arm64" "1.9.4" - "@biomejs/cli-linux-x64-musl" "1.9.4" "@biomejs/cli-linux-arm64-musl" "1.9.4" + "@biomejs/cli-linux-x64" "1.9.4" + "@biomejs/cli-linux-x64-musl" "1.9.4" + "@biomejs/cli-win32-arm64" "1.9.4" + "@biomejs/cli-win32-x64" "1.9.4" "@biomejs/cli-darwin-arm64@1.9.4": version "1.9.4" @@ -1205,9 +1205,9 @@ resolved "https://registry.npmjs.org/@clack/prompts/-/prompts-0.10.0.tgz" integrity sha512-H3rCl6CwW1NdQt9rE3n373t7o5cthPv7yUoxF2ytZvyvlJv89C5RYMJu83Hed8ODgys5vpBU0GKxIRG83jd8NQ== dependencies: + "@clack/core" "0.4.1" picocolors "^1.0.0" sisteransi "^1.0.5" - "@clack/core" "0.4.1" "@csstools/color-helpers@^5.0.2": version "5.0.2" @@ -1252,8 +1252,8 @@ resolved "https://registry.npmjs.org/@effect/platform/-/platform-0.72.0.tgz" integrity sha512-uHsW2hlo6AiIW3zpLAVAoNvJngS/JwCZBAM4RSRllm8JTgjjCraef78FJBDNnSXz+2a10Xzzx4qxVsP3s8EV5Q== dependencies: - multipasta "^0.2.5" find-my-way-ts "^0.1.5" + multipasta "^0.2.5" "@egjs/agent@^2.2.1": version "2.4.4" @@ -1615,10 +1615,10 @@ resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.3.tgz" integrity sha512-pJT1OkhplSmvvr6i3CWTPvC/FGC06MbN5TNBfRO6Ox62AEz90eMq+dVvtX9Bl3jxCEkS0tATzDarRZuOLw7oFg== dependencies: - decimal.js "10" - tslib "2" "@formatjs/fast-memoize" "2.2.6" "@formatjs/intl-localematcher" "0.6.0" + decimal.js "10" + tslib "2" "@formatjs/fast-memoize@2.2.6", "@formatjs/fast-memoize@^2.2.0": version "2.2.6" @@ -1632,17 +1632,17 @@ resolved "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.1.tgz" integrity sha512-o0AhSNaOfKoic0Sn1GkFCK4MxdRsw7mPJ5/rBpIqdvcC7MIuyUSW8WChUEvrK78HhNpYOgqCQbINxCTumJLzZA== dependencies: - tslib "2" "@formatjs/ecma402-abstract" "2.3.3" "@formatjs/icu-skeleton-parser" "1.8.13" + tslib "2" "@formatjs/icu-skeleton-parser@1.8.13": version "1.8.13" resolved "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.13.tgz" integrity sha512-N/LIdTvVc1TpJmMt2jVg0Fr1F7Q1qJPdZSCs19unMskCmVQ/sa0H9L8PWt13vq+gLdLg1+pPsvBLydL1Apahjg== dependencies: - tslib "2" "@formatjs/ecma402-abstract" "2.3.3" + tslib "2" "@formatjs/intl-localematcher@^0.5.4": version "0.5.10" @@ -1999,6 +1999,10 @@ integrity sha512-K65StXUeGAtFJ4ikvHKtmDCO5Ab7g0FZUu2J5VpoKD+O6Y3CjLYzRi+TMlI3kaL4CL158+FccMoOd/eaddmeRQ== dependencies: "@babel/runtime" "^7.26.0" + "@mui/core-downloads-tracker" "^6.4.7" + "@mui/system" "^6.4.7" + "@mui/types" "^7.2.21" + "@mui/utils" "^6.4.6" "@popperjs/core" "^2.11.8" "@types/react-transition-group" "^4.4.12" clsx "^2.1.1" @@ -2006,31 +2010,27 @@ prop-types "^15.8.1" react-is "^19.0.0" react-transition-group "^4.4.5" - "@mui/utils" "^6.4.6" - "@mui/system" "^6.4.7" - "@mui/types" "^7.2.21" - "@mui/core-downloads-tracker" "^6.4.7" "@mui/private-theming@^6.4.6": version "6.4.6" resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.6.tgz" integrity sha512-T5FxdPzCELuOrhpA2g4Pi6241HAxRwZudzAuL9vBvniuB5YU82HCmrARw32AuCiyTfWzbrYGGpZ4zyeqqp9RvQ== dependencies: + "@babel/runtime" "^7.26.0" "@mui/utils" "^6.4.6" prop-types "^15.8.1" - "@babel/runtime" "^7.26.0" "@mui/styled-engine@^6.4.6": version "6.4.6" resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.6.tgz" integrity sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ== dependencies: - csstype "^3.1.3" - prop-types "^15.8.1" "@babel/runtime" "^7.26.0" "@emotion/cache" "^11.13.5" - "@emotion/sheet" "^1.4.0" "@emotion/serialize" "^1.3.3" + "@emotion/sheet" "^1.4.0" + csstype "^3.1.3" + prop-types "^15.8.1" "@mui/system@^6.4.7": version "6.4.7" @@ -2038,13 +2038,13 @@ integrity sha512-7wwc4++Ak6tGIooEVA9AY7FhH2p9fvBMORT4vNLMAysH3Yus/9B9RYMbrn3ANgsOyvT3Z7nE+SP8/+3FimQmcg== dependencies: "@babel/runtime" "^7.26.0" - clsx "^2.1.1" - csstype "^3.1.3" - prop-types "^15.8.1" "@mui/private-theming" "^6.4.6" - "@mui/utils" "^6.4.6" "@mui/styled-engine" "^6.4.6" "@mui/types" "^7.2.21" + "@mui/utils" "^6.4.6" + clsx "^2.1.1" + csstype "^3.1.3" + prop-types "^15.8.1" "@mui/types@^7.2.21": version "7.2.21" @@ -2056,12 +2056,12 @@ resolved "https://registry.npmjs.org/@mui/utils/-/utils-6.4.6.tgz" integrity sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA== dependencies: - clsx "^2.1.1" - react-is "^19.0.0" - "@mui/types" "^7.2.21" - prop-types "^15.8.1" "@babel/runtime" "^7.26.0" + "@mui/types" "^7.2.21" "@types/prop-types" "^15.7.14" + clsx "^2.1.1" + prop-types "^15.8.1" + react-is "^19.0.0" "@nangohq/frontend@^0.53.1": version "0.53.2" @@ -2075,8 +2075,8 @@ resolved "https://registry.npmjs.org/@nangohq/node/-/node-0.53.2.tgz" integrity sha512-QfBrtbv1dekI3RH+HX+43MGIRs36MNuWMdWS1RRFKjiCmIwKaOje6qjRj0UDjQYtokKcbt2id2sAAq8fmusjCQ== dependencies: - axios "^1.7.9" "@nangohq/types" "0.53.2" + axios "^1.7.9" "@nangohq/types@0.53.2": version "0.53.2" @@ -2084,8 +2084,8 @@ integrity sha512-G7oC4QsJrmLjAWQmvB7gY8hE0UMr8PofAY/pPsk/0sHIM1YWeealBI7RiPeN4UluArT7w+OoUvMQd+jtrTh9Lw== dependencies: axios "^1.7.9" - type-fest "4.32.0" json-schema "0.4.0" + type-fest "4.32.0" "@neondatabase/serverless@^0.10.4", "@neondatabase/serverless@^0.6.0 || ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0": version "0.10.4" @@ -2206,8 +2206,8 @@ resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: - run-parallel "^1.1.9" "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" @@ -2219,8 +2219,8 @@ resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: - fastq "^1.6.0" "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" "@novu/client@2.6.6": version "2.6.6" @@ -2234,10 +2234,10 @@ resolved "https://registry.npmjs.org/@novu/headless/-/headless-2.6.6.tgz" integrity sha512-2FBU1SwzUJQMnaIb9EItdREs8kiA7YG0Lgu3nMqcoTw2b8wpHC6PL1tA11XKkGY/H+dCDRM29ubbcm3tUYd+yA== dependencies: + "@novu/client" "2.6.6" + "@novu/shared" "2.6.6" "@tanstack/query-core" "^4.15.1" socket.io-client "4.7.2" - "@novu/shared" "2.6.6" - "@novu/client" "2.6.6" "@novu/js@2.6.6": version "2.6.6" @@ -2259,25 +2259,25 @@ resolved "https://registry.npmjs.org/@novu/node/-/node-2.6.6.tgz" integrity sha512-WMGzHOG1has1/FsMveE/Sak02vv6jAz1RLlw99tLARr3wQyQBdpMwtG8lNcZzi/hBogLJ07R6wFcZtgoXx/i4Q== dependencies: + "@novu/shared" "2.6.6" axios "^1.6.8" axios-retry "^3.8.0" handlebars "^4.7.7" lodash.get "^4.4.2" lodash.merge "^4.6.2" uuid "^9.0.1" - "@novu/shared" "2.6.6" "@novu/ntfr-client@^0.0.4": version "0.0.4" resolved "https://registry.npmjs.org/@novu/ntfr-client/-/ntfr-client-0.0.4.tgz" integrity sha512-/9q+qGFHHFwMsuqoLwTADMjSx2JPagpJpm7jOZRzQZgSEDg9kwNAhADneRzVYhMyjdEXIQyjTmX/oP8ABAavFw== dependencies: - ws "^8.11.0" - zod "3.22.3" https "^1.0.0" node-fetch "^3.3.2" partysocket "^0.0.17" proxy-agent "^6.3.0" + ws "^8.11.0" + zod "3.22.3" "@novu/react@^2.6.5": version "2.6.6" @@ -2296,7 +2296,7 @@ resolved "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz" integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw== -"@opentelemetry/api@1.9.0", "@opentelemetry/api@>=1.0.0 <1.10.0", "@opentelemetry/api@>=1.3.0 <1.10.0", "@opentelemetry/api@>=1.4.0 <1.10.0", "@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.8": +"@opentelemetry/api@1.9.0", "@opentelemetry/api@>=1.0.0 <1.10.0", "@opentelemetry/api@>=1.3.0 <1.10.0", "@opentelemetry/api@>=1.4.0 <1.10.0", "@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0", "@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.8": version "1.9.0" resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -2332,11 +2332,11 @@ resolved "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.52.1.tgz" integrity sha512-qKgywId2DbdowPZpOBXQKp0B8DfhfIArmSic15z13Nk/JAOccBUQdPwDjDnjsM5f0ckZFMVR2t/tijTUAqDZoA== dependencies: - "@opentelemetry/core" "1.25.1" "@opentelemetry/api-logs" "0.52.1" - "@opentelemetry/sdk-logs" "0.52.1" - "@opentelemetry/otlp-transformer" "0.52.1" + "@opentelemetry/core" "1.25.1" "@opentelemetry/otlp-exporter-base" "0.52.1" + "@opentelemetry/otlp-transformer" "0.52.1" + "@opentelemetry/sdk-logs" "0.52.1" "@opentelemetry/exporter-trace-otlp-grpc@0.52.1": version "0.52.1" @@ -2345,10 +2345,10 @@ dependencies: "@grpc/grpc-js" "^1.7.1" "@opentelemetry/core" "1.25.1" + "@opentelemetry/otlp-grpc-exporter-base" "0.52.1" + "@opentelemetry/otlp-transformer" "0.52.1" "@opentelemetry/resources" "1.25.1" "@opentelemetry/sdk-trace-base" "1.25.1" - "@opentelemetry/otlp-transformer" "0.52.1" - "@opentelemetry/otlp-grpc-exporter-base" "0.52.1" "@opentelemetry/exporter-trace-otlp-http@0.52.1": version "0.52.1" @@ -2356,10 +2356,10 @@ integrity sha512-05HcNizx0BxcFKKnS5rwOV+2GevLTVIRA0tRgWYyw4yCgR53Ic/xk83toYKts7kbzcI+dswInUg/4s8oyA+tqg== dependencies: "@opentelemetry/core" "1.25.1" + "@opentelemetry/otlp-exporter-base" "0.52.1" + "@opentelemetry/otlp-transformer" "0.52.1" "@opentelemetry/resources" "1.25.1" "@opentelemetry/sdk-trace-base" "1.25.1" - "@opentelemetry/otlp-transformer" "0.52.1" - "@opentelemetry/otlp-exporter-base" "0.52.1" "@opentelemetry/exporter-trace-otlp-proto@0.52.1": version "0.52.1" @@ -2367,10 +2367,10 @@ integrity sha512-pt6uX0noTQReHXNeEslQv7x311/F1gJzMnp1HD2qgypLRPbXDeMzzeTngRTUaUbP6hqWNtPxuLr4DEoZG+TcEQ== dependencies: "@opentelemetry/core" "1.25.1" + "@opentelemetry/otlp-exporter-base" "0.52.1" + "@opentelemetry/otlp-transformer" "0.52.1" "@opentelemetry/resources" "1.25.1" "@opentelemetry/sdk-trace-base" "1.25.1" - "@opentelemetry/otlp-transformer" "0.52.1" - "@opentelemetry/otlp-exporter-base" "0.52.1" "@opentelemetry/exporter-zipkin@1.25.1": version "1.25.1" @@ -2387,24 +2387,24 @@ resolved "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz" integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw== dependencies: - semver "^7.5.2" - shimmer "^1.2.1" + "@opentelemetry/api-logs" "0.52.1" "@types/shimmer" "^1.0.2" import-in-the-middle "^1.8.1" require-in-the-middle "^7.1.1" - "@opentelemetry/api-logs" "0.52.1" + semver "^7.5.2" + shimmer "^1.2.1" "@opentelemetry/instrumentation@^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0": version "0.57.2" resolved "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz" integrity sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg== dependencies: - semver "^7.5.2" - shimmer "^1.2.1" + "@opentelemetry/api-logs" "0.57.2" "@types/shimmer" "^1.2.0" import-in-the-middle "^1.8.1" require-in-the-middle "^7.1.1" - "@opentelemetry/api-logs" "0.57.2" + semver "^7.5.2" + shimmer "^1.2.1" "@opentelemetry/otlp-exporter-base@0.52.1": version "0.52.1" @@ -2421,21 +2421,21 @@ dependencies: "@grpc/grpc-js" "^1.7.1" "@opentelemetry/core" "1.25.1" - "@opentelemetry/otlp-transformer" "0.52.1" "@opentelemetry/otlp-exporter-base" "0.52.1" + "@opentelemetry/otlp-transformer" "0.52.1" "@opentelemetry/otlp-transformer@0.52.1": version "0.52.1" resolved "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.52.1.tgz" integrity sha512-I88uCZSZZtVa0XniRqQWKbjAUm73I8tpEy/uJYPPYw5d7BRdVk0RfTBQw8kSUl01oVWEuqxLDa802222MYyWHg== dependencies: - protobufjs "^7.3.0" - "@opentelemetry/core" "1.25.1" "@opentelemetry/api-logs" "0.52.1" - "@opentelemetry/sdk-logs" "0.52.1" + "@opentelemetry/core" "1.25.1" "@opentelemetry/resources" "1.25.1" + "@opentelemetry/sdk-logs" "0.52.1" "@opentelemetry/sdk-metrics" "1.25.1" "@opentelemetry/sdk-trace-base" "1.25.1" + protobufjs "^7.3.0" "@opentelemetry/propagator-b3@1.25.1": version "1.25.1" @@ -2464,8 +2464,8 @@ resolved "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz" integrity sha512-MBYh+WcPPsN8YpRHRmK1Hsca9pVlyyKd4BxOC4SsgHACnl/bPp4Cri9hWhVm5+2tiQ9Zf4qSc1Jshw9tOLGWQA== dependencies: - "@opentelemetry/core" "1.25.1" "@opentelemetry/api-logs" "0.52.1" + "@opentelemetry/core" "1.25.1" "@opentelemetry/resources" "1.25.1" "@opentelemetry/sdk-metrics@1.25.1": @@ -2473,28 +2473,28 @@ resolved "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.25.1.tgz" integrity sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q== dependencies: - lodash.merge "^4.6.2" "@opentelemetry/core" "1.25.1" "@opentelemetry/resources" "1.25.1" + lodash.merge "^4.6.2" "@opentelemetry/sdk-node@0.52.1": version "0.52.1" resolved "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.52.1.tgz" integrity sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA== dependencies: - "@opentelemetry/core" "1.25.1" "@opentelemetry/api-logs" "0.52.1" - "@opentelemetry/sdk-logs" "0.52.1" + "@opentelemetry/core" "1.25.1" + "@opentelemetry/exporter-trace-otlp-grpc" "0.52.1" + "@opentelemetry/exporter-trace-otlp-http" "0.52.1" + "@opentelemetry/exporter-trace-otlp-proto" "0.52.1" + "@opentelemetry/exporter-zipkin" "1.25.1" + "@opentelemetry/instrumentation" "0.52.1" "@opentelemetry/resources" "1.25.1" + "@opentelemetry/sdk-logs" "0.52.1" "@opentelemetry/sdk-metrics" "1.25.1" "@opentelemetry/sdk-trace-base" "1.25.1" "@opentelemetry/sdk-trace-node" "1.25.1" - "@opentelemetry/exporter-zipkin" "1.25.1" - "@opentelemetry/instrumentation" "0.52.1" "@opentelemetry/semantic-conventions" "1.25.1" - "@opentelemetry/exporter-trace-otlp-grpc" "0.52.1" - "@opentelemetry/exporter-trace-otlp-http" "0.52.1" - "@opentelemetry/exporter-trace-otlp-proto" "0.52.1" "@opentelemetry/sdk-trace-base@1.25.1": version "1.25.1" @@ -2510,12 +2510,12 @@ resolved "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz" integrity sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ== dependencies: - semver "^7.5.2" + "@opentelemetry/context-async-hooks" "1.25.1" "@opentelemetry/core" "1.25.1" "@opentelemetry/propagator-b3" "1.25.1" - "@opentelemetry/sdk-trace-base" "1.25.1" "@opentelemetry/propagator-jaeger" "1.25.1" - "@opentelemetry/context-async-hooks" "1.25.1" + "@opentelemetry/sdk-trace-base" "1.25.1" + semver "^7.5.2" "@opentelemetry/semantic-conventions@1.25.1": version "1.25.1" @@ -2657,9 +2657,9 @@ resolved "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz" integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== dependencies: - config-chain "^1.1.11" - "@pnpm/network.ca-file" "^1.0.1" "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" "@popperjs/core@^2.11.8", "@popperjs/core@^2.9.0": version "2.11.8" @@ -2671,8 +2671,8 @@ resolved "https://registry.npmjs.org/@prisma/adapter-neon/-/adapter-neon-6.4.1.tgz" integrity sha512-9pgh5OR+tJfWCm6VNh6uxtUiBHvSKUBhCfrONMSMKmnYtPiY38bYwb5UXMwR+3CG+f4xmcACv0K7+UHWX8gaSw== dependencies: - postgres-array "3.0.2" "@prisma/driver-adapter-utils" "6.4.1" + postgres-array "3.0.2" "@prisma/client@>=2.26.0 || >=3 || >=4 || >=5 || >=6", "@prisma/client@>=4.16.1", "@prisma/client@^6.3.1": version "6.4.1" @@ -2697,9 +2697,9 @@ integrity sha512-KldENzMHtKYwsOSLThghOIdXOBEsfDuGSrxAZjMnimBiDKd3AE4JQ+Kv+gBD/x77WoV9xIPf25GXMWffXZ17BA== dependencies: "@prisma/debug" "6.4.1" + "@prisma/engines-version" "6.4.0-29.a9055b89e58b4b5bfb59600785423b1db3d0e75d" "@prisma/fetch-engine" "6.4.1" "@prisma/get-platform" "6.4.1" - "@prisma/engines-version" "6.4.0-29.a9055b89e58b4b5bfb59600785423b1db3d0e75d" "@prisma/engines-version@6.4.0-29.a9055b89e58b4b5bfb59600785423b1db3d0e75d": version "6.4.0-29.a9055b89e58b4b5bfb59600785423b1db3d0e75d" @@ -2717,8 +2717,8 @@ integrity sha512-uZ5hVeTmDspx7KcaRCNoXmcReOD+84nwlO2oFvQPRQh9xiFYnnUKDz7l9bLxp8t4+25CsaNlgrgilXKSQwrIGQ== dependencies: "@prisma/debug" "6.4.1" - "@prisma/get-platform" "6.4.1" "@prisma/engines-version" "6.4.0-29.a9055b89e58b4b5bfb59600785423b1db3d0e75d" + "@prisma/get-platform" "6.4.1" "@prisma/get-platform@6.4.1": version "6.4.1" @@ -2796,9 +2796,9 @@ extract-zip "^2.0.1" progress "^2.0.3" proxy-agent "^6.5.0" + semver "^7.7.1" tar-fs "^3.0.8" yargs "^17.7.2" - semver "^7.7.1" "@radix-ui/number@1.1.0": version "1.1.0" @@ -2822,14 +2822,14 @@ resolved "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.3.tgz" integrity sha512-RIQ15mrcvqIkDARJeERSuXSry2N8uYnxkdDetpfmalT/+0ntOXLkFOsh9iwlAsCv+qcmhZjbdJogIm6WBa6c4A== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collapsible" "1.1.3" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-collapsible" "1.1.3" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-alert-dialog@^1.1.2": @@ -2838,11 +2838,11 @@ integrity sha512-p4XnPqgej8sZAAReCAKgz1REYZEBLR8hU9Pg27wFnCWIMc8g1ccCs0FjBcy05V15VTu8pAePw/VDYeOm/uZ6yQ== dependencies: "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-slot" "1.1.2" - "@radix-ui/react-dialog" "1.1.6" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dialog" "1.1.6" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-arrow@1.1.2": version "1.1.2" @@ -2867,37 +2867,37 @@ integrity sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw== dependencies: "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-previous" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-collapsible@1.1.3", "@radix-ui/react-collapsible@^1.1.1": version "1.1.3" resolved "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz" integrity sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-collection@1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz" integrity sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw== dependencies: - "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-compose-refs@1.0.0": version "1.0.0" @@ -2929,8 +2929,8 @@ integrity sha512-aUP99QZ3VU84NPsHeaFt4cQUNgJqFsLLOt/RbbWXszZ6MP0DpDyjkFZORr4RpAEx3sUBk+Kc8h13yGtC5Qw8dg== dependencies: "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-menu" "2.1.6" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-menu" "2.1.6" "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" @@ -2940,41 +2940,41 @@ resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.0.tgz" integrity sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q== dependencies: - aria-hidden "^1.1.1" "@babel/runtime" "^7.13.10" - "@radix-ui/react-id" "1.0.0" "@radix-ui/primitive" "1.0.0" - react-remove-scroll "2.5.4" - "@radix-ui/react-slot" "1.0.0" - "@radix-ui/react-portal" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-focus-guards" "1.0.0" + "@radix-ui/react-focus-scope" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-portal" "1.0.0" "@radix-ui/react-presence" "1.0.0" "@radix-ui/react-primitive" "1.0.0" - "@radix-ui/react-focus-scope" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-focus-guards" "1.0.0" - "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-slot" "1.0.0" "@radix-ui/react-use-controllable-state" "1.0.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.4" "@radix-ui/react-dialog@1.1.6", "@radix-ui/react-dialog@^1.1.1", "@radix-ui/react-dialog@^1.1.2": version "1.1.6" resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz" integrity sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw== dependencies: - aria-hidden "^1.2.4" - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - react-remove-scroll "^2.6.3" - "@radix-ui/react-slot" "1.1.2" - "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-portal" "1.1.4" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-focus-scope" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" "@radix-ui/react-direction@1.1.0": version "1.1.0" @@ -2988,8 +2988,8 @@ dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-use-escape-keydown" "1.0.0" @@ -2999,8 +2999,8 @@ integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== dependencies: "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-escape-keydown" "1.1.0" @@ -3009,12 +3009,12 @@ resolved "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz" integrity sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-menu" "2.1.6" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-menu" "2.1.6" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-focus-guards@1.0.0": @@ -3035,8 +3035,8 @@ integrity sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-focus-scope@1.1.2": @@ -3044,8 +3044,8 @@ resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz" integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== dependencies: - "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-hover-card@^1.1.2": @@ -3054,13 +3054,13 @@ integrity sha512-E4ozl35jq0VRlrdc4dhHrNSV0JqBb4Jy73WAhBEK7JoYnQ83ED5r0Rb/XdVKw89ReAJN38N492BAPBZQ57VmqQ== dependencies: "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" "@radix-ui/react-popper" "1.2.2" "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-context" "1.1.1" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.5" "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-icons@^1.3.0": @@ -3095,81 +3095,81 @@ resolved "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.6.tgz" integrity sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg== dependencies: - aria-hidden "^1.2.4" - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - react-remove-scroll "^2.6.3" - "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-popper" "1.2.2" "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-context" "1.1.1" "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-direction" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-focus-scope" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-focus-guards" "1.1.1" "@radix-ui/react-roving-focus" "1.1.2" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.5" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" "@radix-ui/react-navigation-menu@^1.2.1": version "1.2.5" resolved "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.5.tgz" integrity sha512-myMHHQUZ3ZLTi8W381/Vu43Ia0NqakkQZ2vzynMmTUtQQ9kNkjzhOwkZC9TAM5R07OZUVIQyHC06f/9JZJpvvA== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-previous" "1.1.0" - "@radix-ui/react-visually-hidden" "1.1.2" "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.5" - "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" "@radix-ui/react-popover@^1.1.2": version "1.1.6" resolved "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.6.tgz" integrity sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg== dependencies: - aria-hidden "^1.2.4" - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - react-remove-scroll "^2.6.3" - "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-popper" "1.2.2" "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-context" "1.1.1" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-focus-scope" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" "@radix-ui/react-popper@1.2.2": version "1.2.2" resolved "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz" integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== dependencies: - "@radix-ui/rect" "1.1.0" - "@radix-ui/react-arrow" "1.1.2" "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-use-rect" "1.1.0" - "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" "@radix-ui/react-portal@1.0.0": version "1.0.0" @@ -3233,28 +3233,28 @@ integrity sha512-xtCsqt8Rp09FK50ItqEqTJ7Sxanz8EM8dnkVIhJrc/wkMMomSmXHvYbhv3E7Zx4oXh98aaLt9W679SUYXg4IDA== dependencies: "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-roving-focus" "1.1.2" - "@radix-ui/react-use-previous" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-roving-focus@1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz" integrity sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" @@ -3265,11 +3265,11 @@ dependencies: "@radix-ui/number" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect" "1.1.0" @@ -3278,27 +3278,27 @@ resolved "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz" integrity sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg== dependencies: - aria-hidden "^1.2.4" "@radix-ui/number" "1.1.0" - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - react-remove-scroll "^2.6.3" - "@radix-ui/react-slot" "1.1.2" - "@radix-ui/react-popper" "1.2.2" - "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-direction" "1.1.0" - "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-focus-scope" "1.1.2" "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.5" "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-use-previous" "1.1.0" - "@radix-ui/react-visually-hidden" "1.1.2" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.5" - "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" "@radix-ui/react-separator@^1.1.0": version "1.1.2" @@ -3314,15 +3314,15 @@ dependencies: "@radix-ui/number" "1.1.0" "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-direction" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-previous" "1.1.0" - "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-slot@1.0.0": version "1.0.0" @@ -3345,23 +3345,23 @@ integrity sha512-1nc+vjEOQkJVsJtWPSiISGT6OKm4SiOdjMo+/icLxo2G4vxz1GntC5MzfL4v8ey9OEfw787QCD1y3mUv0NiFEQ== dependencies: "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-previous" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" "@radix-ui/react-tabs@^1.1.1": version "1.1.3" resolved "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz" integrity sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-roving-focus" "1.1.2" "@radix-ui/react-use-controllable-state" "1.1.0" @@ -3372,35 +3372,35 @@ integrity sha512-gN4dpuIVKEgpLn1z5FhzT9mYRUitbfZq9XqN/7kkBMUgFTzTG8x/KszWJugJXHcwxckY8xcKDZPz7kG3o6DsUA== dependencies: "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-portal" "1.1.4" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-collection" "1.1.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-visually-hidden" "1.1.2" "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.5" - "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" "@radix-ui/react-tooltip@^1.1.3": version "1.1.8" resolved "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.8.tgz" integrity sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA== dependencies: - "@radix-ui/react-id" "1.1.0" "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-id" "1.1.0" "@radix-ui/react-popper" "1.2.2" "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-context" "1.1.1" "@radix-ui/react-presence" "1.1.2" "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-visually-hidden" "1.1.2" - "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-slot" "1.1.2" "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" "@radix-ui/react-use-callback-ref@1.0.0": version "1.0.0" @@ -3519,26 +3519,26 @@ resolved "https://registry.npmjs.org/@react-email/components/-/components-0.0.31.tgz" integrity sha512-rQsTY9ajobncix9raexhBjC7O6cXUMc87eNez2gnB1FwtkUO8DqWZcktbtwOJi7GKmuAPTx0o/IOFtiBNXziKA== dependencies: - "@react-email/hr" "0.0.11" - "@react-email/img" "0.0.11" - "@react-email/row" "0.0.12" "@react-email/body" "0.0.11" + "@react-email/button" "0.0.19" + "@react-email/code-block" "0.0.11" + "@react-email/code-inline" "0.0.5" + "@react-email/column" "0.0.13" + "@react-email/container" "0.0.15" "@react-email/font" "0.0.9" "@react-email/head" "0.0.12" + "@react-email/heading" "0.0.15" + "@react-email/hr" "0.0.11" "@react-email/html" "0.0.11" + "@react-email/img" "0.0.11" "@react-email/link" "0.0.12" - "@react-email/text" "0.0.11" - "@react-email/button" "0.0.19" - "@react-email/column" "0.0.13" - "@react-email/render" "1.0.3" - "@react-email/heading" "0.0.15" + "@react-email/markdown" "0.0.14" "@react-email/preview" "0.0.12" + "@react-email/render" "1.0.3" + "@react-email/row" "0.0.12" "@react-email/section" "0.0.16" - "@react-email/markdown" "0.0.14" "@react-email/tailwind" "1.0.4" - "@react-email/container" "0.0.15" - "@react-email/code-block" "0.0.11" - "@react-email/code-inline" "0.0.5" + "@react-email/text" "0.0.11" "@react-email/container@0.0.15": version "0.0.15" @@ -3597,18 +3597,18 @@ resolved "https://registry.npmjs.org/@react-email/render/-/render-0.0.10.tgz" integrity sha512-FdLhg/E5PH5qZU/jf9NbvRi5v5134kbX7o8zIhOJIk/TALxB18ggprnH5tQX96dGQFqlLob8OLReaRwrpEF7YA== dependencies: - react "18.2.0" + html-to-text "9.0.5" pretty "2.0.0" + react "18.2.0" react-dom "18.2.0" - html-to-text "9.0.5" "@react-email/render@1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@react-email/render/-/render-1.0.1.tgz" integrity sha512-W3gTrcmLOVYnG80QuUp22ReIT/xfLsVJ+n7ghSlG2BITB8evNABn1AO2rGQoXuK84zKtDAlxCdm3hRyIpZdGSA== dependencies: - js-beautify "^1.14.11" html-to-text "9.0.5" + js-beautify "^1.14.11" react-promise-suspense "0.3.4" "@react-email/render@1.0.3": @@ -3616,8 +3616,8 @@ resolved "https://registry.npmjs.org/@react-email/render/-/render-1.0.3.tgz" integrity sha512-VQ8g4SuIq/jWdfBTdTjb7B8Np0jj+OoD7VebfdHhLTZzVQKesR2aigpYqE/ZXmwj4juVxDm8T2b6WIIu48rPCg== dependencies: - prettier "3.3.3" html-to-text "9.0.5" + prettier "3.3.3" react-promise-suspense "0.3.4" "@react-email/row@0.0.12": @@ -3677,10 +3677,10 @@ resolved "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.4.1.tgz" integrity sha512-kV0Pf33HnthuBOVdYNani21kYyj118Fn+9757bxqoksiXoZlYvBsFq6giNdCsKcTIE1eAMqNDq3xE1VQ0cfsHA== dependencies: - dset "^3.1.2" - tslib "^2.4.1" "@lukeed/uuid" "^2.0.0" "@segment/analytics-generic-utils" "1.1.1" + dset "^3.1.2" + tslib "^2.4.1" "@segment/analytics-generic-utils@1.1.1": version "1.1.1" @@ -3694,12 +3694,12 @@ resolved "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-1.3.0.tgz" integrity sha512-lRLz1WZaDokMoUe299yP5JkInc3OgJuqNNlxb6j0q22umCiq6b5iDo2gRmFn93reirIvJxWIicQsGrHd93q8GQ== dependencies: - tslib "^2.4.1" - buffer "^6.0.3" - node-fetch "^2.6.7" "@lukeed/uuid" "^2.0.0" "@segment/analytics-core" "1.4.1" "@segment/analytics-generic-utils" "1.1.1" + buffer "^6.0.3" + node-fetch "^2.6.7" + tslib "^2.4.1" "@selderee/plugin-htmlparser2@^0.11.0": version "0.11.0" @@ -3709,12 +3709,12 @@ domhandler "^5.0.3" selderee "^0.11.0" -"@simplewebauthn/browser@^13.0.0": +"@simplewebauthn/browser@^13.0.0", "@simplewebauthn/browser@^9.0.1": version "13.1.0" resolved "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.0.tgz" integrity sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg== -"@simplewebauthn/server@^13.0.0": +"@simplewebauthn/server@^13.0.0", "@simplewebauthn/server@^9.0.2": version "13.1.1" resolved "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.1.1.tgz" integrity sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA== @@ -3732,20 +3732,20 @@ resolved "https://registry.npmjs.org/@slack/bolt/-/bolt-3.22.0.tgz" integrity sha512-iKDqGPEJDnrVwxSVlFW6OKTkijd7s4qLBeSufoBsTM0reTyfdp/5izIQVkxNfzjHi3o6qjdYbRXkYad5HBsBog== dependencies: - axios "^1.7.4" - tsscmp "^1.0.6" - express "^4.21.0" - raw-body "^2.3.3" + "@slack/logger" "^4.0.0" "@slack/oauth" "^2.6.3" + "@slack/socket-mode" "^1.3.6" "@slack/types" "^2.13.0" - "@slack/logger" "^4.0.0" - "@types/tsscmp" "^1.0.0" "@slack/web-api" "^6.13.0" "@types/express" "^4.16.1" + "@types/promise.allsettled" "^1.0.3" + "@types/tsscmp" "^1.0.0" + axios "^1.7.4" + express "^4.21.0" path-to-regexp "^8.1.0" - "@slack/socket-mode" "^1.3.6" promise.allsettled "^1.0.2" - "@types/promise.allsettled" "^1.0.3" + raw-body "^2.3.3" + tsscmp "^1.0.6" "@slack/logger@^3.0.0": version "3.0.0" @@ -3766,25 +3766,25 @@ resolved "https://registry.npmjs.org/@slack/oauth/-/oauth-2.6.3.tgz" integrity sha512-1amXs6xRkJpoH6zSgjVPgGEJXCibKNff9WNDijcejIuVy1HFAl1adh7lehaGNiHhTWfQkfKxBiF+BGn56kvoFw== dependencies: - "@types/node" ">=12" - jsonwebtoken "^9.0.0" "@slack/logger" "^3.0.0" "@slack/web-api" "^6.12.1" - lodash.isstring "^4.0.1" "@types/jsonwebtoken" "^8.3.7" + "@types/node" ">=12" + jsonwebtoken "^9.0.0" + lodash.isstring "^4.0.1" "@slack/socket-mode@^1.3.6": version "1.3.6" resolved "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-1.3.6.tgz" integrity sha512-G+im7OP7jVqHhiNSdHgv2VVrnN5U7KY845/5EZimZkrD4ZmtV0P3BiWkgeJhPtdLuM7C7i6+M6h6Bh+S4OOalA== dependencies: - ws "^7.5.3" - finity "^0.5.4" - "@types/ws" "^7.4.7" - "@types/node" ">=12.0.0" "@slack/logger" "^3.0.0" - eventemitter3 "^5" "@slack/web-api" "^6.12.1" + "@types/node" ">=12.0.0" + "@types/ws" "^7.4.7" + eventemitter3 "^5" + finity "^0.5.4" + ws "^7.5.3" "@slack/types@^2.11.0", "@slack/types@^2.13.0", "@slack/types@^2.9.0": version "2.14.0" @@ -3796,35 +3796,35 @@ resolved "https://registry.npmjs.org/@slack/web-api/-/web-api-6.13.0.tgz" integrity sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g== dependencies: + "@slack/logger" "^3.0.0" + "@slack/types" "^2.11.0" + "@types/is-stream" "^1.1.0" + "@types/node" ">=12.0.0" axios "^1.7.4" - p-queue "^6.6.1" - p-retry "^4.0.0" + eventemitter3 "^3.1.0" form-data "^2.5.0" - is-stream "^1.1.0" - "@types/node" ">=12.0.0" is-electron "2.2.2" - "@slack/types" "^2.11.0" - "@slack/logger" "^3.0.0" - eventemitter3 "^3.1.0" - "@types/is-stream" "^1.1.0" + is-stream "^1.1.0" + p-queue "^6.6.1" + p-retry "^4.0.0" "@slack/web-api@^7.8.0": version "7.8.0" resolved "https://registry.npmjs.org/@slack/web-api/-/web-api-7.8.0.tgz" integrity sha512-d4SdG+6UmGdzWw38a4sN3lF/nTEzsDxhzU13wm10ejOpPehtmRoqBKnPztQUfFiWbNvSb4czkWYJD4kt+5+Fuw== dependencies: - axios "^1.7.8" - retry "^0.13.1" - p-queue "^6" - p-retry "^4" - form-data "^4.0.0" - is-stream "^2" - "@types/node" ">=18.0.0" - is-electron "2.2.2" + "@slack/logger" "^4.0.0" "@slack/types" "^2.9.0" + "@types/node" ">=18.0.0" "@types/retry" "0.12.0" - "@slack/logger" "^4.0.0" + axios "^1.7.8" eventemitter3 "^5.0.1" + form-data "^4.0.0" + is-electron "2.2.2" + is-stream "^2" + p-queue "^6" + p-retry "^4" + retry "^0.13.1" "@smithy/abort-controller@^4.0.1": version "4.0.1" @@ -3846,8 +3846,8 @@ resolved "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz" integrity sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig== dependencies: - tslib "^2.6.2" "@smithy/util-base64" "^4.0.0" + tslib "^2.6.2" "@smithy/config-resolver@^4.0.1": version "4.0.1" @@ -4172,9 +4172,9 @@ resolved "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz" integrity sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg== dependencies: - tslib "^2.6.2" - "@smithy/util-utf8" "^4.0.0" "@smithy/util-buffer-from" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" "@smithy/util-body-length-browser@^4.0.0": version "4.0.0" @@ -4195,16 +4195,16 @@ resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz" integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== dependencies: - tslib "^2.6.2" "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" "@smithy/util-buffer-from@^4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz" integrity sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug== dependencies: - tslib "^2.6.2" "@smithy/is-array-buffer" "^4.0.0" + tslib "^2.6.2" "@smithy/util-config-provider@^4.0.0": version "4.0.0" @@ -4296,16 +4296,16 @@ resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz" integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== dependencies: - tslib "^2.6.2" "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" "@smithy/util-utf8@^4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz" integrity sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow== dependencies: - tslib "^2.6.2" "@smithy/util-buffer-from" "^4.0.0" + tslib "^2.6.2" "@smithy/util-waiter@^4.0.2": version "4.0.2" @@ -4391,9 +4391,9 @@ resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz" integrity sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA== dependencies: - lodash.merge "^4.6.2" lodash.castarray "^4.4.0" lodash.isplainobject "^4.0.6" + lodash.merge "^4.6.2" postcss-selector-parser "6.0.10" "@tanstack/query-core@^4.15.1": @@ -4621,62 +4621,62 @@ resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.5.tgz" integrity sha512-z9JFtqc5ZOsdQLd9vRnXfTCQ8v5ADAfRt9Nm7SqP6FUHII8E1hs38ACzf5xursmth/VonJYb5+73Pqxk1hGIPw== dependencies: - prosemirror-menu "^1.2.4" - prosemirror-view "^1.37.0" - prosemirror-model "^1.23.0" - prosemirror-state "^1.4.3" + prosemirror-changeset "^2.2.1" prosemirror-collab "^1.3.1" - prosemirror-keymap "^1.2.2" - prosemirror-tables "^1.6.3" - prosemirror-history "^1.4.1" prosemirror-commands "^1.6.2" - prosemirror-markdown "^1.13.1" - prosemirror-changeset "^2.2.1" - prosemirror-gapcursor "^1.3.2" - prosemirror-transform "^1.10.2" prosemirror-dropcursor "^1.8.1" + prosemirror-gapcursor "^1.3.2" + prosemirror-history "^1.4.1" prosemirror-inputrules "^1.4.0" - prosemirror-schema-list "^1.4.1" + prosemirror-keymap "^1.2.2" + prosemirror-markdown "^1.13.1" + prosemirror-menu "^1.2.4" + prosemirror-model "^1.23.0" prosemirror-schema-basic "^1.2.3" + prosemirror-schema-list "^1.4.1" + prosemirror-state "^1.4.3" + prosemirror-tables "^1.6.3" prosemirror-trailing-node "^3.0.0" + prosemirror-transform "^1.10.2" + prosemirror-view "^1.37.0" "@tiptap/react@^2.11.2", "@tiptap/react@^2.11.5", "@tiptap/react@^2.9.1": version "2.11.5" resolved "https://registry.npmjs.org/@tiptap/react/-/react-2.11.5.tgz" integrity sha512-Dp8eHL1G+R/C4+QzAczyb3t1ovexEIZx9ln7SGEM+cT1KHKAw9XGPRgsp92+NQaYI+EdEb/YqoBOSzQcd18/OQ== dependencies: - fast-deep-equal "^3" - use-sync-external-store "^1" "@tiptap/extension-bubble-menu" "^2.11.5" - "@types/use-sync-external-store" "^0.0.6" "@tiptap/extension-floating-menu" "^2.11.5" + "@types/use-sync-external-store" "^0.0.6" + fast-deep-equal "^3" + use-sync-external-store "^1" "@tiptap/starter-kit@^2.11.2", "@tiptap/starter-kit@^2.11.5", "@tiptap/starter-kit@^2.9.1": version "2.11.5" resolved "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.11.5.tgz" integrity sha512-SLI7Aj2ruU1t//6Mk8f+fqW+18uTqpdfLUJYgwu0CkqBckrkRZYZh6GVLk/02k3H2ki7QkFxiFbZrdbZdng0JA== dependencies: - "@tiptap/pm" "^2.11.5" "@tiptap/core" "^2.11.5" + "@tiptap/extension-blockquote" "^2.11.5" "@tiptap/extension-bold" "^2.11.5" + "@tiptap/extension-bullet-list" "^2.11.5" "@tiptap/extension-code" "^2.11.5" - "@tiptap/extension-text" "^2.11.5" - "@tiptap/extension-italic" "^2.11.5" - "@tiptap/extension-strike" "^2.11.5" - "@tiptap/extension-heading" "^2.11.5" - "@tiptap/extension-history" "^2.11.5" + "@tiptap/extension-code-block" "^2.11.5" "@tiptap/extension-document" "^2.11.5" + "@tiptap/extension-dropcursor" "^2.11.5" "@tiptap/extension-gapcursor" "^2.11.5" + "@tiptap/extension-hard-break" "^2.11.5" + "@tiptap/extension-heading" "^2.11.5" + "@tiptap/extension-history" "^2.11.5" + "@tiptap/extension-horizontal-rule" "^2.11.5" + "@tiptap/extension-italic" "^2.11.5" "@tiptap/extension-list-item" "^2.11.5" + "@tiptap/extension-ordered-list" "^2.11.5" "@tiptap/extension-paragraph" "^2.11.5" - "@tiptap/extension-blockquote" "^2.11.5" - "@tiptap/extension-code-block" "^2.11.5" - "@tiptap/extension-dropcursor" "^2.11.5" - "@tiptap/extension-hard-break" "^2.11.5" + "@tiptap/extension-strike" "^2.11.5" + "@tiptap/extension-text" "^2.11.5" "@tiptap/extension-text-style" "^2.11.5" - "@tiptap/extension-bullet-list" "^2.11.5" - "@tiptap/extension-ordered-list" "^2.11.5" - "@tiptap/extension-horizontal-rule" "^2.11.5" + "@tiptap/pm" "^2.11.5" "@tiptap/suggestion@^2.11.2": version "2.11.5" @@ -4703,32 +4703,32 @@ resolved "https://registry.npmjs.org/@trigger.dev/core/-/core-3.3.13.tgz" integrity sha512-3VU4YMS+RVCkfVXeUKSWlkVszgFK44tIknR9sHLYgetI714L3tgH47XBXJ3+/ZV5Y9Vvv6O6pRIuV7EEhzbexg== dependencies: - zod "3.23.8" - jose "^5.4.0" - execa "^8.0.1" - dequal "^2.0.3" - nanoid "^3.3.4" - superjson "^2.2.1" - zod-error "1.5.0" - eventsource "^3.0.5" + "@electric-sql/client" "1.0.0-beta.1" + "@google-cloud/precise-date" "^4.0.0" "@jsonhero/path" "^1.0.21" - socket.io-client "4.7.5" - humanize-duration "^3.27.3" "@opentelemetry/api" "1.9.0" - eventsource-parser "^3.0.0" - "@electric-sql/client" "1.0.0-beta.1" - zod-validation-error "^1.5.0" "@opentelemetry/api-logs" "0.52.1" + "@opentelemetry/exporter-logs-otlp-http" "0.52.1" + "@opentelemetry/exporter-trace-otlp-http" "0.52.1" + "@opentelemetry/instrumentation" "0.52.1" + "@opentelemetry/resources" "1.25.1" "@opentelemetry/sdk-logs" "0.52.1" "@opentelemetry/sdk-node" "0.52.1" - "@opentelemetry/resources" "1.25.1" - "@google-cloud/precise-date" "^4.0.0" "@opentelemetry/sdk-trace-base" "1.25.1" "@opentelemetry/sdk-trace-node" "1.25.1" - "@opentelemetry/instrumentation" "0.52.1" "@opentelemetry/semantic-conventions" "1.25.1" - "@opentelemetry/exporter-logs-otlp-http" "0.52.1" - "@opentelemetry/exporter-trace-otlp-http" "0.52.1" + dequal "^2.0.3" + eventsource "^3.0.5" + eventsource-parser "^3.0.0" + execa "^8.0.1" + humanize-duration "^3.27.3" + jose "^5.4.0" + nanoid "^3.3.4" + socket.io-client "4.7.5" + superjson "^2.2.1" + zod "3.23.8" + zod-error "1.5.0" + zod-validation-error "^1.5.0" "@trigger.dev/core@3.3.17", "@trigger.dev/core@^3.3.17": version "3.3.17" @@ -4775,19 +4775,19 @@ resolved "https://registry.npmjs.org/@trigger.dev/sdk/-/sdk-3.3.13.tgz" integrity sha512-iXtHMnzvzmPfBk7+whpWOElBJt6viCoA3r8xgrrrurj8oxjIVe4UvdDiB7wbUJJ44WROWEb0wVKyQut1L/FwQQ== dependencies: - ws "^8.11.0" + "@opentelemetry/api" "1.9.0" + "@opentelemetry/api-logs" "0.52.1" + "@opentelemetry/semantic-conventions" "1.25.1" + "@trigger.dev/core" "3.3.13" + chalk "^5.2.0" + cronstrue "^2.21.0" + debug "^4.3.4" evt "^2.4.13" slug "^6.0.0" + terminal-link "^3.0.0" ulid "^2.3.0" uuid "^9.0.0" - chalk "^5.2.0" - debug "^4.3.4" - cronstrue "^2.21.0" - terminal-link "^3.0.0" - "@trigger.dev/core" "3.3.13" - "@opentelemetry/api" "1.9.0" - "@opentelemetry/api-logs" "0.52.1" - "@opentelemetry/semantic-conventions" "1.25.1" + ws "^8.11.0" "@trigger.dev/sdk@3.3.17", "@trigger.dev/sdk@^3.3.15": version "3.3.17" @@ -4824,8 +4824,8 @@ resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz" integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: - "@types/node" "*" "@types/connect" "*" + "@types/node" "*" "@types/connect@*": version "3.4.38" @@ -4858,36 +4858,36 @@ resolved "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz" integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== dependencies: - "@types/d3-dsv" "*" - "@types/d3-geo" "*" - "@types/d3-axis" "*" - "@types/d3-drag" "*" - "@types/d3-ease" "*" - "@types/d3-path" "*" - "@types/d3-time" "*" - "@types/d3-zoom" "*" "@types/d3-array" "*" + "@types/d3-axis" "*" "@types/d3-brush" "*" "@types/d3-chord" "*" "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" "@types/d3-fetch" "*" "@types/d3-force" "*" - "@types/d3-scale" "*" - "@types/d3-shape" "*" - "@types/d3-timer" "*" "@types/d3-format" "*" - "@types/d3-random" "*" - "@types/d3-contour" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" "@types/d3-polygon" "*" - "@types/d3-delaunay" "*" - "@types/d3-dispatch" "*" "@types/d3-quadtree" "*" - "@types/d3-hierarchy" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" "@types/d3-selection" "*" - "@types/d3-transition" "*" - "@types/d3-interpolate" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" "@types/d3-time-format" "*" - "@types/d3-scale-chromatic" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" "@types/d3-array@*", "@types/d3-array@^3.0.3": version "3.2.1" @@ -4923,8 +4923,8 @@ resolved "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz" integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== dependencies: - "@types/geojson" "*" "@types/d3-array" "*" + "@types/geojson" "*" "@types/d3-delaunay@*": version "6.0.4" @@ -5060,8 +5060,8 @@ resolved "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz" integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== dependencies: - "@types/d3-selection" "*" "@types/d3-interpolate" "*" + "@types/d3-selection" "*" "@types/debug@^4.0.0": version "4.1.12" @@ -5092,20 +5092,20 @@ resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: - "@types/qs" "*" "@types/body-parser" "*" - "@types/serve-static" "*" "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" "@types/express-serve-static-core@^4.17.33": version "4.19.6" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz" integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== dependencies: - "@types/qs" "*" "@types/node" "*" - "@types/send" "*" + "@types/qs" "*" "@types/range-parser" "*" + "@types/send" "*" "@types/geojson@*": version "7946.0.16" @@ -5153,8 +5153,8 @@ resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz" integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== dependencies: - "@types/mdurl" "^2" "@types/linkify-it" "^5" + "@types/mdurl" "^2" "@types/mdast@^4.0.0": version "4.0.4" @@ -5197,17 +5197,17 @@ resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz" integrity sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA== dependencies: - form-data "^4.0.0" "@types/node" "*" + form-data "^4.0.0" "@types/pg@8.11.6": version "8.11.6" resolved "https://registry.npmjs.org/@types/pg/-/pg-8.11.6.tgz" integrity sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ== dependencies: - pg-types "^4.0.1" "@types/node" "*" pg-protocol "*" + pg-types "^4.0.1" "@types/promise.allsettled@^1.0.3": version "1.0.6" @@ -5229,14 +5229,14 @@ resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== -"@types/react@*", "@types/react@19.0.10", "@types/react@>=18", "@types/react@^19.0.0", "@types/react@^19.0.8": +"@types/react@*", "@types/react@19.0.10", "@types/react@>=16.8", "@types/react@>=17.0.0", "@types/react@>=18", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^19.0.0", "@types/react@^19.0.8": version "19.0.10" resolved "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz" integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g== dependencies: csstype "^3.0.2" -"@types/react-dom@19.0.4", "@types/react-dom@^19.0.0", "@types/react-dom@^19.0.3": +"@types/react-dom@*", "@types/react-dom@19.0.4", "@types/react-dom@^19.0.0", "@types/react-dom@^19.0.3": version "19.0.4" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz" integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg== @@ -5264,9 +5264,9 @@ resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz" integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== dependencies: + "@types/http-errors" "*" "@types/node" "*" "@types/send" "*" - "@types/http-errors" "*" "@types/shimmer@^1.0.2", "@types/shimmer@^1.2.0": version "1.2.0" @@ -5339,17 +5339,17 @@ resolved "https://registry.npmjs.org/@uploadthing/react/-/react-7.3.0.tgz" integrity sha512-rSH9BpPy2/G7nZ3SEbZQANUFHkBCS5CwWiVzmOW9fzFNoqF+buqBvi5FDweffqMSwmr+/VS8Wpyj87/GYbV0Fw== dependencies: - file-selector "0.6.0" "@uploadthing/shared" "7.1.7" + file-selector "0.6.0" "@uploadthing/shared@7.1.7": version "7.1.7" resolved "https://registry.npmjs.org/@uploadthing/shared/-/shared-7.1.7.tgz" integrity sha512-VDvGmyHhdwaivC+eee77yZnOVvz59mOmLVbcuYFo4SkoNvPuc3AyPORqJJMBveQivTvELdrQcjlx6IPv98JkSA== dependencies: - sqids "^0.3.0" - effect "3.12.0" "@uploadthing/mime-types" "0.3.4" + effect "3.12.0" + sqids "^0.3.0" "@upstash/core-analytics@^0.0.10": version "0.0.10" @@ -5377,9 +5377,9 @@ resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz" integrity sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q== dependencies: - entities "^4.5.0" - "@vue/shared" "3.5.13" "@babel/parser" "^7.25.3" + "@vue/shared" "3.5.13" + entities "^4.5.0" estree-walker "^2.0.2" source-map-js "^1.2.0" @@ -5388,31 +5388,31 @@ resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz" integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA== dependencies: - "@vue/shared" "3.5.13" "@vue/compiler-core" "3.5.13" + "@vue/shared" "3.5.13" "@vue/compiler-sfc@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz" integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ== dependencies: - postcss "^8.4.48" - "@vue/shared" "3.5.13" - magic-string "^0.30.11" "@babel/parser" "^7.25.3" - estree-walker "^2.0.2" - source-map-js "^1.2.0" + "@vue/compiler-core" "3.5.13" "@vue/compiler-dom" "3.5.13" "@vue/compiler-ssr" "3.5.13" - "@vue/compiler-core" "3.5.13" + "@vue/shared" "3.5.13" + estree-walker "^2.0.2" + magic-string "^0.30.11" + postcss "^8.4.48" + source-map-js "^1.2.0" "@vue/compiler-ssr@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz" integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA== dependencies: - "@vue/shared" "3.5.13" "@vue/compiler-dom" "3.5.13" + "@vue/shared" "3.5.13" "@vue/reactivity@3.5.13": version "3.5.13" @@ -5426,26 +5426,26 @@ resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz" integrity sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw== dependencies: - "@vue/shared" "3.5.13" "@vue/reactivity" "3.5.13" + "@vue/shared" "3.5.13" "@vue/runtime-dom@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz" integrity sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog== dependencies: - csstype "^3.1.3" - "@vue/shared" "3.5.13" "@vue/reactivity" "3.5.13" "@vue/runtime-core" "3.5.13" + "@vue/shared" "3.5.13" + csstype "^3.1.3" "@vue/server-renderer@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz" integrity sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA== dependencies: - "@vue/shared" "3.5.13" "@vue/compiler-ssr" "3.5.13" + "@vue/shared" "3.5.13" "@vue/shared@3.5.13": version "3.5.13" @@ -5509,19 +5509,19 @@ ai@3.4.33, ai@^3.4.33: resolved "https://registry.npmjs.org/ai/-/ai-3.4.33.tgz" integrity sha512-plBlrVZKwPoRTmM8+D1sJac9Bq8eaa2jiZlHLZIWekKWI1yMWYZvCCEezY9ASPwRhULYDJB2VhKOBUUeg3S5JQ== dependencies: - "@ai-sdk/vue" "0.0.59" - json-schema "^0.4.0" + "@ai-sdk/provider" "0.0.26" + "@ai-sdk/provider-utils" "1.0.22" "@ai-sdk/react" "0.0.70" "@ai-sdk/solid" "0.0.54" - jsondiffpatch "0.6.0" "@ai-sdk/svelte" "0.0.57" - "@ai-sdk/provider" "0.0.26" "@ai-sdk/ui-utils" "0.0.50" - secure-json-parse "^2.7.0" + "@ai-sdk/vue" "0.0.59" "@opentelemetry/api" "1.9.0" eventsource-parser "1.1.2" + json-schema "^0.4.0" + jsondiffpatch "0.6.0" + secure-json-parse "^2.7.0" zod-to-json-schema "^3.23.3" - "@ai-sdk/provider-utils" "1.0.22" ai@^4.1.41: version "4.1.54" @@ -5540,10 +5540,10 @@ ajv@^6.12.3: resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - uri-js "^4.2.2" fast-deep-equal "^3.1.1" - json-schema-traverse "^0.4.1" fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" ansi-escapes@^4.2.1: version "4.3.2" @@ -5596,8 +5596,8 @@ anymatch@~3.1.2: resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: - picomatch "^2.0.4" normalize-path "^3.0.0" + picomatch "^2.0.4" aproba@^1.0.3: version "1.2.0" @@ -5808,7 +5808,7 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bare-events@^2.0.0, bare-events@^2.2.0: +bare-events@*, bare-events@^2.0.0, bare-events@^2.2.0: version "2.5.4" resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz" integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA== @@ -5868,19 +5868,19 @@ better-auth@^1.1.18: resolved "https://registry.npmjs.org/better-auth/-/better-auth-1.2.3.tgz" integrity sha512-y97/ah2SOWaW81IRg36m7xMSMVl7ATaHie/nhQ0in/reVlEX/6juVPszNqq0gcTwQtFsB8oe15wQKgdf4yHP9Q== dependencies: - zod "^3.24.1" + "@better-auth/utils" "0.2.3" + "@better-fetch/fetch" "^1.1.15" + "@noble/ciphers" "^0.6.0" + "@noble/hashes" "^1.6.1" + "@simplewebauthn/browser" "^13.0.0" + "@simplewebauthn/server" "^13.0.0" + better-call "^1.0.3" defu "^6.1.4" jose "^5.9.6" kysely "^0.27.4" - valibot "1.0.0-beta.15" nanostores "^0.11.3" - better-call "^1.0.3" - "@noble/hashes" "^1.6.1" - "@noble/ciphers" "^0.6.0" - "@better-auth/utils" "0.2.3" - "@better-fetch/fetch" "^1.1.15" - "@simplewebauthn/server" "^13.0.0" - "@simplewebauthn/browser" "^13.0.0" + valibot "1.0.0-beta.15" + zod "^3.24.1" better-call@^1.0.3: version "1.0.4" @@ -5918,18 +5918,18 @@ body-parser@1.20.3: resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz" integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: - qs "6.13.0" - depd "2.0.0" bytes "3.1.2" + content-type "~1.0.5" debug "2.6.9" - unpipe "1.0.0" + depd "2.0.0" destroy "1.2.0" - type-is "~1.6.18" - raw-body "2.5.2" - iconv-lite "0.4.24" http-errors "2.0.0" + iconv-lite "0.4.24" on-finished "2.4.1" - content-type "~1.0.5" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" bowser@^2.11.0: version "2.11.0" @@ -6004,17 +6004,17 @@ bun@^1.2.2: resolved "https://registry.npmjs.org/bun/-/bun-1.2.4.tgz" integrity sha512-ZY0EZ/UKqheaLeAtMsfJA6jWoWvV9HAtfFaOJSmS3LrNpFKs1Sg5fZLSsczN1h3a+Dtheo4O3p3ZYWrf40kRGw== optionalDependencies: - "@oven/bun-linux-x64" "1.2.4" + "@oven/bun-darwin-aarch64" "1.2.4" "@oven/bun-darwin-x64" "1.2.4" - "@oven/bun-windows-x64" "1.2.4" + "@oven/bun-darwin-x64-baseline" "1.2.4" "@oven/bun-linux-aarch64" "1.2.4" - "@oven/bun-darwin-aarch64" "1.2.4" - "@oven/bun-linux-x64-musl" "1.2.4" "@oven/bun-linux-aarch64-musl" "1.2.4" + "@oven/bun-linux-x64" "1.2.4" "@oven/bun-linux-x64-baseline" "1.2.4" - "@oven/bun-darwin-x64-baseline" "1.2.4" - "@oven/bun-windows-x64-baseline" "1.2.4" + "@oven/bun-linux-x64-musl" "1.2.4" "@oven/bun-linux-x64-musl-baseline" "1.2.4" + "@oven/bun-windows-x64" "1.2.4" + "@oven/bun-windows-x64-baseline" "1.2.4" bundle-name@^4.1.0: version "4.1.0" @@ -6123,16 +6123,16 @@ chokidar@^3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + optionalDependencies: + fsevents "~2.3.2" dependencies: - braces "~3.0.2" - is-glob "~4.0.1" anymatch "~3.1.2" - readdirp "~3.6.0" + braces "~3.0.2" glob-parent "~5.1.2" is-binary-path "~2.1.0" + is-glob "~4.0.1" normalize-path "~3.0.0" - optionalDependencies: - fsevents "~2.3.2" + readdirp "~3.6.0" chokidar@^4.0.1: version "4.0.3" @@ -6188,9 +6188,9 @@ cliui@^8.0.1: resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: - wrap-ansi "^7.0.0" - strip-ansi "^6.0.1" string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" clone@^1.0.2: version "1.0.4" @@ -6229,8 +6229,8 @@ color@^4.2.3: resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== dependencies: - color-string "^1.9.0" color-convert "^2.0.1" + color-string "^1.9.0" color-convert@^2.0.1: version "2.0.1" @@ -6403,8 +6403,8 @@ config-chain@^1.1.11, config-chain@^1.1.13: resolved "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz" integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== dependencies: - proto-list "~1.2.1" ini "^1.3.4" + proto-list "~1.2.1" configstore@^5.0.0: version "5.0.1" @@ -6412,11 +6412,11 @@ configstore@^5.0.0: integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== dependencies: dot-prop "^5.2.0" - make-dir "^3.0.0" graceful-fs "^4.1.2" - xdg-basedir "^4.0.0" + make-dir "^3.0.0" unique-string "^2.0.0" write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" @@ -6482,8 +6482,8 @@ cors@~2.8.5: resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: - vary "^1" object-assign "^4" + vary "^1" crelt@^1.0.0: version "1.0.6" @@ -6500,18 +6500,18 @@ cross-spawn@7.0.5: resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz" integrity sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug== dependencies: - which "^2.0.1" path-key "^3.1.0" shebang-command "^2.0.0" + which "^2.0.1" cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: - which "^2.0.1" path-key "^3.1.0" shebang-command "^2.0.0" + which "^2.0.1" crypto@^1.0.1: version "1.0.1" @@ -7160,10 +7160,10 @@ editorconfig@^1.0.4: resolved "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz" integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q== dependencies: - semver "^7.5.3" + "@one-ini/wasm" "0.1.1" commander "^10.0.0" minimatch "9.0.1" - "@one-ini/wasm" "0.1.1" + semver "^7.5.3" ee-first@1.1.1: version "1.1.1" @@ -7220,7 +7220,7 @@ encodeurl@~2.0.0: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -encoding@^0.1.13: +encoding@^0.1.0, encoding@^0.1.13: version "0.1.13" resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== @@ -7254,11 +7254,11 @@ engine.io-client@~6.5.2: resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz" integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== dependencies: - ws "~8.17.1" + "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" engine.io-parser "~5.2.1" + ws "~8.17.1" xmlhttprequest-ssl "~2.0.0" - "@socket.io/component-emitter" "~3.1.0" engine.io-parser@~5.2.1: version "5.2.3" @@ -7389,28 +7389,28 @@ esbuild@0.19.11: integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA== optionalDependencies: "@esbuild/aix-ppc64" "0.19.11" - "@esbuild/linux-arm" "0.19.11" - "@esbuild/linux-x64" "0.19.11" - "@esbuild/sunos-x64" "0.19.11" - "@esbuild/win32-x64" "0.19.11" - "@esbuild/darwin-x64" "0.19.11" - "@esbuild/linux-ia32" "0.19.11" - "@esbuild/netbsd-x64" "0.19.11" - "@esbuild/win32-ia32" "0.19.11" "@esbuild/android-arm" "0.19.11" + "@esbuild/android-arm64" "0.19.11" "@esbuild/android-x64" "0.19.11" + "@esbuild/darwin-arm64" "0.19.11" + "@esbuild/darwin-x64" "0.19.11" + "@esbuild/freebsd-arm64" "0.19.11" "@esbuild/freebsd-x64" "0.19.11" + "@esbuild/linux-arm" "0.19.11" "@esbuild/linux-arm64" "0.19.11" + "@esbuild/linux-ia32" "0.19.11" + "@esbuild/linux-loong64" "0.19.11" + "@esbuild/linux-mips64el" "0.19.11" "@esbuild/linux-ppc64" "0.19.11" + "@esbuild/linux-riscv64" "0.19.11" "@esbuild/linux-s390x" "0.19.11" + "@esbuild/linux-x64" "0.19.11" + "@esbuild/netbsd-x64" "0.19.11" "@esbuild/openbsd-x64" "0.19.11" + "@esbuild/sunos-x64" "0.19.11" "@esbuild/win32-arm64" "0.19.11" - "@esbuild/darwin-arm64" "0.19.11" - "@esbuild/android-arm64" "0.19.11" - "@esbuild/freebsd-arm64" "0.19.11" - "@esbuild/linux-loong64" "0.19.11" - "@esbuild/linux-riscv64" "0.19.11" - "@esbuild/linux-mips64el" "0.19.11" + "@esbuild/win32-ia32" "0.19.11" + "@esbuild/win32-x64" "0.19.11" "esbuild@>=0.12 <1": version "0.25.0" @@ -7479,12 +7479,12 @@ escodegen@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + optionalDependencies: + source-map "~0.6.1" dependencies: + esprima "^4.0.1" estraverse "^5.2.0" esutils "^2.0.2" - esprima "^4.0.1" - optionalDependencies: - source-map "~0.6.1" esm-env@^1.2.1: version "1.2.2" @@ -7584,52 +7584,52 @@ execa@^8.0.1: resolved "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz" integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== dependencies: - onetime "^6.0.0" - is-stream "^3.0.0" - get-stream "^8.0.1" cross-spawn "^7.0.3" - signal-exit "^4.1.0" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" merge-stream "^2.0.0" npm-run-path "^5.1.0" - human-signals "^5.0.0" + onetime "^6.0.0" + signal-exit "^4.1.0" strip-final-newline "^3.0.0" -express@^4.21.0: +express@*, express@^4.21.0: version "4.21.2" resolved "https://registry.npmjs.org/express/-/express-4.21.2.tgz" integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== dependencies: - qs "6.13.0" + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.3" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.7.1" + cookie-signature "1.0.6" + debug "2.6.9" depd "2.0.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" etag "~1.8.1" - send "0.19.0" - vary "~1.1.2" - debug "2.6.9" + finalhandler "1.3.1" fresh "0.5.2" - cookie "0.7.1" - accepts "~1.3.8" + http-errors "2.0.0" + merge-descriptors "1.0.3" methods "~1.1.2" - type-is "~1.6.18" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "2.0.1" - encodeurl "~2.0.0" + path-to-regexp "0.1.12" proxy-addr "~2.0.7" - body-parser "1.20.3" - escape-html "~1.0.3" - http-errors "2.0.0" - on-finished "2.4.1" - safe-buffer "5.2.1" - utils-merge "1.0.1" - content-type "~1.0.4" - finalhandler "1.3.1" + qs "6.13.0" range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.19.0" serve-static "1.16.2" - array-flatten "1.1.1" - path-to-regexp "0.1.12" setprototypeof "1.2.0" - cookie-signature "1.0.6" - merge-descriptors "1.0.3" - content-disposition "0.5.4" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" extend@^3.0.0, extend@~3.0.2: version "3.0.2" @@ -7656,12 +7656,12 @@ extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + optionalDependencies: + "@types/yauzl" "^2.9.1" dependencies: debug "^4.1.1" get-stream "^5.1.0" yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" @@ -7700,11 +7700,11 @@ fast-glob@3.3.1: resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: - merge2 "^1.3.0" - micromatch "^4.0.4" - glob-parent "^5.1.2" "@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" fast-glob@^3.3.2, fast-glob@^3.3.3: version "3.3.3" @@ -7802,12 +7802,12 @@ finalhandler@1.3.1: integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - unpipe "~1.0.0" - parseurl "~1.3.3" - statuses "2.0.1" encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" find-my-way-ts@^0.1.5: version "0.1.5" @@ -7871,8 +7871,8 @@ form-data@~2.3.2: integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" - mime-types "^2.1.12" combined-stream "^1.0.6" + mime-types "^2.1.12" form-data@^2.5.0: version "2.5.3" @@ -7880,10 +7880,10 @@ form-data@^2.5.0: integrity sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ== dependencies: asynckit "^0.4.0" - mime-types "^2.1.35" - safe-buffer "^5.2.1" combined-stream "^1.0.8" es-set-tostringtag "^2.1.0" + mime-types "^2.1.35" + safe-buffer "^5.2.1" form-data@^4.0.0, form-data@^4.0.1: version "4.0.2" @@ -7930,9 +7930,9 @@ framer-motion@^11.18.2: resolved "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz" integrity sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w== dependencies: - tslib "^2.4.0" motion-dom "^11.18.1" motion-utils "^11.18.1" + tslib "^2.4.0" framer-motion@^12.4.7: version "12.4.10" @@ -7968,10 +7968,10 @@ fstream@^1.0.0, fstream@^1.0.12: resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz" integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" mkdirp ">=0.5 0" rimraf "2" - inherits "~2.0.0" - graceful-fs "^4.1.2" function-bind@^1.1.2: version "1.1.2" @@ -8001,13 +8001,13 @@ gauge@~2.7.3: integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" - strip-ansi "^3.0.1" - wide-align "^1.1.0" + console-control-strings "^1.0.0" has-unicode "^2.0.0" + object-assign "^4.1.0" signal-exit "^3.0.0" string-width "^1.0.1" - object-assign "^4.1.0" - console-control-strings "^1.0.0" + strip-ansi "^3.0.1" + wide-align "^1.1.0" geist@^1.3.1: version "1.3.1" @@ -8126,11 +8126,11 @@ glob@^7.0.3, glob@^7.1.3: resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: - once "^1.3.0" + fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" minimatch "^3.1.1" - fs.realpath "^1.0.0" + once "^1.3.0" path-is-absolute "^1.0.0" glob@10.3.4: @@ -8138,23 +8138,23 @@ glob@10.3.4: resolved "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz" integrity sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ== dependencies: - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + foreground-child "^3.1.0" jackspeak "^2.0.3" minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" - foreground-child "^3.1.0" glob@^10.3.10, glob@^10.4.2: version "10.4.5" resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: - minipass "^7.1.2" + foreground-child "^3.1.0" jackspeak "^3.1.2" minimatch "^9.0.4" - path-scurry "^1.11.1" - foreground-child "^3.1.0" + minipass "^7.1.2" package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -8220,13 +8220,13 @@ handlebars@^4.7.7: version "4.7.8" resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz" integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + optionalDependencies: + uglify-js "^3.1.4" dependencies: minimist "^1.2.5" neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" har-schema@^2.0.0: version "2.0.0" @@ -8355,10 +8355,10 @@ htmlparser2@^8.0.2: resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz" integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" domutils "^3.0.1" entities "^4.4.0" - domhandler "^5.0.3" - domelementtype "^2.3.0" http-errors@2.0.0: version "2.0.0" @@ -8384,9 +8384,9 @@ http-signature@~1.2.0: resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: - sshpk "^1.7.0" - jsprim "^1.2.2" assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" https@^1.0.0: version "1.0.0" @@ -8485,21 +8485,21 @@ inquirer@^8.2.0: resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz" integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== dependencies: - ora "^5.4.1" - rxjs "^7.5.5" + ansi-escapes "^4.2.1" chalk "^4.1.1" - lodash "^4.17.21" - figures "^3.0.0" - through "^2.3.6" - cli-width "^3.0.0" - run-async "^2.4.0" - wrap-ansi "^6.0.1" cli-cursor "^3.1.0" - strip-ansi "^6.0.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" mute-stream "0.0.8" - ansi-escapes "^4.2.1" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" string-width "^4.1.0" - external-editor "^3.0.3" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" internal-slot@^1.1.0: version "1.1.0" @@ -8525,10 +8525,10 @@ intl-messageformat@^10.5.14: resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.15.tgz" integrity sha512-LRyExsEsefQSBjU2p47oAheoKz+EOJxSLDdjOaEjdriajfHsMXOmV/EhMvYSg9bAgCUHasuAC+mcUBe/95PfIg== dependencies: - tslib "2" - "@formatjs/icu-messageformat-parser" "2.11.1" "@formatjs/ecma402-abstract" "2.3.3" "@formatjs/fast-memoize" "2.2.6" + "@formatjs/icu-messageformat-parser" "2.11.1" + tslib "2" ip-address@^9.0.5: version "9.0.5" @@ -8925,19 +8925,19 @@ jackspeak@^2.0.3: version "2.3.6" resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" + dependencies: + "@isaacs/cliui" "^8.0.2" jackspeak@^3.1.2: version "3.4.3" resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" + dependencies: + "@isaacs/cliui" "^8.0.2" jiti@^1.21.6: version "1.21.7" @@ -9080,10 +9080,10 @@ jsonfile@^6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" + dependencies: + universalify "^2.0.0" jsonrepair@^3.11.2: version "3.12.0" @@ -9095,26 +9095,26 @@ jsonwebtoken@^9.0.0: resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz" integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== dependencies: - ms "^2.1.1" jws "^3.2.2" - semver "^7.5.4" - lodash.once "^4.0.0" lodash.includes "^4.3.0" - lodash.isnumber "^3.0.3" - lodash.isstring "^4.0.1" lodash.isboolean "^3.0.3" lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" jsprim@^1.2.2: version "1.4.2" resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: - verror "1.10.0" - extsprintf "1.3.0" assert-plus "1.0.0" + extsprintf "1.3.0" json-schema "0.4.0" + verror "1.10.0" jwa@^1.4.1: version "1.4.1" @@ -9162,9 +9162,9 @@ keycon@^1.2.0: resolved "https://registry.npmjs.org/keycon/-/keycon-1.4.0.tgz" integrity sha512-p1NAIxiRMH3jYfTeXRs2uWbVJ1WpEjpi8ktzUyBJsX7/wn2qu2VRXktneBLNtKNxJmlUYxRi9gOJt1DuthXR7A== dependencies: + "@cfcs/core" "^0.0.6" "@daybrush/utils" "^1.7.1" "@scena/event-emitter" "^1.0.2" - "@cfcs/core" "^0.0.6" keycode "^2.2.0" kind-of@^3.0.2: @@ -9738,13 +9738,13 @@ micromark-extension-gfm-footnote@^2.0.0: integrity sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw== dependencies: devlop "^1.0.0" - micromark-util-types "^2.0.0" - micromark-util-symbol "^2.0.0" + micromark-core-commonmark "^2.0.0" micromark-factory-space "^2.0.0" micromark-util-character "^2.0.0" - micromark-core-commonmark "^2.0.0" - micromark-util-sanitize-uri "^2.0.0" micromark-util-normalize-identifier "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" micromark-extension-gfm-strikethrough@^2.0.0: version "2.1.0" @@ -9878,10 +9878,10 @@ micromark-util-decode-string@^2.0.0: resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz" integrity sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ== dependencies: + decode-named-character-reference "^1.0.0" micromark-util-character "^2.0.0" micromark-util-decode-numeric-character-reference "^2.0.0" micromark-util-symbol "^2.0.0" - decode-named-character-reference "^1.0.0" micromark-util-encode@^2.0.0: version "2.0.1" @@ -10039,8 +10039,8 @@ motion@^11.18.2: resolved "https://registry.npmjs.org/motion/-/motion-11.18.2.tgz" integrity sha512-JLjvFDuFr42NFtcVoMAyC2sEjnpA8xpy6qWPyzQvCloznAyQ8FIXioxWfHiLtgYhoVpfUqSWpn1h9++skj9+Wg== dependencies: - tslib "^2.4.0" framer-motion "^11.18.2" + tslib "^2.4.0" motion-dom@^11.18.1: version "11.18.1" @@ -10139,47 +10139,47 @@ next@15.0.4: version "15.0.4" resolved "https://registry.npmjs.org/next/-/next-15.0.4.tgz" integrity sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA== - dependencies: - busboy "1.6.0" - postcss "8.4.31" - "@next/env" "15.0.4" - styled-jsx "5.1.6" - "@swc/counter" "0.1.3" - "@swc/helpers" "0.5.13" - caniuse-lite "^1.0.30001579" optionalDependencies: - sharp "^0.33.5" - "@next/swc-darwin-x64" "15.0.4" "@next/swc-darwin-arm64" "15.0.4" - "@next/swc-linux-x64-gnu" "15.0.4" - "@next/swc-linux-x64-musl" "15.0.4" - "@next/swc-win32-x64-msvc" "15.0.4" + "@next/swc-darwin-x64" "15.0.4" "@next/swc-linux-arm64-gnu" "15.0.4" "@next/swc-linux-arm64-musl" "15.0.4" + "@next/swc-linux-x64-gnu" "15.0.4" + "@next/swc-linux-x64-musl" "15.0.4" "@next/swc-win32-arm64-msvc" "15.0.4" - -"next@>= 14.0.0", next@>=12, next@>=13.2.0, "next@^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0", "next@^13.0.0 || ^14.0.0 || ^15.0.0", "next@^14.0.0-0 || ^15.0.0-0", next@^15.2.0: - version "15.2.1" - resolved "https://registry.npmjs.org/next/-/next-15.2.1.tgz" - integrity sha512-zxbsdQv3OqWXybK5tMkPCBKyhIz63RstJ+NvlfkaLMc/m5MwXgz2e92k+hSKcyBpyADhMk2C31RIiaDjUZae7g== + "@next/swc-win32-x64-msvc" "15.0.4" + sharp "^0.33.5" dependencies: + "@next/env" "15.0.4" + "@swc/counter" "0.1.3" + "@swc/helpers" "0.5.13" busboy "1.6.0" + caniuse-lite "^1.0.30001579" postcss "8.4.31" - "@next/env" "15.2.1" styled-jsx "5.1.6" - "@swc/counter" "0.1.3" - "@swc/helpers" "0.5.15" - caniuse-lite "^1.0.30001579" + +next@*, "next@>= 14.0.0", next@>=12, next@>=13.2.0, next@>=14.2.0, "next@^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0", "next@^13.0.0 || ^14.0.0 || ^15.0.0", "next@^14.0.0-0 || ^15.0.0-0", next@^15.2.0: + version "15.2.1" + resolved "https://registry.npmjs.org/next/-/next-15.2.1.tgz" + integrity sha512-zxbsdQv3OqWXybK5tMkPCBKyhIz63RstJ+NvlfkaLMc/m5MwXgz2e92k+hSKcyBpyADhMk2C31RIiaDjUZae7g== optionalDependencies: - sharp "^0.33.5" - "@next/swc-darwin-x64" "15.2.1" "@next/swc-darwin-arm64" "15.2.1" - "@next/swc-linux-x64-gnu" "15.2.1" - "@next/swc-linux-x64-musl" "15.2.1" - "@next/swc-win32-x64-msvc" "15.2.1" + "@next/swc-darwin-x64" "15.2.1" "@next/swc-linux-arm64-gnu" "15.2.1" "@next/swc-linux-arm64-musl" "15.2.1" + "@next/swc-linux-x64-gnu" "15.2.1" + "@next/swc-linux-x64-musl" "15.2.1" "@next/swc-win32-arm64-msvc" "15.2.1" + "@next/swc-win32-x64-msvc" "15.2.1" + sharp "^0.33.5" + dependencies: + "@next/env" "15.2.1" + "@swc/counter" "0.1.3" + "@swc/helpers" "0.5.15" + busboy "1.6.0" + caniuse-lite "^1.0.30001579" + postcss "8.4.31" + styled-jsx "5.1.6" "next-auth@^5.0.0-beta.25": version "5.0.0-beta.25" @@ -10202,9 +10202,9 @@ next-intl@^3.26.3: resolved "https://registry.npmjs.org/next-intl/-/next-intl-3.26.5.tgz" integrity sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg== dependencies: - use-intl "^3.26.5" - negotiator "^1.0.0" "@formatjs/intl-localematcher" "^0.5.4" + negotiator "^1.0.0" + use-intl "^3.26.5" next-safe-action@^7.10.3: version "7.10.4" @@ -10252,18 +10252,18 @@ node-gyp@^3.0.3: resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz" integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== dependencies: - tar "^2.0.0" + fstream "^1.0.0" glob "^7.0.3" - nopt "2 || 3" - osenv "0" - which "1" + graceful-fs "^4.1.2" mkdirp "^0.5.0" + nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "^2.87.0" rimraf "2" semver "~5.3.0" - fstream "^1.0.0" - request "^2.87.0" - graceful-fs "^4.1.2" + tar "^2.0.0" + which "1" node-gyp-build@^4.8.1: version "4.8.4" @@ -10326,10 +10326,10 @@ novel@^1.0.2: "@types/node" "^22.10.6" cmdk "^1.0.4" jotai "^2.11.0" + katex "^0.16.20" react-markdown "^9.0.3" react-moveable "^0.56.0" react-tweet "^3.2.1" - katex "^0.16.20" tippy.js "^6.3.7" tiptap-extension-global-drag-handle "^0.1.16" tunnel-rat "^0.1.2" @@ -10340,28 +10340,28 @@ novu@^2.6.5: integrity sha512-zD644K1kxxmYSnve8e3xNUVB/haCFHRmXhaYeAmxCnI4oSTos0EAgsvIijFIWrXdiE4a8lAi6hhFsZDOjBkX7g== dependencies: "@novu/ntfr-client" "^0.0.4" + "@novu/shared" "2.6.6" "@segment/analytics-node" "^1.1.4" + "@types/cross-spawn" "6.0.0" + async-sema "3.0.1" axios "^1.6.8" chalk "4.1.2" commander "^9.0.0" configstore "^5.0.0" + cross-spawn "7.0.5" dotenv "^16.4.5" + fast-glob "3.3.1" get-port "^5.1.1" gradient-string "^2.0.0" inquirer "^8.2.0" jwt-decode "^3.1.2" open "^8.4.0" ora "^5.4.1" - uuid "^9.0.0" - ws "^8.11.0" picocolors "^1.0.0" - validate-npm-package-name "3.0.0" prompts "2.4.2" - "@types/cross-spawn" "6.0.0" - cross-spawn "7.0.5" - fast-glob "3.3.1" - async-sema "3.0.1" - "@novu/shared" "2.6.6" + uuid "^9.0.0" + validate-npm-package-name "3.0.0" + ws "^8.11.0" npm-run-path@^5.1.0: version "5.3.0" @@ -10375,10 +10375,10 @@ npm-run-path@^5.1.0: resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: - gauge "~2.7.3" - set-blocking "~2.0.0" are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" number-is-nan@^1.0.0: version "1.0.1" @@ -10498,13 +10498,13 @@ ora@5.4.1, ora@^5.4.1: dependencies: bl "^4.1.0" chalk "^4.1.0" - wcwidth "^1.0.1" cli-cursor "^3.1.0" - strip-ansi "^6.0.0" - log-symbols "^4.1.0" cli-spinners "^2.5.0" is-interactive "^1.0.0" is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" orderedmap@^2.0.0: version "2.1.1" @@ -10526,8 +10526,8 @@ osenv@0: resolved "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: - os-tmpdir "^1.0.0" os-homedir "^1.0.0" + os-tmpdir "^1.0.0" overlap-area@^1.1.0: version "1.1.0" @@ -10569,16 +10569,16 @@ p-queue@^6, p-queue@^6.6.1: resolved "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz" integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== dependencies: - p-timeout "^3.2.0" eventemitter3 "^4.0.4" + p-timeout "^3.2.0" p-retry@^4: version "4.6.2" resolved "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz" integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== dependencies: - retry "^0.13.1" "@types/retry" "0.12.0" + retry "^0.13.1" p-timeout@^3.2.0: version "3.2.0" @@ -10702,8 +10702,8 @@ path-scurry@^1.10.1, path-scurry@^1.11.1: resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@0.1.12: version "0.1.12" @@ -10773,7 +10773,7 @@ picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0, picocolors@^1.1.1: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1, "picomatch@^3 || ^4": version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -10810,9 +10810,9 @@ pkg-types@^1.1.3, pkg-types@^1.3.0: resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz" integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== dependencies: + confbox "^0.1.8" mlly "^1.7.4" pathe "^2.0.1" - confbox "^0.1.8" playwright-core@^1.50.1: version "1.50.1" @@ -10861,7 +10861,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.47, postcss@^8.4.48, postcss@^8.5.2: +postcss@>=8.0.9, postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.47, postcss@^8.4.48, postcss@^8.5.2: version "8.5.3" resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -10891,8 +10891,8 @@ postcss-load-config@^4.0.2: resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz" integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== dependencies: - yaml "^2.3.4" lilconfig "^3.0.0" + yaml "^2.3.4" postcss-nested@^6.2.0: version "6.2.0" @@ -10966,7 +10966,7 @@ posthog-node@^4.4.1, posthog-node@^4.5.2: dependencies: axios "^1.7.4" -preact@10.11.3: +preact@10.11.3, preact@>=10: version "10.11.3" resolved "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz" integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg== @@ -11021,16 +11021,16 @@ pretty-format@^3.8.0: resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz" integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== -prisma@^6.3.1: +prisma@*, prisma@^6.3.1: version "6.4.1" resolved "https://registry.npmjs.org/prisma/-/prisma-6.4.1.tgz" integrity sha512-q2uJkgXnua/jj66mk6P9bX/zgYJFI/jn4Yp0aS6SPRrjH/n6VyOV7RDe1vHD0DX8Aanx4MvgmUPPoYnR6MJnPg== + optionalDependencies: + fsevents "2.3.3" dependencies: - esbuild ">=0.12 <1" "@prisma/engines" "6.4.1" + esbuild ">=0.12 <1" esbuild-register "3.6.0" - optionalDependencies: - fsevents "2.3.3" prismjs@1.29.0: version "1.29.0" @@ -11111,8 +11111,8 @@ prosemirror-commands@^1.0.0, prosemirror-commands@^1.6.2: integrity sha512-6toodS4R/Aah5pdsrIwnTYPEjW70SlO5a66oo5Kk+CIrgJz3ukOoS+FYDGqvQlAX5PxoGWDX1oD++tn5X3pyRA== dependencies: prosemirror-model "^1.0.0" - prosemirror-transform "^1.10.2" prosemirror-state "^1.0.0" + prosemirror-transform "^1.10.2" prosemirror-dropcursor@^1.8.1: version "1.8.1" @@ -11120,8 +11120,8 @@ prosemirror-dropcursor@^1.8.1: integrity sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw== dependencies: prosemirror-state "^1.0.0" - prosemirror-view "^1.1.0" prosemirror-transform "^1.1.0" + prosemirror-view "^1.1.0" prosemirror-gapcursor@^1.3.2: version "1.3.2" @@ -11156,17 +11156,17 @@ prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.2.2: resolved "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz" integrity sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ== dependencies: - w3c-keyname "^2.2.0" prosemirror-state "^1.0.0" + w3c-keyname "^2.2.0" prosemirror-markdown@^1.13.1: version "1.13.1" resolved "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.1.tgz" integrity sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw== dependencies: + "@types/markdown-it" "^14.0.0" markdown-it "^14.0.0" prosemirror-model "^1.20.0" - "@types/markdown-it" "^14.0.0" prosemirror-menu@^1.2.4: version "1.2.4" @@ -11174,9 +11174,9 @@ prosemirror-menu@^1.2.4: integrity sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA== dependencies: crelt "^1.0.0" - prosemirror-state "^1.0.0" prosemirror-commands "^1.0.0" prosemirror-history "^1.0.0" + prosemirror-state "^1.0.0" prosemirror-model@^1.0.0, prosemirror-model@^1.19.0, prosemirror-model@^1.20.0, prosemirror-model@^1.21.0, prosemirror-model@^1.22.1, prosemirror-model@^1.23.0, prosemirror-model@^1.24.1: version "1.24.1" @@ -11198,8 +11198,8 @@ prosemirror-schema-list@^1.4.1: integrity sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q== dependencies: prosemirror-model "^1.0.0" - prosemirror-transform "^1.7.3" prosemirror-state "^1.0.0" + prosemirror-transform "^1.7.3" prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.4.2, prosemirror-state@^1.4.3: version "1.4.3" @@ -11307,8 +11307,8 @@ pump@^3.0.0: resolved "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz" integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== dependencies: - once "^1.3.1" end-of-stream "^1.1.0" + once "^1.3.1" punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" @@ -11326,8 +11326,8 @@ puppeteer-core@^24.2.0: integrity sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g== dependencies: "@puppeteer/browsers" "2.8.0" - debug "^4.4.0" chromium-bidi "2.1.2" + debug "^4.4.0" devtools-protocol "0.0.1413902" typed-query-selector "^2.12.0" ws "^8.18.1" @@ -11389,18 +11389,18 @@ raw-body@2.5.2, raw-body@^2.3.3: integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" - unpipe "1.0.0" - iconv-lite "0.4.24" http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" rc@1.2.8: version "1.2.8" resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: + deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" - deep-extend "^0.6.0" strip-json-comments "~2.0.1" react@18.2.0, react@18.x, "react@^16.8 || ^17.0 || ^18.0", react@^18.0.0, react@^18.2.0: @@ -11433,10 +11433,10 @@ react-dom@18.2.0, "react-dom@^16.8 || ^17.0 || ^18.0", react-dom@^18.0.0: resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== dependencies: - scheduler "^0.23.0" loose-envify "^1.1.0" + scheduler "^0.23.0" -react-dom@19.0.0, "react-dom@>= 18.2.0", react-dom@>=16, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.1, "react-dom@>=16.8.6 || ^17.0.0 || ^18.0.0", react-dom@>=18.0.0, "react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19 || ^19.0.0-rc", "react-dom@^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@^19.0.0: +react-dom@19.0.0, "react-dom@>= 18.2.0", react-dom@>=16, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.1, "react-dom@>=16.8.6 || ^17.0.0 || ^18.0.0", react-dom@>=17, react-dom@>=18.0.0, "react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19 || ^19.0.0-rc", "react-dom@^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@^19.0.0: version "19.0.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz" integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== @@ -11457,20 +11457,20 @@ react-email@1.x, react-email@3.0.4: resolved "https://registry.npmjs.org/react-email/-/react-email-3.0.4.tgz" integrity sha512-nXdo9P3V+qYSW6m5yN3XpFGhHb/bflX86m0EDQEqDIgayprj6InmBJoBnMSIyC5EP4tPtoAljlclJns4lJG/MQ== dependencies: - ora "5.4.1" - glob "10.3.4" - next "15.0.4" + "@babel/core" "7.24.5" + "@babel/parser" "7.24.5" chalk "4.1.2" - esbuild "0.19.11" chokidar "^4.0.1" - debounce "2.0.0" commander "11.1.0" - socket.io "4.8.0" - mime-types "2.1.35" - "@babel/core" "7.24.5" + debounce "2.0.0" + esbuild "0.19.11" + glob "10.3.4" log-symbols "4.1.0" - "@babel/parser" "7.24.5" + mime-types "2.1.35" + next "15.0.4" normalize-path "3.0.0" + ora "5.4.1" + socket.io "4.8.0" react-hook-form@^7.0.0, react-hook-form@^7.54.2: version "7.54.2" @@ -11512,17 +11512,17 @@ react-markdown@^9.0.3: resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz" integrity sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw== dependencies: - vfile "^6.0.0" - devlop "^1.0.0" - unified "^11.0.0" "@types/hast" "^3.0.0" "@types/mdast" "^4.0.0" + devlop "^1.0.0" + hast-util-to-jsx-runtime "^2.0.0" + html-url-attributes "^3.0.0" + mdast-util-to-hast "^13.0.0" remark-parse "^11.0.0" remark-rehype "^11.0.0" + unified "^11.0.0" unist-util-visit "^5.0.0" - mdast-util-to-hast "^13.0.0" - html-url-attributes "^3.0.0" - hast-util-to-jsx-runtime "^2.0.0" + vfile "^6.0.0" react-moveable@^0.56.0: version "0.56.0" @@ -11565,11 +11565,11 @@ react-remove-scroll@2.5.4: resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.4.tgz" integrity sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA== dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" tslib "^2.1.0" - use-sidecar "^1.1.2" use-callback-ref "^1.3.0" - react-style-singleton "^2.2.1" - react-remove-scroll-bar "^2.3.3" + use-sidecar "^1.1.2" react-remove-scroll@^2.6.3: version "2.6.3" @@ -11616,8 +11616,8 @@ react-style-singleton@^2.2.1, react-style-singleton@^2.2.2, react-style-singleto resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== dependencies: - tslib "^2.0.0" get-nonce "^1.0.0" + tslib "^2.0.0" react-textarea-autosize@^8.5.7: version "8.5.7" @@ -11669,13 +11669,13 @@ readable-stream@^2.0.6: resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: - isarray "~1.0.0" + core-util-is "~1.0.0" inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" safe-buffer "~5.1.1" - core-util-is "~1.0.0" string_decoder "~1.1.1" util-deprecate "~1.0.1" - process-nextick-args "~2.0.0" readable-stream@^3.4.0: version "3.6.2" @@ -11715,10 +11715,10 @@ recharts@^2.12.7: integrity sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q== dependencies: clsx "^2.0.0" + eventemitter3 "^4.0.1" lodash "^4.17.21" react-is "^18.3.1" react-smooth "^4.0.4" - eventemitter3 "^4.0.1" recharts-scale "^0.4.4" tiny-invariant "^1.3.1" victory-vendor "^36.6.8" @@ -11822,26 +11822,26 @@ request@^2.87.0: resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: - qs "~6.5.2" + aws-sign2 "~0.7.0" aws4 "^1.8.0" - uuid "^3.3.2" - extend "~3.0.2" caseless "~0.12.0" - isstream "~0.1.2" - aws-sign2 "~0.7.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" mime-types "~2.1.19" oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" safe-buffer "^5.1.2" tough-cookie "~2.5.0" tunnel-agent "^0.6.0" - forever-agent "~0.6.1" - har-validator "~5.1.3" - is-typedarray "~1.0.0" - http-signature "~1.2.0" - combined-stream "~1.0.6" - performance-now "^2.1.0" - json-stringify-safe "~5.0.1" + uuid "^3.3.2" require-directory@^2.1.1: version "2.1.1" @@ -12089,19 +12089,19 @@ send@0.19.0: resolved "https://registry.npmjs.org/send/-/send-0.19.0.tgz" integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: - ms "2.1.3" - depd "2.0.0" - etag "~1.8.1" - mime "1.6.0" debug "2.6.9" - fresh "0.5.2" + depd "2.0.0" destroy "1.2.0" - statuses "2.0.1" encodeurl "~1.0.2" escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" on-finished "2.4.1" range-parser "~1.2.1" + statuses "2.0.1" seroval@^1.0, seroval@^1.1.0: version "1.2.1" @@ -12178,30 +12178,30 @@ sharp@^0.33.5: version "0.33.5" resolved "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz" integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw== - dependencies: - color "^4.2.3" - semver "^7.6.3" - detect-libc "^2.0.3" optionalDependencies: - "@img/sharp-wasm32" "0.33.5" - "@img/sharp-linux-arm" "0.33.5" - "@img/sharp-linux-x64" "0.33.5" - "@img/sharp-win32-x64" "0.33.5" - "@img/sharp-darwin-x64" "0.33.5" - "@img/sharp-win32-ia32" "0.33.5" - "@img/sharp-linux-arm64" "0.33.5" - "@img/sharp-linux-s390x" "0.33.5" "@img/sharp-darwin-arm64" "0.33.5" - "@img/sharp-linuxmusl-x64" "0.33.5" - "@img/sharp-linuxmusl-arm64" "0.33.5" - "@img/sharp-libvips-linux-arm" "1.0.5" - "@img/sharp-libvips-linux-x64" "1.0.4" + "@img/sharp-darwin-x64" "0.33.5" + "@img/sharp-libvips-darwin-arm64" "1.0.4" "@img/sharp-libvips-darwin-x64" "1.0.4" + "@img/sharp-libvips-linux-arm" "1.0.5" "@img/sharp-libvips-linux-arm64" "1.0.4" "@img/sharp-libvips-linux-s390x" "1.0.4" - "@img/sharp-libvips-darwin-arm64" "1.0.4" - "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + "@img/sharp-libvips-linux-x64" "1.0.4" "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" + "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + "@img/sharp-linux-arm" "0.33.5" + "@img/sharp-linux-arm64" "0.33.5" + "@img/sharp-linux-s390x" "0.33.5" + "@img/sharp-linux-x64" "0.33.5" + "@img/sharp-linuxmusl-arm64" "0.33.5" + "@img/sharp-linuxmusl-x64" "0.33.5" + "@img/sharp-wasm32" "0.33.5" + "@img/sharp-win32-ia32" "0.33.5" + "@img/sharp-win32-x64" "0.33.5" + dependencies: + color "^4.2.3" + detect-libc "^2.0.3" + semver "^7.6.3" shebang-command@^2.0.0: version "2.0.0" @@ -12275,9 +12275,9 @@ simple-git@^3.27.0: resolved "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz" integrity sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA== dependencies: - debug "^4.3.5" "@kwsites/file-exists" "^1.1.1" "@kwsites/promise-deferred" "^1.1.1" + debug "^4.3.5" simple-swizzle@^0.2.2: version "0.2.2" @@ -12306,13 +12306,13 @@ socket.io@4.8.0: resolved "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz" integrity sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA== dependencies: - cors "~2.8.5" - debug "~4.3.2" accepts "~1.3.4" base64id "~2.0.0" + cors "~2.8.5" + debug "~4.3.2" engine.io "~6.6.0" - socket.io-parser "~4.2.4" socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" socket.io-adapter@~2.5.2: version "2.5.5" @@ -12327,28 +12327,28 @@ socket.io-client@4.7.2: resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz" integrity sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w== dependencies: + "@socket.io/component-emitter" "~3.1.0" debug "~4.3.2" engine.io-client "~6.5.2" socket.io-parser "~4.2.4" - "@socket.io/component-emitter" "~3.1.0" socket.io-client@4.7.5: version "4.7.5" resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz" integrity sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ== dependencies: + "@socket.io/component-emitter" "~3.1.0" debug "~4.3.2" engine.io-client "~6.5.2" socket.io-parser "~4.2.4" - "@socket.io/component-emitter" "~3.1.0" socket.io-parser@~4.2.4: version "4.2.4" resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz" integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== dependencies: - debug "~4.3.1" "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" socks@^2.8.3: version "2.8.4" @@ -12372,7 +12372,7 @@ solid-floating-ui@^0.3.1: resolved "https://registry.npmjs.org/solid-floating-ui/-/solid-floating-ui-0.3.1.tgz" integrity sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q== -solid-js@^1.6.12, solid-js@^1.8, solid-js@^1.8.11: +solid-js@^1.6.12, solid-js@^1.7.7, solid-js@^1.8, solid-js@^1.8.11: version "1.9.5" resolved "https://registry.npmjs.org/solid-js/-/solid-js-1.9.5.tgz" integrity sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw== @@ -12434,14 +12434,14 @@ sshpk@^1.7.0: integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== dependencies: asn1 "~0.2.3" - jsbn "~0.1.0" - getpass "^0.1.1" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - tweetnacl "~0.14.0" assert-plus "^1.0.0" bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" safer-buffer "^2.0.2" + tweetnacl "~0.14.0" sswr@^2.1.0: version "2.2.0" @@ -12472,38 +12472,38 @@ streamx@^2.15.0, streamx@^2.21.0: version "2.22.0" resolved "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz" integrity sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw== + optionalDependencies: + bare-events "^2.2.0" dependencies: fast-fifo "^1.3.2" text-decoder "^1.1.0" - optionalDependencies: - bare-events "^2.2.0" string-width@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: - strip-ansi "^3.0.0" code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, "string-width@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: - strip-ansi "^6.0.1" emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: - strip-ansi "^7.0.1" - emoji-regex "^9.2.2" eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" string.prototype.trim@^1.2.10: version "1.2.10" @@ -12679,16 +12679,16 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -"svelte@^4.0.0 || ^5.0.0": +"svelte@^3.0.0 || ^4.0.0 || ^5.0.0", "svelte@^4.0.0 || ^5.0.0": version "5.22.5" resolved "https://registry.npmjs.org/svelte/-/svelte-5.22.5.tgz" integrity sha512-+2BDWVa/rqr34oM+5HFUSmCCPdBBeNqFv2Xc/SSB8kV4iQhWWBNvU9/nd5Dz3PkAGl7Bm/AndS1vY4fe1MgTKA== dependencies: "@ampproject/remapping" "^2.3.0" "@jridgewell/sourcemap-codec" "^1.5.0" + "@sveltejs/acorn-typescript" "^1.0.5" "@types/estree" "^1.0.5" acorn "^8.12.1" - "@sveltejs/acorn-typescript" "^1.0.5" aria-query "^5.3.1" axobject-query "^4.1.0" clsx "^2.1.1" @@ -12740,33 +12740,33 @@ tailwind-merge@^2.4.0, tailwind-merge@^2.6.0: resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz" integrity sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA== -"tailwindcss@>=3.0.0 || insiders", "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1", tailwindcss@^3.4.13, tailwindcss@^3.4.17: +"tailwindcss@>=3.0.0 || insiders", "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1", "tailwindcss@^3.0.0 || ^4.0.0-beta.0", tailwindcss@^3.4.13, tailwindcss@^3.4.17: version "3.4.17" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz" integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== dependencies: + "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" - dlv "^1.1.3" - jiti "^1.21.6" - is-glob "^4.0.3" - postcss "^8.4.47" - resolve "^1.22.8" - sucrase "^3.35.0" chokidar "^3.6.0" + didyoumean "^1.2.2" + dlv "^1.1.3" fast-glob "^3.3.2" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.6" lilconfig "^3.1.3" - didyoumean "^1.2.2" micromatch "^4.0.8" - picocolors "^1.1.1" - postcss-js "^4.0.1" - glob-parent "^6.0.2" - object-hash "^3.0.0" normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.1.1" + postcss "^8.4.47" postcss-import "^15.1.0" - postcss-nested "^6.2.0" - "@alloc/quick-lru" "^5.2.0" + postcss-js "^4.0.1" postcss-load-config "^4.0.2" + postcss-nested "^6.2.0" postcss-selector-parser "^6.1.2" + resolve "^1.22.8" + sucrase "^3.35.0" tailwindcss-animate@^1.0.7: version "1.0.7" @@ -12778,20 +12778,20 @@ tar@^2.0.0: resolved "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz" integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== dependencies: + block-stream "*" fstream "^1.0.12" inherits "2" - block-stream "*" tar-fs@^3.0.8: version "3.0.8" resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz" integrity sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg== - dependencies: - pump "^3.0.0" - tar-stream "^3.1.5" optionalDependencies: bare-fs "^4.0.1" bare-path "^3.0.0" + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" tar-stream@^3.1.5: version "3.1.7" @@ -12874,8 +12874,8 @@ tinygradient@^1.1.5: resolved "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz" integrity sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw== dependencies: - tinycolor2 "^1.0.0" "@types/tinycolor2" "^1.4.0" + tinycolor2 "^1.0.0" tippy.js@^6.3.7: version "6.3.7" @@ -13006,11 +13006,11 @@ turbo@^2.4.4: resolved "https://registry.npmjs.org/turbo/-/turbo-2.4.4.tgz" integrity sha512-N9FDOVaY3yz0YCOhYIgOGYad7+m2ptvinXygw27WPLQvcZDl3+0Sa77KGVlLSiuPDChOUEnTKE9VJwLSi9BPGQ== optionalDependencies: - turbo-linux-64 "2.4.4" turbo-darwin-64 "2.4.4" - turbo-windows-64 "2.4.4" - turbo-linux-arm64 "2.4.4" turbo-darwin-arm64 "2.4.4" + turbo-linux-64 "2.4.4" + turbo-linux-arm64 "2.4.4" + turbo-windows-64 "2.4.4" turbo-windows-arm64 "2.4.4" turbo-darwin-64@2.4.4: @@ -13068,8 +13068,8 @@ type-is@~1.6.18: resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: - mime-types "~2.1.24" media-typer "0.3.0" + mime-types "~2.1.24" typed-array-buffer@^1.0.3: version "1.0.3" @@ -13128,7 +13128,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@5.7.3, typescript@>=5.7.2, typescript@^5.5.4, typescript@^5.6.3, typescript@^5.7.2, typescript@^5.7.3: +typescript@*, typescript@5.7.3, typescript@>=5, typescript@>=5.1.0, typescript@>=5.7.2, typescript@^5.0.0, typescript@^5.5.4, typescript@^5.6.3, typescript@^5.7.2, typescript@^5.7.3: version "5.7.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz" integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== @@ -13259,11 +13259,11 @@ uploadthing@^7.2.0, uploadthing@^7.5.0: resolved "https://registry.npmjs.org/uploadthing/-/uploadthing-7.5.2.tgz" integrity sha512-hrvsVXgu6cYYJW97UuFLd3U2+TrPGyMBtPYSkqSTVq45Orkq9qFk095qkXYIW4EA/DyvCo78VV25HfSXT3EH7w== dependencies: - effect "3.12.0" "@effect/platform" "0.72.0" - "@uploadthing/shared" "7.1.7" "@standard-schema/spec" "1.0.0-beta.4" "@uploadthing/mime-types" "0.3.4" + "@uploadthing/shared" "7.1.7" + effect "3.12.0" uri-js@^4.2.2: version "4.4.1" @@ -13294,8 +13294,8 @@ use-intl@^3.26.5: resolved "https://registry.npmjs.org/use-intl/-/use-intl-3.26.5.tgz" integrity sha512-OdsJnC/znPvHCHLQH/duvQNXnP1w0hPfS+tkSi3mAbfjYBGh4JnyfdwkQBfIVf7t8gs9eSX/CntxUMvtKdG2MQ== dependencies: - intl-messageformat "^10.5.14" "@formatjs/fast-memoize" "^2.2.0" + intl-messageformat "^10.5.14" use-isomorphic-layout-effect@^1.1.1: version "1.2.0" @@ -13322,7 +13322,7 @@ use-sidecar@^1.1.2, use-sidecar@^1.1.3: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1, use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: +use-sync-external-store@>=1.2.0, use-sync-external-store@^1, use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz" integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== @@ -13352,7 +13352,7 @@ uuid@^11.0.5: resolved "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz" integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== -"valibot@1.0.0-beta.15": +"valibot@1.0.0-beta.15", "valibot@>= 0.36.0": version "1.0.0-beta.15" resolved "https://registry.npmjs.org/valibot/-/valibot-1.0.0-beta.15.tgz" integrity sha512-BKy8XosZkDHWmYC+cJG74LBzP++Gfntwi33pP3D3RKztz2XV9jmFWnkOi21GoqARP8wAWARwhV6eTr1JcWzjGw== @@ -13386,9 +13386,9 @@ verror@1.10.0: resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: - extsprintf "^1.2.0" assert-plus "^1.0.0" core-util-is "1.0.2" + extsprintf "^1.2.0" vfile@^6.0.0: version "6.0.3" @@ -13411,31 +13411,31 @@ victory-vendor@^36.6.8: resolved "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz" integrity sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ== dependencies: - d3-ease "^3.0.1" - d3-time "^3.0.0" - d3-array "^3.1.6" - d3-scale "^4.0.2" - d3-shape "^3.1.0" - d3-timer "^3.0.1" - "@types/d3-ease" "^3.0.0" - "@types/d3-time" "^3.0.0" - d3-interpolate "^3.0.1" "@types/d3-array" "^3.0.3" + "@types/d3-ease" "^3.0.0" + "@types/d3-interpolate" "^3.0.1" "@types/d3-scale" "^4.0.2" "@types/d3-shape" "^3.1.0" + "@types/d3-time" "^3.0.0" "@types/d3-timer" "^3.0.0" - "@types/d3-interpolate" "^3.0.1" + d3-array "^3.1.6" + d3-ease "^3.0.1" + d3-interpolate "^3.0.1" + d3-scale "^4.0.2" + d3-shape "^3.1.0" + d3-time "^3.0.0" + d3-timer "^3.0.1" -vue@3.5.13, "vue@>=3.2.26 < 4": +vue@3.5.13, "vue@>=3.2.26 < 4", vue@^3.3.4: version "3.5.13" resolved "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz" integrity sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ== dependencies: - "@vue/shared" "3.5.13" - "@vue/runtime-dom" "3.5.13" "@vue/compiler-dom" "3.5.13" "@vue/compiler-sfc" "3.5.13" + "@vue/runtime-dom" "3.5.13" "@vue/server-renderer" "3.5.13" + "@vue/shared" "3.5.13" w3c-keyname@^2.2.0: version "2.2.8" @@ -13676,8 +13676,8 @@ write-file-atomic@^3.0.0: integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" - signal-exit "^3.0.2" is-typedarray "^1.0.0" + signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" ws@^7.5.3: @@ -13767,13 +13767,13 @@ yargs@^17.7.2: resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - y18n "^5.0.5" cliui "^8.0.1" escalade "^3.1.1" - string-width "^4.2.3" - yargs-parser "^21.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" yargs-parser@^21.1.1: version "21.1.1" @@ -13790,8 +13790,8 @@ yauzl@^2.10.0: resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz" integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== dependencies: - fd-slicer "~1.1.0" buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" zimmerframe@^1.1.2: version "1.1.2"