diff --git a/.env.example b/.env.example
index a59043e802..1e3bb1a739 100644
--- a/.env.example
+++ b/.env.example
@@ -408,3 +408,6 @@ NEXT_PUBLIC_WEBSITE_TERMS_URL=
# NEXT_PUBLIC_LOGGER_LEVEL=3 sets to log info, warn, error and fatal logs.
# [0: silly & upwards, 1: trace & upwards, 2: debug & upwards, 3: info & upwards, 4: warn & upwards, 5: error & fatal, 6: fatal]
NEXT_PUBLIC_LOGGER_LEVEL=
+
+# Used to use Replexica SDK, a tool for real-time AI-powered localization
+REPLEXICA_API_KEY=
\ No newline at end of file
diff --git a/apps/web/package.json b/apps/web/package.json
index d732e1120a..561a50f162 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -64,6 +64,7 @@
"@radix-ui/react-switch": "^1.0.0",
"@radix-ui/react-toggle-group": "^1.0.0",
"@radix-ui/react-tooltip": "^1.0.0",
+ "@replexica/sdk": "^0.6.0",
"@sentry/nextjs": "^8.8.0",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.35.0",
diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json
index 26367507cb..e7ca29bddc 100644
--- a/apps/web/public/static/locales/en/common.json
+++ b/apps/web/public/static/locales/en/common.json
@@ -2791,6 +2791,7 @@
"salesforce_route_to_custom_lookup_field": "Route to a user that matches a lookup field on an account",
"salesforce_option": "Salesforce Option",
"lookup_field_name": "Lookup Field Name",
+ "translate_description_button": "Translate description to the visitor's browser language using AI",
"rr_distribution_method": "Distribution",
"rr_distribution_method_description": "Allows for optimising distribution for maximum availability or to aim for a more balanced assignment.",
"rr_distribution_method_availability_title": "Maximize availability",
diff --git a/apps/web/test/lib/handleChildrenEventTypes.test.ts b/apps/web/test/lib/handleChildrenEventTypes.test.ts
index 22c8652181..a028816818 100644
--- a/apps/web/test/lib/handleChildrenEventTypes.test.ts
+++ b/apps/web/test/lib/handleChildrenEventTypes.test.ts
@@ -112,6 +112,7 @@ describe("handleChildrenEventTypes", () => {
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
+ autoTranslateDescriptionEnabled,
...evType
} = mockFindFirstEventType({
id: 123,
@@ -182,7 +183,7 @@ describe("handleChildrenEventTypes", () => {
bookingLimits: undefined,
},
});
- const { profileId, ...rest } = evType;
+ const { profileId, autoTranslateDescriptionEnabled, ...rest } = evType;
expect(prismaMock.eventType.update).toHaveBeenCalledWith({
data: {
...rest,
@@ -265,6 +266,7 @@ describe("handleChildrenEventTypes", () => {
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
+ autoTranslateDescriptionEnabled,
...evType
} = mockFindFirstEventType({
id: 123,
@@ -337,7 +339,7 @@ describe("handleChildrenEventTypes", () => {
length: 30,
},
});
- const { profileId, ...rest } = evType;
+ const { profileId, autoTranslateDescriptionEnabled, ...rest } = evType;
expect(prismaMock.eventType.update).toHaveBeenCalledWith({
data: {
...rest,
@@ -378,6 +380,7 @@ describe("handleChildrenEventTypes", () => {
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
+ autoTranslateDescriptionEnabled,
...evType
} = mockFindFirstEventType({
metadata: { managedEventConfig: {} },
diff --git a/packages/features/bookings/Booker/components/EventMeta.tsx b/packages/features/bookings/Booker/components/EventMeta.tsx
index 32fad2b847..889ec090ac 100644
--- a/packages/features/bookings/Booker/components/EventMeta.tsx
+++ b/packages/features/bookings/Booker/components/EventMeta.tsx
@@ -48,6 +48,8 @@ export const EventMeta = ({
| "recurringEvent"
| "price"
| "isDynamic"
+ | "fieldTranslations"
+ | "autoTranslateDescriptionEnabled"
> | null;
isPending: boolean;
isPlatform?: boolean;
@@ -101,6 +103,10 @@ export const EventMeta = ({
: isHalfFull
? "text-yellow-500"
: "text-bookinghighlight";
+ const browserLocale = navigator.language; // e.g. "en-US", "es-ES", "fr-FR"
+ const translatedDescription = (event?.fieldTranslations ?? []).find((translation) =>
+ browserLocale.startsWith(translation.targetLang)
+ )?.translatedText;
return (
@@ -120,9 +126,9 @@ export const EventMeta = ({
/>
)}
{event?.title}
- {event.description && (
+ {(event.description || translatedDescription) && (
-
+
)}
diff --git a/packages/features/bookings/types.ts b/packages/features/bookings/types.ts
index 41eb8d2451..e598e88bd3 100644
--- a/packages/features/bookings/types.ts
+++ b/packages/features/bookings/types.ts
@@ -51,6 +51,8 @@ export type BookerEvent = Pick<
| "bookingFields"
| "seatsShowAvailabilityCount"
| "isInstantEvent"
+ | "fieldTranslations"
+ | "autoTranslateDescriptionEnabled"
> & { users: BookerEventUser[]; showInstantEventConnectNowModal: boolean } & { profile: BookerEventProfile };
export type ValidationErrors = { key: FieldPath; error: ErrorOption }[];
diff --git a/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx b/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx
index 7ae3ea5691..6e1bb89f75 100644
--- a/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx
+++ b/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx
@@ -1,3 +1,4 @@
+import { useSession } from "next-auth/react";
import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import type { UseFormGetValues, UseFormSetValue, Control, FormState } from "react-hook-form";
@@ -20,6 +21,7 @@ export type EventSetupTabProps = Pick<
>;
export const EventSetupTab = (props: EventSetupTabProps & { urlPrefix: string; hasOrgBranding: boolean }) => {
const { t } = useLocale();
+ const session = useSession();
const isPlatform = useIsPlatform();
const formMethods = useFormContext();
const { eventType, team, urlPrefix, hasOrgBranding } = props;
@@ -29,6 +31,7 @@ export const EventSetupTab = (props: EventSetupTabProps & { urlPrefix: string; h
const [firstRender, setFirstRender] = useState(true);
const seatsEnabled = formMethods.watch("seatsPerTimeSlotEnabled");
+ const autoTranslateDescriptionEnabled = formMethods.watch("autoTranslateDescriptionEnabled");
const multipleDurationOptions = [
5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 150, 180, 240, 300, 360, 420, 480,
@@ -95,6 +98,17 @@ export const EventSetupTab = (props: EventSetupTabProps & { urlPrefix: string; h
>
)}
+
+ {
+ formMethods.setValue("autoTranslateDescriptionEnabled", value, { shouldDirty: true });
+ }}
+ disabled={!session.data?.user.org?.id}
+ tooltip={!session.data?.user.org?.id ? t("orgs_upgrade_to_enable_feature") : undefined}
+ />
+
()({
metadata: true,
lockTimeZoneToggleOnBookingPage: true,
requiresConfirmation: true,
+ autoTranslateDescriptionEnabled: true,
+ fieldTranslations: {
+ select: {
+ translatedText: true,
+ targetLang: true,
+ },
+ },
requiresBookerEmailVerification: true,
recurringEvent: true,
price: true,
@@ -293,6 +300,8 @@ export const getPublicEvent = async (
},
isInstantEvent: false,
showInstantEventConnectNowModal: false,
+ autoTranslateDescriptionEnabled: false,
+ fieldTranslations: [],
};
}
diff --git a/packages/features/eventtypes/lib/types.ts b/packages/features/eventtypes/lib/types.ts
index e9003b3112..382002f647 100644
--- a/packages/features/eventtypes/lib/types.ts
+++ b/packages/features/eventtypes/lib/types.ts
@@ -2,6 +2,7 @@ import type { z } from "zod";
import type { EventLocationType } from "@calcom/core/location";
import type { ChildrenEventType } from "@calcom/features/eventtypes/components/ChildrenEventTypeSelect";
+import type { EventTypeTranslation } from "@calcom/prisma/client";
import type { PeriodType, SchedulingType } from "@calcom/prisma/enums";
import type { BookerLayoutSettings, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import type { customInputSchema } from "@calcom/prisma/zod-utils";
@@ -109,6 +110,8 @@ export type FormValues = {
seatsShowAttendees: boolean | null;
seatsShowAvailabilityCount: boolean | null;
seatsPerTimeSlotEnabled: boolean;
+ autoTranslateDescriptionEnabled: boolean;
+ fieldTranslations: EventTypeTranslation[];
scheduleName: string;
minimumBookingNotice: number;
minimumBookingNoticeInDurationType: number;
diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts
index b3197f46df..02e3fe7aac 100644
--- a/packages/lib/constants.ts
+++ b/packages/lib/constants.ts
@@ -168,6 +168,7 @@ export const CALCOM_PRIVATE_API_ROUTE = process.env.CALCOM_PRIVATE_API_ROUTE ||
export const WEBSITE_PRIVACY_POLICY_URL =
process.env.NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL || "https://cal.com/privacy";
export const WEBSITE_TERMS_URL = process.env.NEXT_PUBLIC_WEBSITE_TERMS_URL || "https://cal.com/terms";
+export const REPLEXICA_API_KEY = process.env.REPLEXICA_API_KEY;
/**
* The maximum number of days we should check for if we don't find all required bookable days
@@ -190,3 +191,4 @@ export const RECORDING_DEFAULT_ICON = IS_PRODUCTION
export const RECORDING_IN_PROGRESS_ICON = IS_PRODUCTION
? `${WEBAPP_URL}/stop-recording.svg`
: `https://app.cal.com/stop-recording.svg`;
+
diff --git a/packages/lib/defaultEvents.ts b/packages/lib/defaultEvents.ts
index 2723c9c5d9..14dfaceeea 100644
--- a/packages/lib/defaultEvents.ts
+++ b/packages/lib/defaultEvents.ts
@@ -110,6 +110,8 @@ const commons = {
useEventTypeDestinationCalendarEmail: false,
secondaryEmailId: null,
secondaryEmail: null,
+ autoTranslateDescriptionEnabled: false,
+ fieldTranslations: [],
maxLeadThreshold: null,
};
diff --git a/packages/lib/server/eventTypeSelect.ts b/packages/lib/server/eventTypeSelect.ts
index 6613958d98..3748949e8f 100644
--- a/packages/lib/server/eventTypeSelect.ts
+++ b/packages/lib/server/eventTypeSelect.ts
@@ -13,6 +13,7 @@ export const eventTypeSelect = Prisma.validator()({
title: true,
requiresConfirmation: true,
requiresConfirmationWillBlockSlot: true,
+ autoTranslateDescriptionEnabled: true,
position: true,
offsetStart: true,
profileId: true,
diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts
index 6e124206df..9cbbd6fb97 100644
--- a/packages/lib/server/repository/eventType.ts
+++ b/packages/lib/server/repository/eventType.ts
@@ -445,6 +445,13 @@ export class EventTypeRepository {
requiresConfirmation: true,
requiresConfirmationWillBlockSlot: true,
requiresBookerEmailVerification: true,
+ autoTranslateDescriptionEnabled: true,
+ fieldTranslations: {
+ select: {
+ translatedText: true,
+ targetLang: true,
+ },
+ },
recurringEvent: true,
hideCalendarNotes: true,
hideCalendarEventDetails: true,
diff --git a/packages/lib/server/service/replexica.ts b/packages/lib/server/service/replexica.ts
new file mode 100644
index 0000000000..9d0954b32e
--- /dev/null
+++ b/packages/lib/server/service/replexica.ts
@@ -0,0 +1,60 @@
+import { ReplexicaEngine } from "@replexica/sdk";
+
+import { REPLEXICA_API_KEY } from "@calcom/lib/constants";
+
+export class ReplexicaService {
+ private static engine = new ReplexicaEngine({
+ apiKey: REPLEXICA_API_KEY,
+ });
+
+ /**
+ * Localizes text from one language to another
+ * @param text The text to localize
+ * @param sourceLocale The source language locale
+ * @param targetLocale The target language locale
+ * @returns The localized text
+ */
+ static async localizeText(text: string, sourceLocale: string, targetLocale: string): Promise {
+ if (!text?.trim()) {
+ return text;
+ }
+
+ try {
+ const result = await this.engine.localizeText(text, {
+ sourceLocale,
+ targetLocale,
+ });
+
+ return result;
+ } catch (error) {
+ return text;
+ }
+ }
+
+ /**
+ * Localizes an array of texts from one language to another
+ * @param texts Array of texts to localize
+ * @param sourceLocale The source language locale
+ * @param targetLocale The target language locale
+ * @returns The localized texts array
+ */
+ static async localizeTexts(texts: string[], sourceLocale: string, targetLocale: string): Promise {
+ if (!texts.length) {
+ return texts;
+ }
+
+ try {
+ const result = await this.engine.localizeChat(
+ texts.map((text) => ({ name: "NO_NAME", text: text.trim() })),
+ {
+ sourceLocale,
+ targetLocale,
+ }
+ );
+
+ return result.map((chat: { name: string; text: string }) => chat.text);
+ } catch (error) {
+ return texts;
+ }
+ }
+}
diff --git a/packages/lib/test/builder.ts b/packages/lib/test/builder.ts
index b1219af561..42c5de580b 100644
--- a/packages/lib/test/builder.ts
+++ b/packages/lib/test/builder.ts
@@ -138,6 +138,7 @@ export const buildEventType = (eventType?: Partial): EventType => {
secondaryEmailId: null,
isRRWeightsEnabled: false,
eventTypeColor: null,
+ autoTranslateDescriptionEnabled: false,
...eventType,
};
};
diff --git a/packages/platform/atoms/event-types/hooks/useEventTypeForm.ts b/packages/platform/atoms/event-types/hooks/useEventTypeForm.ts
index 6ec614fe4a..eb1712ee01 100644
--- a/packages/platform/atoms/event-types/hooks/useEventTypeForm.ts
+++ b/packages/platform/atoms/event-types/hooks/useEventTypeForm.ts
@@ -109,6 +109,7 @@ export const useEventTypeForm = ({
},
})),
seatsPerTimeSlotEnabled: eventType.seatsPerTimeSlot,
+ autoTranslateDescriptionEnabled: eventType.autoTranslateDescriptionEnabled,
rescheduleWithSameRoundRobinHost: eventType.rescheduleWithSameRoundRobinHost,
assignAllTeamMembers: eventType.assignAllTeamMembers,
aiPhoneCallConfig: {
diff --git a/packages/prisma/migrations/20241114210330_add_event_type_translation_model/migration.sql b/packages/prisma/migrations/20241114210330_add_event_type_translation_model/migration.sql
new file mode 100644
index 0000000000..2b6be7c0e8
--- /dev/null
+++ b/packages/prisma/migrations/20241114210330_add_event_type_translation_model/migration.sql
@@ -0,0 +1,30 @@
+-- CreateEnum
+CREATE TYPE "EventTypeAutoTranslatedField" AS ENUM ('DESCRIPTION');
+
+-- AlterTable
+ALTER TABLE "EventType" ADD COLUMN "autoTranslateDescriptionEnabled" BOOLEAN NOT NULL DEFAULT false;
+
+-- CreateTable
+CREATE TABLE "EventTypeTranslation" (
+ "id" TEXT NOT NULL,
+ "eventTypeId" INTEGER NOT NULL,
+ "field" "EventTypeAutoTranslatedField" NOT NULL,
+ "sourceLang" TEXT NOT NULL,
+ "targetLang" TEXT NOT NULL,
+ "translatedText" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "createdBy" INTEGER NOT NULL,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "updatedBy" INTEGER,
+
+ CONSTRAINT "EventTypeTranslation_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE INDEX "EventTypeTranslation_eventTypeId_field_targetLang_idx" ON "EventTypeTranslation"("eventTypeId", "field", "targetLang");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "EventTypeTranslation_eventTypeId_field_targetLang_key" ON "EventTypeTranslation"("eventTypeId", "field", "targetLang");
+
+-- AddForeignKey
+ALTER TABLE "EventTypeTranslation" ADD CONSTRAINT "EventTypeTranslation_eventTypeId_fkey" FOREIGN KEY ("eventTypeId") REFERENCES "EventType"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma
index b1ac89be8f..4965f8272d 100644
--- a/packages/prisma/schema.prisma
+++ b/packages/prisma/schema.prisma
@@ -110,6 +110,7 @@ model EventType {
requiresConfirmation Boolean @default(false)
requiresConfirmationWillBlockSlot Boolean @default(false)
requiresBookerEmailVerification Boolean @default(false)
+ autoTranslateDescriptionEnabled Boolean @default(false)
/// @zod.custom(imports.recurringEventType)
recurringEvent Json?
disableGuests Boolean @default(false)
@@ -149,6 +150,7 @@ model EventType {
useEventTypeDestinationCalendarEmail Boolean @default(false)
aiPhoneCallConfig AIPhoneCallConfiguration?
isRRWeightsEnabled Boolean @default(false)
+ fieldTranslations EventTypeTranslation[]
maxLeadThreshold Int?
/// @zod.custom(imports.eventTypeColor)
@@ -1590,3 +1592,24 @@ model AttributeToUser {
@@unique([memberId, attributeOptionId])
}
+
+enum EventTypeAutoTranslatedField {
+ DESCRIPTION // Currently the only field we translate
+}
+
+model EventTypeTranslation {
+ id String @id @default(cuid())
+ eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
+ eventTypeId Int
+ field EventTypeAutoTranslatedField
+ sourceLang String
+ targetLang String
+ translatedText String @db.Text
+ createdAt DateTime @default(now())
+ createdBy Int
+ updatedAt DateTime @updatedAt
+ updatedBy Int?
+
+ @@unique([eventTypeId, field, targetLang])
+ @@index([eventTypeId, field, targetLang])
+}
diff --git a/packages/trpc/server/routers/viewer/eventTypes/update.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/update.handler.ts
index 6706dbfdc0..9a73c89379 100644
--- a/packages/trpc/server/routers/viewer/eventTypes/update.handler.ts
+++ b/packages/trpc/server/routers/viewer/eventTypes/update.handler.ts
@@ -35,6 +35,7 @@ type User = {
id: SessionUser["profile"]["id"] | null;
};
selectedCalendars: SessionUser["selectedCalendars"];
+ organizationId: number | null;
};
type UpdateOptions = {
@@ -74,6 +75,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
secondaryEmailId,
aiPhoneCallConfig,
isRRWeightsEnabled,
+ autoTranslateDescriptionEnabled,
...rest
} = input;
@@ -153,6 +155,8 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
const data: Prisma.EventTypeUpdateInput = {
...rest,
+ // autoTranslate feature is allowed for org users only
+ autoTranslateDescriptionEnabled: !!(ctx.user.organizationId && autoTranslateDescriptionEnabled),
bookingFields,
isRRWeightsEnabled,
metadata: rest.metadata === null ? Prisma.DbNull : (rest.metadata as Prisma.InputJsonObject),
diff --git a/yarn.lock b/yarn.lock
index 436318fee4..02ec1d6862 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5045,6 +5045,7 @@ __metadata:
"@radix-ui/react-switch": ^1.0.0
"@radix-ui/react-toggle-group": ^1.0.0
"@radix-ui/react-tooltip": ^1.0.0
+ "@replexica/sdk": ^0.6.0
"@sentry/nextjs": ^8.8.0
"@stripe/react-stripe-js": ^1.10.0
"@stripe/stripe-js": ^1.35.0
@@ -9980,7 +9981,7 @@ __metadata:
languageName: node
linkType: hard
-"@paralleldrive/cuid2@npm:2.2.2":
+"@paralleldrive/cuid2@npm:2.2.2, @paralleldrive/cuid2@npm:^2.2.2":
version: 2.2.2
resolution: "@paralleldrive/cuid2@npm:2.2.2"
dependencies:
@@ -12366,6 +12367,31 @@ __metadata:
languageName: node
linkType: hard
+"@replexica/sdk@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "@replexica/sdk@npm:0.6.0"
+ dependencies:
+ "@paralleldrive/cuid2": ^2.2.2
+ "@replexica/spec": 0.18.0
+ jsdom: ^25.0.1
+ typescript: ^5.6.3
+ vitest: ^2.1.4
+ zod: ^3.23.8
+ checksum: 95a239cf24025a8ea1a03b0720c8a1bd351f73777015fd3a8b74995740fb191c87d157ac04e7b1824f9b5b8f27cef3ce1b7126deb7bf7683b74b8435d3de1238
+ languageName: node
+ linkType: hard
+
+"@replexica/spec@npm:0.18.0":
+ version: 0.18.0
+ resolution: "@replexica/spec@npm:0.18.0"
+ dependencies:
+ typescript: ^5.6.3
+ vitest: ^2.1.4
+ zod: ^3.23.8
+ checksum: d9afcfd965b804d395436cc6daf9a051142e13658297e45f742a6397699360e8f28d43399c4c31077b250ca965e1733200bf8c63eae328b4960320d2dd6ae5b5
+ languageName: node
+ linkType: hard
+
"@resvg/resvg-wasm@npm:2.4.0":
version: 2.4.0
resolution: "@resvg/resvg-wasm@npm:2.4.0"
@@ -17462,6 +17488,18 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/expect@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/expect@npm:2.1.5"
+ dependencies:
+ "@vitest/spy": 2.1.5
+ "@vitest/utils": 2.1.5
+ chai: ^5.1.2
+ tinyrainbow: ^1.2.0
+ checksum: feb3dc9397d43a84525ee1966efc940d2175a4ca939b142239a875d43de1efbbfcd347440c2703f74560643c079b0ea1b52a46b80b7e4945f6d5a9ab5762c007
+ languageName: node
+ linkType: hard
+
"@vitest/mocker@npm:2.1.1":
version: 2.1.1
resolution: "@vitest/mocker@npm:2.1.1"
@@ -17482,6 +17520,25 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/mocker@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/mocker@npm:2.1.5"
+ dependencies:
+ "@vitest/spy": 2.1.5
+ estree-walker: ^3.0.3
+ magic-string: ^0.30.12
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+ checksum: 165db0dfdbd78da68be2e880638f5a8ff603745d80acbe0353d4d3c72233d9991545dda746db8c66e592baf9c8d880310681042da9b819affeca9f7a2dd7f389
+ languageName: node
+ linkType: hard
+
"@vitest/pretty-format@npm:2.1.1, @vitest/pretty-format@npm:^2.1.1":
version: 2.1.1
resolution: "@vitest/pretty-format@npm:2.1.1"
@@ -17491,6 +17548,15 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/pretty-format@npm:2.1.5, @vitest/pretty-format@npm:^2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/pretty-format@npm:2.1.5"
+ dependencies:
+ tinyrainbow: ^1.2.0
+ checksum: 0d470aabe0b27825c19da9e922bd2da073da5a7bdf0db7b101107c83f3071d728d98633b465d73b90c3fd68926f750fbf50d322140853fb30bad51389c766074
+ languageName: node
+ linkType: hard
+
"@vitest/runner@npm:2.1.1":
version: 2.1.1
resolution: "@vitest/runner@npm:2.1.1"
@@ -17501,6 +17567,16 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/runner@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/runner@npm:2.1.5"
+ dependencies:
+ "@vitest/utils": 2.1.5
+ pathe: ^1.1.2
+ checksum: 93ee4c4e23a958a33b0214859f3e5552e2dcaf18625302ac8e824e22ffc4cadb52e6de0b62a1dcfeb7aeae59cde097c21792c9b753f4bde6fbb391f3902e5193
+ languageName: node
+ linkType: hard
+
"@vitest/snapshot@npm:2.1.1":
version: 2.1.1
resolution: "@vitest/snapshot@npm:2.1.1"
@@ -17512,6 +17588,17 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/snapshot@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/snapshot@npm:2.1.5"
+ dependencies:
+ "@vitest/pretty-format": 2.1.5
+ magic-string: ^0.30.12
+ pathe: ^1.1.2
+ checksum: bb61537367e4f51071234a7917f4c12eb564a243fb9dcd056b44d22cd3b108d2e0da428a8d0fe0363dd12e9b9aeabe155e3d4ae7c849c2e6be932329f6977801
+ languageName: node
+ linkType: hard
+
"@vitest/spy@npm:2.1.1, @vitest/spy@npm:^2.1.0-beta.1":
version: 2.1.1
resolution: "@vitest/spy@npm:2.1.1"
@@ -17521,6 +17608,15 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/spy@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/spy@npm:2.1.5"
+ dependencies:
+ tinyspy: ^3.0.2
+ checksum: db5aec91b3ac9130537c0e619940cbb8aebbd7fb2af4da9c42804d0bc7179dec75cd9573b56d8a1ec1c845e5751e3ba1dbc30b07fa38d637f241d77b45c37fbe
+ languageName: node
+ linkType: hard
+
"@vitest/ui@npm:^2.1.1":
version: 2.1.1
resolution: "@vitest/ui@npm:2.1.1"
@@ -17549,6 +17645,17 @@ __metadata:
languageName: node
linkType: hard
+"@vitest/utils@npm:2.1.5":
+ version: 2.1.5
+ resolution: "@vitest/utils@npm:2.1.5"
+ dependencies:
+ "@vitest/pretty-format": 2.1.5
+ loupe: ^3.1.2
+ tinyrainbow: ^1.2.0
+ checksum: f12f6d95d058b537afd9e0b0af1075a80bf77789f32b75bf6a110a2bbf5afd08930ee71a0bd53bfb42bc923e4706d5e26c41df0e1c2854db1a668a011d6c010a
+ languageName: node
+ linkType: hard
+
"@volar/language-core@npm:1.11.1, @volar/language-core@npm:~1.11.1":
version: 1.11.1
resolution: "@volar/language-core@npm:1.11.1"
@@ -20429,6 +20536,19 @@ __metadata:
languageName: node
linkType: hard
+"chai@npm:^5.1.2":
+ version: 5.1.2
+ resolution: "chai@npm:5.1.2"
+ dependencies:
+ assertion-error: ^2.0.1
+ check-error: ^2.1.1
+ deep-eql: ^5.0.1
+ loupe: ^3.1.0
+ pathval: ^2.0.0
+ checksum: f2341967ab5632612548d372c27b46219adad3af35021d8cba2ae3c262f588de2c60cb3f004e6ad40e363a9cad6d20d0de51f00e7e9ac31cce17fb05d4efa316
+ languageName: node
+ linkType: hard
+
"chalk@npm:3.0.0, chalk@npm:^3.0.0":
version: 3.0.0
resolution: "chalk@npm:3.0.0"
@@ -22184,6 +22304,15 @@ __metadata:
languageName: node
linkType: hard
+"cssstyle@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "cssstyle@npm:4.1.0"
+ dependencies:
+ rrweb-cssom: ^0.7.1
+ checksum: a8f5746430c42347e76dc830548f3a296882e42a90af188ae44e4c1a4131aec246b0b6c8562e3e6e4fa0ff14aeee5cd14a0e2fe5a7105dcf39f98eb70d16b634
+ languageName: node
+ linkType: hard
+
"csstype@npm:^3.0.2":
version: 3.1.0
resolution: "csstype@npm:3.1.0"
@@ -22374,6 +22503,16 @@ __metadata:
languageName: node
linkType: hard
+"data-urls@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "data-urls@npm:5.0.0"
+ dependencies:
+ whatwg-mimetype: ^4.0.0
+ whatwg-url: ^14.0.0
+ checksum: 5c40568c31b02641a70204ff233bc4e42d33717485d074244a98661e5f2a1e80e38fe05a5755dfaf2ee549f2ab509d6a3af2a85f4b2ad2c984e5d176695eaf46
+ languageName: node
+ linkType: hard
+
"data-view-buffer@npm:^1.0.1":
version: 1.0.1
resolution: "data-view-buffer@npm:1.0.1"
@@ -22498,7 +22637,7 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:^4.3.6":
+"debug@npm:^4.3.6, debug@npm:^4.3.7":
version: 4.3.7
resolution: "debug@npm:4.3.7"
dependencies:
@@ -23989,6 +24128,13 @@ __metadata:
languageName: node
linkType: hard
+"es-module-lexer@npm:^1.5.4":
+ version: 1.5.4
+ resolution: "es-module-lexer@npm:1.5.4"
+ checksum: a0cf04fb92d052647ac7d818d1913b98d3d3d0f5b9d88f0eafb993436e4c3e2c958599db68839d57f2dfa281fdf0f60e18d448eb78fc292c33c0f25635b6854f
+ languageName: node
+ linkType: hard
+
"es-object-atoms@npm:^1.0.0":
version: 1.0.0
resolution: "es-object-atoms@npm:1.0.0"
@@ -25199,6 +25345,13 @@ __metadata:
languageName: node
linkType: hard
+"expect-type@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "expect-type@npm:1.1.0"
+ checksum: 65d25ec10bca32bcf650dcfe734532acc4b7a73677c656f299a7cbed273b5c4d6a3dab11af76f452645d54a95c4ef39fc73772f2c8eb6684ba35672958d6f3b3
+ languageName: node
+ linkType: hard
+
"expect@npm:^29.0.0":
version: 29.6.1
resolution: "expect@npm:29.6.1"
@@ -27674,6 +27827,15 @@ __metadata:
languageName: node
linkType: hard
+"html-encoding-sniffer@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "html-encoding-sniffer@npm:4.0.0"
+ dependencies:
+ whatwg-encoding: ^3.1.1
+ checksum: 3339b71dab2723f3159a56acf541ae90a408ce2d11169f00fe7e0c4663d31d6398c8a4408b504b4eec157444e47b084df09b3cb039c816660f0dd04846b8957d
+ languageName: node
+ linkType: hard
+
"html-entities@npm:^2.1.0":
version: 2.3.3
resolution: "html-entities@npm:2.3.3"
@@ -27864,7 +28026,7 @@ __metadata:
languageName: node
linkType: hard
-"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1":
+"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1, http-proxy-agent@npm:^7.0.2":
version: 7.0.2
resolution: "http-proxy-agent@npm:7.0.2"
dependencies:
@@ -27995,7 +28157,7 @@ __metadata:
languageName: node
linkType: hard
-"https-proxy-agent@npm:^7.0.0":
+"https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.5":
version: 7.0.5
resolution: "https-proxy-agent@npm:7.0.5"
dependencies:
@@ -30516,6 +30678,40 @@ __metadata:
languageName: node
linkType: hard
+"jsdom@npm:^25.0.1":
+ version: 25.0.1
+ resolution: "jsdom@npm:25.0.1"
+ dependencies:
+ cssstyle: ^4.1.0
+ data-urls: ^5.0.0
+ decimal.js: ^10.4.3
+ form-data: ^4.0.0
+ html-encoding-sniffer: ^4.0.0
+ http-proxy-agent: ^7.0.2
+ https-proxy-agent: ^7.0.5
+ is-potential-custom-element-name: ^1.0.1
+ nwsapi: ^2.2.12
+ parse5: ^7.1.2
+ rrweb-cssom: ^0.7.1
+ saxes: ^6.0.0
+ symbol-tree: ^3.2.4
+ tough-cookie: ^5.0.0
+ w3c-xmlserializer: ^5.0.0
+ webidl-conversions: ^7.0.0
+ whatwg-encoding: ^3.1.1
+ whatwg-mimetype: ^4.0.0
+ whatwg-url: ^14.0.0
+ ws: ^8.18.0
+ xml-name-validator: ^5.0.0
+ peerDependencies:
+ canvas: ^2.11.2
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+ checksum: b637d28445d570014195b3c77d06e54ef69d1f807eaf61388cb470e4d9227244e7fe2e0c32b6df03ac4fe35f746d7c721672d9136ecebb49d2e61a04ab9628e0
+ languageName: node
+ linkType: hard
+
"jsesc@npm:^2.5.1":
version: 2.5.2
resolution: "jsesc@npm:2.5.2"
@@ -31753,6 +31949,13 @@ __metadata:
languageName: node
linkType: hard
+"loupe@npm:^3.1.2":
+ version: 3.1.2
+ resolution: "loupe@npm:3.1.2"
+ checksum: 4a75bbe8877a1ced3603e08b1095cd6f4c987c50fe63719fdc3009029560f91e07a915e7f6eff1322bb62bfb2a2beeef06b13ccb3c12f81bda9f3674434dcab9
+ languageName: node
+ linkType: hard
+
"lower-case-first@npm:^1.0.0":
version: 1.0.2
resolution: "lower-case-first@npm:1.0.2"
@@ -32006,6 +32209,15 @@ __metadata:
languageName: node
linkType: hard
+"magic-string@npm:^0.30.12":
+ version: 0.30.12
+ resolution: "magic-string@npm:0.30.12"
+ dependencies:
+ "@jridgewell/sourcemap-codec": ^1.5.0
+ checksum: 3f0d23b74371765f0e6cad4284eebba0ac029c7a55e39292de5aa92281afb827138cb2323d24d2924f6b31f138c3783596c5ccaa98653fe9cf122e1f81325b59
+ languageName: node
+ linkType: hard
+
"mailhog@npm:^4.16.0":
version: 4.16.0
resolution: "mailhog@npm:4.16.0"
@@ -34148,6 +34360,13 @@ __metadata:
languageName: node
linkType: hard
+"nwsapi@npm:^2.2.12":
+ version: 2.2.13
+ resolution: "nwsapi@npm:2.2.13"
+ checksum: d34fb7838517c3c7e8cc824e443275b08b57f6a025a860693d18c56ddcfd176e32df9bf0ae7f5a95c7a32981501caa1f9fda31b59f28aa72a4b9d01f573a8e6b
+ languageName: node
+ linkType: hard
+
"nwsapi@npm:^2.2.4":
version: 2.2.4
resolution: "nwsapi@npm:2.2.4"
@@ -36840,6 +37059,13 @@ __metadata:
languageName: node
linkType: hard
+"punycode@npm:^2.3.1":
+ version: 2.3.1
+ resolution: "punycode@npm:2.3.1"
+ checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2
+ languageName: node
+ linkType: hard
+
"pupa@npm:^3.1.0":
version: 3.1.0
resolution: "pupa@npm:3.1.0"
@@ -39303,6 +39529,13 @@ __metadata:
languageName: node
linkType: hard
+"rrweb-cssom@npm:^0.7.1":
+ version: 0.7.1
+ resolution: "rrweb-cssom@npm:0.7.1"
+ checksum: 62e410ddbaaba6abc196c3bbfa8de4952e0a134d9f2b454ee293039bf9931322d806e14d52ed122a5c2bd332a868b9da2e99358fb6232c33758b5ede86d992c8
+ languageName: node
+ linkType: hard
+
"rtl-css-js@npm:^1.16.1":
version: 1.16.1
resolution: "rtl-css-js@npm:1.16.1"
@@ -40611,6 +40844,13 @@ __metadata:
languageName: node
linkType: hard
+"std-env@npm:^3.8.0":
+ version: 3.8.0
+ resolution: "std-env@npm:3.8.0"
+ checksum: ad4554485c2d09138a1d0f03944245e169510e6f5200b7d30fcdd4536e27a2a9a2fd934caff7ef58ebbe21993fa0e2b9e5b1979f431743c925305863b7ff36d5
+ languageName: node
+ linkType: hard
+
"stdin-discarder@npm:^0.2.1":
version: 0.2.2
resolution: "stdin-discarder@npm:0.2.2"
@@ -42119,6 +42359,13 @@ __metadata:
languageName: node
linkType: hard
+"tinyexec@npm:^0.3.1":
+ version: 0.3.1
+ resolution: "tinyexec@npm:0.3.1"
+ checksum: 691b531d464bdc09eeba934e43d8ac2a74c9d22a4bec9cd7f4991375c64e22712f7e5a95ba243a9369a478afd34d41171359012a2248ea49615cd2816ab12959
+ languageName: node
+ linkType: hard
+
"tinyglobby@npm:^0.2.6":
version: 0.2.6
resolution: "tinyglobby@npm:0.2.6"
@@ -42146,6 +42393,13 @@ __metadata:
languageName: node
linkType: hard
+"tinypool@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "tinypool@npm:1.0.2"
+ checksum: 752f23114d8fc95a9497fc812231d6d0a63728376aa11e6e8499c10423a91112e760e388887ea7854f1b16977c321f07c0eab061ec2f60f6761e58b184aac880
+ languageName: node
+ linkType: hard
+
"tinyrainbow@npm:^1.2.0":
version: 1.2.0
resolution: "tinyrainbow@npm:1.2.0"
@@ -42153,7 +42407,7 @@ __metadata:
languageName: node
linkType: hard
-"tinyspy@npm:^3.0.0":
+"tinyspy@npm:^3.0.0, tinyspy@npm:^3.0.2":
version: 3.0.2
resolution: "tinyspy@npm:3.0.2"
checksum: 5db671b2ff5cd309de650c8c4761ca945459d7204afb1776db9a04fb4efa28a75f08517a8620c01ee32a577748802231ad92f7d5b194dc003ee7f987a2a06337
@@ -42170,6 +42424,24 @@ __metadata:
languageName: node
linkType: hard
+"tldts-core@npm:^6.1.61":
+ version: 6.1.61
+ resolution: "tldts-core@npm:6.1.61"
+ checksum: 659411060be80658bd492cf0f3a38223c0cc15e2ffb402e219e51dcfcffcdd581c00e63e494944d4e7ff0a0aeb321058f7811d9089fac455ae0c10b4f5beffd1
+ languageName: node
+ linkType: hard
+
+"tldts@npm:^6.1.32":
+ version: 6.1.61
+ resolution: "tldts@npm:6.1.61"
+ dependencies:
+ tldts-core: ^6.1.61
+ bin:
+ tldts: bin/cli.js
+ checksum: 1d2feafe6160147a2f5ea520ebc84c77153edacd0d69510726ee0c13b2fce8b84d1bad79f2c5337ac361d297d0d16815fe5d3c51c88a7822d2320a75f6d2dea3
+ languageName: node
+ linkType: hard
+
"tmp@npm:0.2.1":
version: 0.2.1
resolution: "tmp@npm:0.2.1"
@@ -42284,6 +42556,15 @@ __metadata:
languageName: node
linkType: hard
+"tough-cookie@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "tough-cookie@npm:5.0.0"
+ dependencies:
+ tldts: ^6.1.32
+ checksum: 774f6c939c96f74b5847361f7e11e0d69383681d21a35a2d37a20956638e614ec521782d2d20bcb32b58638ff337bba87cc72fb72c987bd02ea0fdfc93994cdb
+ languageName: node
+ linkType: hard
+
"tough-cookie@npm:~2.5.0":
version: 2.5.0
resolution: "tough-cookie@npm:2.5.0"
@@ -42303,6 +42584,15 @@ __metadata:
languageName: node
linkType: hard
+"tr46@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "tr46@npm:5.0.0"
+ dependencies:
+ punycode: ^2.3.1
+ checksum: 8d8b021f8e17675ebf9e672c224b6b6cfdb0d5b92141349e9665c14a2501c54a298d11264bbb0b17b447581e1e83d4fc3c038c929f3d210e3964d4be47460288
+ languageName: node
+ linkType: hard
+
"tr46@npm:~0.0.3":
version: 0.0.3
resolution: "tr46@npm:0.0.3"
@@ -43215,6 +43505,16 @@ __metadata:
languageName: node
linkType: hard
+"typescript@npm:^5.6.3":
+ version: 5.6.3
+ resolution: "typescript@npm:5.6.3"
+ bin:
+ tsc: bin/tsc
+ tsserver: bin/tsserver
+ checksum: ba302f8822777ebefb28b554105f3e074466b671e7444ec6b75dadc008a62f46f373d9e57ceced1c433756d06c8b7dc569a7eefdf3a9573122a49205ff99021a
+ languageName: node
+ linkType: hard
+
"typescript@patch:typescript@5.3.3#~builtin":
version: 5.3.3
resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=1f5320"
@@ -43245,6 +43545,16 @@ __metadata:
languageName: node
linkType: hard
+"typescript@patch:typescript@^5.6.3#~builtin":
+ version: 5.6.3
+ resolution: "typescript@patch:typescript@npm%3A5.6.3#~builtin::version=5.6.3&hash=1f5320"
+ bin:
+ tsc: bin/tsc
+ tsserver: bin/tsserver
+ checksum: ade87bce2363ee963eed0e4ca8a312ea02c81873ebd53609bc3f6dc0a57f6e61ad7e3fb8cbb7f7ab8b5081cbee801b023f7c4823ee70b1c447eae050e6c7622b
+ languageName: node
+ linkType: hard
+
"tzdata@npm:^1.0.30":
version: 1.0.40
resolution: "tzdata@npm:1.0.40"
@@ -43901,6 +44211,21 @@ __metadata:
languageName: node
linkType: hard
+"vite-node@npm:2.1.5":
+ version: 2.1.5
+ resolution: "vite-node@npm:2.1.5"
+ dependencies:
+ cac: ^6.7.14
+ debug: ^4.3.7
+ es-module-lexer: ^1.5.4
+ pathe: ^1.1.2
+ vite: ^5.0.0
+ bin:
+ vite-node: vite-node.mjs
+ checksum: b7c12c330f0cf5bb63fd6d36c38d7f1f9ed5cea5a7407db626945038c66e3e4165f79bdbcb928c6a289f299f434fb0a30bd1ab5c9c0d50eb892164bcdc37d167
+ languageName: node
+ linkType: hard
+
"vite-plugin-dts@npm:^3.7.2, vite-plugin-dts@npm:^3.7.3":
version: 3.7.3
resolution: "vite-plugin-dts@npm:3.7.3"
@@ -44199,6 +44524,56 @@ __metadata:
languageName: node
linkType: hard
+"vitest@npm:^2.1.4":
+ version: 2.1.5
+ resolution: "vitest@npm:2.1.5"
+ dependencies:
+ "@vitest/expect": 2.1.5
+ "@vitest/mocker": 2.1.5
+ "@vitest/pretty-format": ^2.1.5
+ "@vitest/runner": 2.1.5
+ "@vitest/snapshot": 2.1.5
+ "@vitest/spy": 2.1.5
+ "@vitest/utils": 2.1.5
+ chai: ^5.1.2
+ debug: ^4.3.7
+ expect-type: ^1.1.0
+ magic-string: ^0.30.12
+ pathe: ^1.1.2
+ std-env: ^3.8.0
+ tinybench: ^2.9.0
+ tinyexec: ^0.3.1
+ tinypool: ^1.0.1
+ tinyrainbow: ^1.2.0
+ vite: ^5.0.0
+ vite-node: 2.1.5
+ why-is-node-running: ^2.3.0
+ peerDependencies:
+ "@edge-runtime/vm": "*"
+ "@types/node": ^18.0.0 || >=20.0.0
+ "@vitest/browser": 2.1.5
+ "@vitest/ui": 2.1.5
+ happy-dom: "*"
+ jsdom: "*"
+ peerDependenciesMeta:
+ "@edge-runtime/vm":
+ optional: true
+ "@types/node":
+ optional: true
+ "@vitest/browser":
+ optional: true
+ "@vitest/ui":
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+ bin:
+ vitest: vitest.mjs
+ checksum: 1a7ddc055aae55452d7fce86cd9aeb92dcdcc3d51105dd87c34c2c0ac2c508c3e20be36c855568686fe19fb06e9f2568fca511ae70511a782155a3449dbdc083
+ languageName: node
+ linkType: hard
+
"vm-browserify@npm:^1.0.1, vm-browserify@npm:^1.1.2":
version: 1.1.2
resolution: "vm-browserify@npm:1.1.2"
@@ -44247,6 +44622,15 @@ __metadata:
languageName: node
linkType: hard
+"w3c-xmlserializer@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "w3c-xmlserializer@npm:5.0.0"
+ dependencies:
+ xml-name-validator: ^5.0.0
+ checksum: 593acc1fdab3f3207ec39d851e6df0f3fa41a36b5809b0ace364c7a6d92e351938c53424a7618ce8e0fbaffee8be2e8e070a5734d05ee54666a8bdf1a376cc40
+ languageName: node
+ linkType: hard
+
"walker@npm:^1.0.8":
version: 1.0.8
resolution: "walker@npm:1.0.8"
@@ -44519,6 +44903,15 @@ __metadata:
languageName: node
linkType: hard
+"whatwg-encoding@npm:^3.1.1":
+ version: 3.1.1
+ resolution: "whatwg-encoding@npm:3.1.1"
+ dependencies:
+ iconv-lite: 0.6.3
+ checksum: f75a61422421d991e4aec775645705beaf99a16a88294d68404866f65e92441698a4f5b9fa11dd609017b132d7b286c3c1534e2de5b3e800333856325b549e3c
+ languageName: node
+ linkType: hard
+
"whatwg-fetch@npm:^3.4.1, whatwg-fetch@npm:^3.6.2":
version: 3.6.20
resolution: "whatwg-fetch@npm:3.6.20"
@@ -44533,6 +44926,13 @@ __metadata:
languageName: node
linkType: hard
+"whatwg-mimetype@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "whatwg-mimetype@npm:4.0.0"
+ checksum: f97edd4b4ee7e46a379f3fb0e745de29fe8b839307cc774300fd49059fcdd560d38cb8fe21eae5575b8f39b022f23477cc66e40b0355c2851ce84760339cef30
+ languageName: node
+ linkType: hard
+
"whatwg-url@npm:^12.0.0, whatwg-url@npm:^12.0.1":
version: 12.0.1
resolution: "whatwg-url@npm:12.0.1"
@@ -44553,6 +44953,16 @@ __metadata:
languageName: node
linkType: hard
+"whatwg-url@npm:^14.0.0":
+ version: 14.0.0
+ resolution: "whatwg-url@npm:14.0.0"
+ dependencies:
+ tr46: ^5.0.0
+ webidl-conversions: ^7.0.0
+ checksum: 4b5887e50f786583bead70916413e67a381d2126899b9eb5c67ce664bba1e7ec07cdff791404581ce73c6190d83c359c9ca1d50711631217905db3877dec075c
+ languageName: node
+ linkType: hard
+
"whatwg-url@npm:^5.0.0":
version: 5.0.0
resolution: "whatwg-url@npm:5.0.0"
@@ -44906,6 +45316,21 @@ __metadata:
languageName: node
linkType: hard
+"ws@npm:^8.18.0":
+ version: 8.18.0
+ resolution: "ws@npm:8.18.0"
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ">=5.0.2"
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+ checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975
+ languageName: node
+ linkType: hard
+
"xdg-basedir@npm:^5.0.1, xdg-basedir@npm:^5.1.0":
version: 5.1.0
resolution: "xdg-basedir@npm:5.1.0"
@@ -44974,6 +45399,13 @@ __metadata:
languageName: node
linkType: hard
+"xml-name-validator@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "xml-name-validator@npm:5.0.0"
+ checksum: 86effcc7026f437701252fcc308b877b4bc045989049cfc79b0cc112cb365cf7b009f4041fab9fb7cd1795498722c3e9fe9651afc66dfa794c16628a639a4c45
+ languageName: node
+ linkType: hard
+
"xml-parse-from-string@npm:^1.0.0":
version: 1.0.1
resolution: "xml-parse-from-string@npm:1.0.1"
@@ -45386,6 +45818,13 @@ __metadata:
languageName: node
linkType: hard
+"zod@npm:^3.23.8":
+ version: 3.23.8
+ resolution: "zod@npm:3.23.8"
+ checksum: 15949ff82118f59c893dacd9d3c766d02b6fa2e71cf474d5aa888570c469dbf5446ac5ad562bb035bf7ac9650da94f290655c194f4a6de3e766f43febd432c5c
+ languageName: node
+ linkType: hard
+
"zustand@npm:^4.3.2":
version: 4.5.2
resolution: "zustand@npm:4.5.2"