diff --git a/.github/workflows/test_next_server.yml b/.github/workflows/test_next_server.yml
index 892566d6..fed6b1a1 100644
--- a/.github/workflows/test_next_server.yml
+++ b/.github/workflows/test_next_server.yml
@@ -13,6 +13,9 @@ on:
jobs:
test-next-server:
runs-on: ubuntu-latest
+ concurrency:
+ group: test-next-server-${{ github.ref }}
+ cancel-in-progress: true
defaults:
run:
@@ -21,17 +24,12 @@ jobs:
steps:
- uses: actions/checkout@v4
- - name: Setup Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '20'
-
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
- version: 8
+ package_json_file: './www/package.json'
- - name: Setup Node.js cache
+ - name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
diff --git a/www/app/lib/__tests__/meetingStatusBatcher.test.tsx b/www/app/lib/__tests__/meetingStatusBatcher.test.tsx
new file mode 100644
index 00000000..43b5a4be
--- /dev/null
+++ b/www/app/lib/__tests__/meetingStatusBatcher.test.tsx
@@ -0,0 +1,220 @@
+import "@testing-library/jest-dom";
+
+// --- Module mocks (hoisted before imports) ---
+
+jest.mock("../apiClient", () => ({
+ client: {
+ GET: jest.fn(),
+ POST: jest.fn(),
+ PUT: jest.fn(),
+ PATCH: jest.fn(),
+ DELETE: jest.fn(),
+ use: jest.fn(),
+ },
+ $api: {
+ useQuery: jest.fn(),
+ useMutation: jest.fn(),
+ },
+ API_URL: "http://test",
+ WEBSOCKET_URL: "ws://test",
+ configureApiAuth: jest.fn(),
+}));
+
+jest.mock("../AuthProvider", () => ({
+ useAuth: () => ({
+ status: "authenticated" as const,
+ accessToken: "test-token",
+ accessTokenExpires: Date.now() + 3600000,
+ user: { id: "user1", name: "Test User" },
+ update: jest.fn(),
+ signIn: jest.fn(),
+ signOut: jest.fn(),
+ lastUserId: "user1",
+ }),
+}));
+
+// Recreate the batcher with a 0ms window. setTimeout(fn, 0) defers to the next
+// macrotask boundary — after all synchronous React rendering completes. All
+// useQuery queryFns fire within the same macrotask, so they all queue into one
+// batch before the timer fires. This is deterministic and avoids fake timers.
+jest.mock("../meetingStatusBatcher", () => {
+ const actual = jest.requireActual("../meetingStatusBatcher");
+ return {
+ ...actual,
+ meetingStatusBatcher: actual.createMeetingStatusBatcher(0),
+ };
+});
+
+// --- Imports (after mocks) ---
+
+import React from "react";
+import { render, waitFor, screen } from "@testing-library/react";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { useRoomActiveMeetings, useRoomUpcomingMeetings } from "../apiHooks";
+import { client } from "../apiClient";
+import { ErrorProvider } from "../../(errors)/errorContext";
+
+const mockClient = client as { POST: jest.Mock };
+
+// --- Helpers ---
+
+function mockBulkStatusEndpoint(
+ roomData?: Record<
+ string,
+ { active_meetings: unknown[]; upcoming_events: unknown[] }
+ >,
+) {
+ mockClient.POST.mockImplementation(
+ async (_path: string, options: { body: { room_names: string[] } }) => {
+ const roomNames: string[] = options.body.room_names;
+ const data = roomData
+ ? Object.fromEntries(
+ roomNames.map((name) => [
+ name,
+ roomData[name] ?? { active_meetings: [], upcoming_events: [] },
+ ]),
+ )
+ : Object.fromEntries(
+ roomNames.map((name) => [
+ name,
+ { active_meetings: [], upcoming_events: [] },
+ ]),
+ );
+ return { data, error: undefined, response: {} };
+ },
+ );
+}
+
+// --- Test component: renders N room cards, each using both hooks ---
+
+function RoomCard({ roomName }: { roomName: string }) {
+ const active = useRoomActiveMeetings(roomName);
+ const upcoming = useRoomUpcomingMeetings(roomName);
+
+ if (active.isLoading || upcoming.isLoading) {
+ return
loading
;
+ }
+
+ return (
+
+ {active.data?.length ?? 0} active, {upcoming.data?.length ?? 0} upcoming
+
+ );
+}
+
+function RoomList({ roomNames }: { roomNames: string[] }) {
+ return (
+ <>
+ {roomNames.map((name) => (
+
+ ))}
+ >
+ );
+}
+
+function createWrapper() {
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { retry: false },
+ },
+ });
+ return function Wrapper({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+ };
+}
+
+// --- Tests ---
+
+describe("meeting status batcher integration", () => {
+ afterEach(() => jest.clearAllMocks());
+
+ it("batches multiple room queries into a single POST request", async () => {
+ const rooms = Array.from({ length: 10 }, (_, i) => `room-${i}`);
+
+ mockBulkStatusEndpoint();
+
+ render(, { wrapper: createWrapper() });
+
+ await waitFor(() => {
+ for (const name of rooms) {
+ expect(screen.getByTestId(`room-${name}`)).toHaveTextContent(
+ "0 active, 0 upcoming",
+ );
+ }
+ });
+
+ const postCalls = mockClient.POST.mock.calls.filter(
+ ([path]: [string]) => path === "/v1/rooms/meetings/bulk-status",
+ );
+
+ // Without batching this would be 20 calls (2 hooks x 10 rooms).
+ // With the 200ms test window, all queries land in one batch → exactly 1 POST.
+ expect(postCalls).toHaveLength(1);
+
+ // The single call should contain all 10 rooms (deduplicated)
+ const requestedRooms: string[] = postCalls[0][1].body.room_names;
+ for (const name of rooms) {
+ expect(requestedRooms).toContain(name);
+ }
+ });
+
+ it("batcher fetcher returns room-specific data", async () => {
+ const {
+ meetingStatusBatcher: batcher,
+ } = require("../meetingStatusBatcher");
+
+ mockBulkStatusEndpoint({
+ "room-a": {
+ active_meetings: [{ id: "m1", room_name: "room-a" }],
+ upcoming_events: [],
+ },
+ "room-b": {
+ active_meetings: [],
+ upcoming_events: [{ id: "e1", title: "Standup" }],
+ },
+ });
+
+ const [resultA, resultB] = await Promise.all([
+ batcher.fetch("room-a"),
+ batcher.fetch("room-b"),
+ ]);
+
+ expect(mockClient.POST).toHaveBeenCalledTimes(1);
+ expect(resultA.active_meetings).toEqual([
+ { id: "m1", room_name: "room-a" },
+ ]);
+ expect(resultA.upcoming_events).toEqual([]);
+ expect(resultB.active_meetings).toEqual([]);
+ expect(resultB.upcoming_events).toEqual([{ id: "e1", title: "Standup" }]);
+ });
+
+ it("renders room-specific meeting data through hooks", async () => {
+ mockBulkStatusEndpoint({
+ "room-a": {
+ active_meetings: [{ id: "m1", room_name: "room-a" }],
+ upcoming_events: [],
+ },
+ "room-b": {
+ active_meetings: [],
+ upcoming_events: [{ id: "e1", title: "Standup" }],
+ },
+ });
+
+ render(, {
+ wrapper: createWrapper(),
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId("room-room-a")).toHaveTextContent(
+ "1 active, 0 upcoming",
+ );
+ expect(screen.getByTestId("room-room-b")).toHaveTextContent(
+ "0 active, 1 upcoming",
+ );
+ });
+ });
+});
diff --git a/www/app/lib/meetingStatusBatcher.ts b/www/app/lib/meetingStatusBatcher.ts
index 4f2625ae..3bb2e29e 100644
--- a/www/app/lib/meetingStatusBatcher.ts
+++ b/www/app/lib/meetingStatusBatcher.ts
@@ -8,18 +8,24 @@ type MeetingStatusResult = {
upcoming_events: components["schemas"]["CalendarEventResponse"][];
};
-export const meetingStatusBatcher = create({
- fetcher: async (roomNames: string[]): Promise => {
- const unique = [...new Set(roomNames)];
- const { data } = await client.POST("/v1/rooms/meetings/bulk-status", {
- body: { room_names: unique },
- });
- return roomNames.map((name) => ({
- roomName: name,
- active_meetings: data?.[name]?.active_meetings ?? [],
- upcoming_events: data?.[name]?.upcoming_events ?? [],
- }));
- },
- resolver: keyResolver("roomName"),
- scheduler: windowScheduler(10),
-});
+const BATCH_WINDOW_MS = 10;
+
+export function createMeetingStatusBatcher(windowMs: number = BATCH_WINDOW_MS) {
+ return create({
+ fetcher: async (roomNames: string[]): Promise => {
+ const unique = [...new Set(roomNames)];
+ const { data } = await client.POST("/v1/rooms/meetings/bulk-status", {
+ body: { room_names: unique },
+ });
+ return roomNames.map((name) => ({
+ roomName: name,
+ active_meetings: data?.[name]?.active_meetings ?? [],
+ upcoming_events: data?.[name]?.upcoming_events ?? [],
+ }));
+ },
+ resolver: keyResolver("roomName"),
+ scheduler: windowScheduler(windowMs),
+ });
+}
+
+export const meetingStatusBatcher = createMeetingStatusBatcher();
diff --git a/www/jest.config.js b/www/jest.config.js
index d2f3247b..e526a641 100644
--- a/www/jest.config.js
+++ b/www/jest.config.js
@@ -1,8 +1,23 @@
module.exports = {
- preset: "ts-jest",
- testEnvironment: "node",
+ testEnvironment: "jest-environment-jsdom",
roots: ["/app"],
- testMatch: ["**/__tests__/**/*.test.ts"],
- collectCoverage: true,
- collectCoverageFrom: ["app/**/*.ts", "!app/**/*.d.ts"],
+ testMatch: ["**/__tests__/**/*.test.ts", "**/__tests__/**/*.test.tsx"],
+ collectCoverage: false,
+ transform: {
+ "^.+\\.[jt]sx?$": [
+ "ts-jest",
+ {
+ tsconfig: {
+ jsx: "react-jsx",
+ module: "esnext",
+ moduleResolution: "bundler",
+ esModuleInterop: true,
+ strict: false,
+ strictNullChecks: true,
+ downlevelIteration: true,
+ lib: ["dom", "dom.iterable", "esnext"],
+ },
+ },
+ ],
+ },
};
diff --git a/www/package.json b/www/package.json
index 6bc17a6a..59a370dc 100644
--- a/www/package.json
+++ b/www/package.json
@@ -62,9 +62,13 @@
"author": "Andreas ",
"license": "All Rights Reserved",
"devDependencies": {
+ "@testing-library/dom": "^10.4.1",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^16.3.2",
"@types/jest": "^30.0.0",
"@types/react": "18.2.20",
"jest": "^30.1.3",
+ "jest-environment-jsdom": "^30.2.0",
"openapi-typescript": "^7.9.1",
"prettier": "^3.0.0",
"ts-jest": "^29.4.1"
diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml
index 59d3c8c7..9897d79e 100644
--- a/www/pnpm-lock.yaml
+++ b/www/pnpm-lock.yaml
@@ -137,6 +137,15 @@ importers:
specifier: ^4.1.5
version: 4.1.5
devDependencies:
+ "@testing-library/dom":
+ specifier: ^10.4.1
+ version: 10.4.1
+ "@testing-library/jest-dom":
+ specifier: ^6.9.1
+ version: 6.9.1
+ "@testing-library/react":
+ specifier: ^16.3.2
+ version: 16.3.2(@testing-library/dom@10.4.1)(@types/react@18.2.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
"@types/jest":
specifier: ^30.0.0
version: 30.0.0
@@ -146,6 +155,9 @@ importers:
jest:
specifier: ^30.1.3
version: 30.1.3(@types/node@24.2.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2))
+ jest-environment-jsdom:
+ specifier: ^30.2.0
+ version: 30.2.0
openapi-typescript:
specifier: ^7.9.1
version: 7.9.1(typescript@5.9.2)
@@ -154,9 +166,15 @@ importers:
version: 3.6.2
ts-jest:
specifier: ^29.4.1
- version: 29.4.1(@babel/core@7.28.3)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.3))(jest-util@30.0.5)(jest@30.1.3(@types/node@24.2.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2)))(typescript@5.9.2)
+ version: 29.4.1(@babel/core@7.28.3)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.3))(jest-util@30.2.0)(jest@30.1.3(@types/node@24.2.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2)))(typescript@5.9.2)
packages:
+ "@adobe/css-tools@4.4.4":
+ resolution:
+ {
+ integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==,
+ }
+
"@alloc/quick-lru@5.2.0":
resolution:
{
@@ -180,6 +198,12 @@ packages:
react: ">=18.0.0"
react-dom: ">=18.0.0"
+ "@asamuzakjp/css-color@3.2.0":
+ resolution:
+ {
+ integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==,
+ }
+
"@babel/code-frame@7.27.1":
resolution:
{
@@ -496,6 +520,49 @@ packages:
}
engines: { node: ">=12" }
+ "@csstools/color-helpers@5.1.0":
+ resolution:
+ {
+ integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==,
+ }
+ engines: { node: ">=18" }
+
+ "@csstools/css-calc@2.1.4":
+ resolution:
+ {
+ integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==,
+ }
+ engines: { node: ">=18" }
+ peerDependencies:
+ "@csstools/css-parser-algorithms": ^3.0.5
+ "@csstools/css-tokenizer": ^3.0.4
+
+ "@csstools/css-color-parser@3.1.0":
+ resolution:
+ {
+ integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==,
+ }
+ engines: { node: ">=18" }
+ peerDependencies:
+ "@csstools/css-parser-algorithms": ^3.0.5
+ "@csstools/css-tokenizer": ^3.0.4
+
+ "@csstools/css-parser-algorithms@3.0.5":
+ resolution:
+ {
+ integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==,
+ }
+ engines: { node: ">=18" }
+ peerDependencies:
+ "@csstools/css-tokenizer": ^3.0.4
+
+ "@csstools/css-tokenizer@3.0.4":
+ resolution:
+ {
+ integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==,
+ }
+ engines: { node: ">=18" }
+
"@daily-co/daily-js@0.84.0":
resolution:
{
@@ -1047,6 +1114,19 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ "@jest/environment-jsdom-abstract@30.2.0":
+ resolution:
+ {
+ integrity: sha512-kazxw2L9IPuZpQ0mEt9lu9Z98SqR74xcagANmMBU16X0lS23yPc0+S6hGLUz8kVRlomZEs/5S/Zlpqwf5yu6OQ==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ peerDependencies:
+ canvas: ^3.0.0
+ jsdom: "*"
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
"@jest/environment@30.1.2":
resolution:
{
@@ -1054,6 +1134,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ "@jest/environment@30.2.0":
+ resolution:
+ {
+ integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
"@jest/expect-utils@30.1.2":
resolution:
{
@@ -1075,6 +1162,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ "@jest/fake-timers@30.2.0":
+ resolution:
+ {
+ integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
"@jest/get-type@30.1.0":
resolution:
{
@@ -1171,6 +1265,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ "@jest/types@30.2.0":
+ resolution:
+ {
+ integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
"@jridgewell/gen-mapping@0.3.13":
resolution:
{
@@ -2646,6 +2747,38 @@ packages:
peerDependencies:
react: ^18 || ^19
+ "@testing-library/dom@10.4.1":
+ resolution:
+ {
+ integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==,
+ }
+ engines: { node: ">=18" }
+
+ "@testing-library/jest-dom@6.9.1":
+ resolution:
+ {
+ integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==,
+ }
+ engines: { node: ">=14", npm: ">=6", yarn: ">=1" }
+
+ "@testing-library/react@16.3.2":
+ resolution:
+ {
+ integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==,
+ }
+ engines: { node: ">=18" }
+ peerDependencies:
+ "@testing-library/dom": ^10.0.0
+ "@types/react": ^18.0.0 || ^19.0.0
+ "@types/react-dom": ^18.0.0 || ^19.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ "@types/react-dom":
+ optional: true
+
"@tsconfig/node10@1.0.12":
resolution:
{
@@ -2676,6 +2809,12 @@ packages:
integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==,
}
+ "@types/aria-query@5.0.4":
+ resolution:
+ {
+ integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==,
+ }
+
"@types/babel__core@7.20.5":
resolution:
{
@@ -2779,6 +2918,12 @@ packages:
integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==,
}
+ "@types/jsdom@21.1.7":
+ resolution:
+ {
+ integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==,
+ }
+
"@types/json-schema@7.0.15":
resolution:
{
@@ -2881,6 +3026,12 @@ packages:
integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==,
}
+ "@types/tough-cookie@4.0.5":
+ resolution:
+ {
+ integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==,
+ }
+
"@types/ua-parser-js@0.7.39":
resolution:
{
@@ -3925,6 +4076,12 @@ packages:
}
engines: { node: ">=10" }
+ aria-query@5.3.0:
+ resolution:
+ {
+ integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==,
+ }
+
aria-query@5.3.2:
resolution:
{
@@ -4508,6 +4665,12 @@ packages:
}
engines: { node: ">= 8" }
+ css.escape@1.5.1:
+ resolution:
+ {
+ integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==,
+ }
+
cssesc@3.0.0:
resolution:
{
@@ -4516,6 +4679,13 @@ packages:
engines: { node: ">=4" }
hasBin: true
+ cssstyle@4.6.0:
+ resolution:
+ {
+ integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==,
+ }
+ engines: { node: ">=18" }
+
csstype@3.1.3:
resolution:
{
@@ -4528,6 +4698,13 @@ packages:
integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==,
}
+ data-urls@5.0.0:
+ resolution:
+ {
+ integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==,
+ }
+ engines: { node: ">=18" }
+
data-view-buffer@1.0.2:
resolution:
{
@@ -4584,6 +4761,12 @@ packages:
supports-color:
optional: true
+ decimal.js@10.6.0:
+ resolution:
+ {
+ integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==,
+ }
+
decode-named-character-reference@1.2.0:
resolution:
{
@@ -4715,6 +4898,18 @@ packages:
}
engines: { node: ">=0.10.0" }
+ dom-accessibility-api@0.5.16:
+ resolution:
+ {
+ integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==,
+ }
+
+ dom-accessibility-api@0.6.3:
+ resolution:
+ {
+ integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==,
+ }
+
domconstants@0.1.2:
resolution:
{
@@ -4798,6 +4993,13 @@ packages:
}
engines: { node: ">=10.13.0" }
+ entities@6.0.1:
+ resolution:
+ {
+ integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==,
+ }
+ engines: { node: ">=0.12" }
+
err-code@3.0.1:
resolution:
{
@@ -5568,6 +5770,13 @@ packages:
integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==,
}
+ html-encoding-sniffer@4.0.0:
+ resolution:
+ {
+ integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==,
+ }
+ engines: { node: ">=18" }
+
html-escaper@2.0.2:
resolution:
{
@@ -5580,6 +5789,13 @@ packages:
integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==,
}
+ http-proxy-agent@7.0.2:
+ resolution:
+ {
+ integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==,
+ }
+ engines: { node: ">= 14" }
+
https-proxy-agent@5.0.1:
resolution:
{
@@ -5607,6 +5823,13 @@ packages:
integrity: sha512-IvLy8MzHTSJ0fDpSzrb8rcdnla6yROEmNBSxInEMyIFu2DQkbmpadTf6B4fHvnytN6iHL2gGwpe5/jHL3wMi+A==,
}
+ iconv-lite@0.6.3:
+ resolution:
+ {
+ integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==,
+ }
+ engines: { node: ">=0.10.0" }
+
ieee754@1.2.1:
resolution:
{
@@ -5667,6 +5890,13 @@ packages:
}
engines: { node: ">=0.8.19" }
+ indent-string@4.0.0:
+ resolution:
+ {
+ integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==,
+ }
+ engines: { node: ">=8" }
+
index-to-position@1.1.0:
resolution:
{
@@ -5903,6 +6133,12 @@ packages:
}
engines: { node: ">=12" }
+ is-potential-custom-element-name@1.0.1:
+ resolution:
+ {
+ integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==,
+ }
+
is-reference@1.2.1:
resolution:
{
@@ -6111,6 +6347,18 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ jest-environment-jsdom@30.2.0:
+ resolution:
+ {
+ integrity: sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
jest-environment-node@30.1.2:
resolution:
{
@@ -6146,6 +6394,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ jest-message-util@30.2.0:
+ resolution:
+ {
+ integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
jest-mock@30.0.5:
resolution:
{
@@ -6153,6 +6408,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ jest-mock@30.2.0:
+ resolution:
+ {
+ integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
jest-pnp-resolver@1.2.3:
resolution:
{
@@ -6221,6 +6483,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ jest-util@30.2.0:
+ resolution:
+ {
+ integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
jest-validate@30.1.0:
resolution:
{
@@ -6315,6 +6584,18 @@ packages:
integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==,
}
+ jsdom@26.1.0:
+ resolution:
+ {
+ integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==,
+ }
+ engines: { node: ">=18" }
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
jsesc@3.1.0:
resolution:
{
@@ -6512,6 +6793,13 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ lz-string@1.5.0:
+ resolution:
+ {
+ integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==,
+ }
+ hasBin: true
+
magic-string@0.30.19:
resolution:
{
@@ -6773,6 +7061,13 @@ packages:
}
engines: { node: ">=6" }
+ min-indent@1.0.1:
+ resolution:
+ {
+ integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==,
+ }
+ engines: { node: ">=4" }
+
minimatch@3.1.2:
resolution:
{
@@ -7000,6 +7295,12 @@ packages:
react-router-dom:
optional: true
+ nwsapi@2.2.23:
+ resolution:
+ {
+ integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==,
+ }
+
oauth@0.9.15:
resolution:
{
@@ -7214,6 +7515,12 @@ packages:
}
engines: { node: ">=18" }
+ parse5@7.3.0:
+ resolution:
+ {
+ integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==,
+ }
+
path-exists@4.0.0:
resolution:
{
@@ -7462,6 +7769,13 @@ packages:
engines: { node: ">=14" }
hasBin: true
+ pretty-format@27.5.1:
+ resolution:
+ {
+ integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==,
+ }
+ engines: { node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0 }
+
pretty-format@3.8.0:
resolution:
{
@@ -7475,6 +7789,13 @@ packages:
}
engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+ pretty-format@30.2.0:
+ resolution:
+ {
+ integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==,
+ }
+ engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 }
+
progress@2.0.3:
resolution:
{
@@ -7574,6 +7895,12 @@ packages:
integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==,
}
+ react-is@17.0.2:
+ resolution:
+ {
+ integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==,
+ }
+
react-is@18.3.1:
resolution:
{
@@ -7688,6 +8015,13 @@ packages:
}
engines: { node: ">= 14.18.0" }
+ redent@3.0.0:
+ resolution:
+ {
+ integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==,
+ }
+ engines: { node: ">=8" }
+
redis-errors@1.2.0:
resolution:
{
@@ -7852,6 +8186,12 @@ packages:
engines: { node: ">=18.0.0", npm: ">=8.0.0" }
hasBin: true
+ rrweb-cssom@0.8.0:
+ resolution:
+ {
+ integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==,
+ }
+
rtcstats@https://codeload.github.com/whereby/rtcstats/tar.gz/63bcb6420d76d34161b39e494524ae73aa6dd70d:
resolution:
{
@@ -7899,6 +8239,12 @@ packages:
}
engines: { node: ">= 0.4" }
+ safer-buffer@2.1.2:
+ resolution:
+ {
+ integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==,
+ }
+
sass@1.90.0:
resolution:
{
@@ -7907,6 +8253,13 @@ packages:
engines: { node: ">=14.0.0" }
hasBin: true
+ saxes@6.0.0:
+ resolution:
+ {
+ integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==,
+ }
+ engines: { node: ">=v12.22.7" }
+
scheduler@0.23.2:
resolution:
{
@@ -8271,6 +8624,13 @@ packages:
}
engines: { node: ">=6" }
+ strip-indent@3.0.0:
+ resolution:
+ {
+ integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==,
+ }
+ engines: { node: ">=8" }
+
strip-json-comments@3.1.1:
resolution:
{
@@ -8355,6 +8715,12 @@ packages:
}
engines: { node: ">= 0.4" }
+ symbol-tree@3.2.4:
+ resolution:
+ {
+ integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==,
+ }
+
synckit@0.11.11:
resolution:
{
@@ -8431,6 +8797,19 @@ packages:
}
engines: { node: ">=12.0.0" }
+ tldts-core@6.1.86:
+ resolution:
+ {
+ integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==,
+ }
+
+ tldts@6.1.86:
+ resolution:
+ {
+ integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==,
+ }
+ hasBin: true
+
tmpl@1.0.5:
resolution:
{
@@ -8444,12 +8823,26 @@ packages:
}
engines: { node: ">=8.0" }
+ tough-cookie@5.1.2:
+ resolution:
+ {
+ integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==,
+ }
+ engines: { node: ">=16" }
+
tr46@0.0.3:
resolution:
{
integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==,
}
+ tr46@5.1.1:
+ resolution:
+ {
+ integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==,
+ }
+ engines: { node: ">=18" }
+
trim-lines@3.0.1:
resolution:
{
@@ -8849,6 +9242,13 @@ packages:
integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==,
}
+ w3c-xmlserializer@5.0.0:
+ resolution:
+ {
+ integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==,
+ }
+ engines: { node: ">=18" }
+
walker@1.0.8:
resolution:
{
@@ -8874,6 +9274,13 @@ packages:
integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==,
}
+ webidl-conversions@7.0.0:
+ resolution:
+ {
+ integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==,
+ }
+ engines: { node: ">=12" }
+
webpack-sources@3.3.3:
resolution:
{
@@ -8907,6 +9314,28 @@ packages:
}
engines: { node: ">=6.0.0", npm: ">=3.10.0" }
+ whatwg-encoding@3.1.1:
+ resolution:
+ {
+ integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==,
+ }
+ engines: { node: ">=18" }
+ deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
+
+ whatwg-mimetype@4.0.0:
+ resolution:
+ {
+ integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==,
+ }
+ engines: { node: ">=18" }
+
+ whatwg-url@14.2.0:
+ resolution:
+ {
+ integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==,
+ }
+ engines: { node: ">=18" }
+
whatwg-url@5.0.0:
resolution:
{
@@ -9004,6 +9433,34 @@ packages:
utf-8-validate:
optional: true
+ ws@8.19.0:
+ resolution:
+ {
+ integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==,
+ }
+ engines: { node: ">=10.0.0" }
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ">=5.0.2"
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xml-name-validator@5.0.0:
+ resolution:
+ {
+ integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==,
+ }
+ engines: { node: ">=18" }
+
+ xmlchars@2.2.0:
+ resolution:
+ {
+ integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==,
+ }
+
xmlhttprequest-ssl@2.0.0:
resolution:
{
@@ -9099,6 +9556,8 @@ packages:
}
snapshots:
+ "@adobe/css-tools@4.4.4": {}
+
"@alloc/quick-lru@5.2.0": {}
"@ampproject/remapping@2.3.0":
@@ -9170,6 +9629,14 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
+ "@asamuzakjp/css-color@3.2.0":
+ dependencies:
+ "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-tokenizer": 3.0.4
+ lru-cache: 10.4.3
+
"@babel/code-frame@7.27.1":
dependencies:
"@babel/helper-validator-identifier": 7.27.1
@@ -9404,6 +9871,26 @@ snapshots:
"@jridgewell/trace-mapping": 0.3.9
optional: true
+ "@csstools/color-helpers@5.1.0": {}
+
+ "@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)":
+ dependencies:
+ "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-tokenizer": 3.0.4
+
+ "@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)":
+ dependencies:
+ "@csstools/color-helpers": 5.1.0
+ "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4)
+ "@csstools/css-tokenizer": 3.0.4
+
+ "@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)":
+ dependencies:
+ "@csstools/css-tokenizer": 3.0.4
+
+ "@csstools/css-tokenizer@3.0.4": {}
+
"@daily-co/daily-js@0.84.0":
dependencies:
"@babel/runtime": 7.28.2
@@ -9769,13 +10256,31 @@ snapshots:
"@jest/diff-sequences@30.0.1": {}
+ "@jest/environment-jsdom-abstract@30.2.0(jsdom@26.1.0)":
+ dependencies:
+ "@jest/environment": 30.2.0
+ "@jest/fake-timers": 30.2.0
+ "@jest/types": 30.2.0
+ "@types/jsdom": 21.1.7
+ "@types/node": 25.0.2
+ jest-mock: 30.2.0
+ jest-util: 30.2.0
+ jsdom: 26.1.0
+
"@jest/environment@30.1.2":
dependencies:
"@jest/fake-timers": 30.1.2
"@jest/types": 30.0.5
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
jest-mock: 30.0.5
+ "@jest/environment@30.2.0":
+ dependencies:
+ "@jest/fake-timers": 30.2.0
+ "@jest/types": 30.2.0
+ "@types/node": 25.0.2
+ jest-mock: 30.2.0
+
"@jest/expect-utils@30.1.2":
dependencies:
"@jest/get-type": 30.1.0
@@ -9791,11 +10296,20 @@ snapshots:
dependencies:
"@jest/types": 30.0.5
"@sinonjs/fake-timers": 13.0.5
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
jest-message-util: 30.1.0
jest-mock: 30.0.5
jest-util: 30.0.5
+ "@jest/fake-timers@30.2.0":
+ dependencies:
+ "@jest/types": 30.2.0
+ "@sinonjs/fake-timers": 13.0.5
+ "@types/node": 25.0.2
+ jest-message-util: 30.2.0
+ jest-mock: 30.2.0
+ jest-util: 30.2.0
+
"@jest/get-type@30.1.0": {}
"@jest/globals@30.1.2":
@@ -9914,6 +10428,16 @@ snapshots:
"@types/yargs": 17.0.33
chalk: 4.1.2
+ "@jest/types@30.2.0":
+ dependencies:
+ "@jest/pattern": 30.0.1
+ "@jest/schemas": 30.0.5
+ "@types/istanbul-lib-coverage": 2.0.6
+ "@types/istanbul-reports": 3.0.4
+ "@types/node": 25.0.2
+ "@types/yargs": 17.0.33
+ chalk: 4.1.2
+
"@jridgewell/gen-mapping@0.3.13":
dependencies:
"@jridgewell/sourcemap-codec": 1.5.5
@@ -10903,6 +11427,35 @@ snapshots:
"@tanstack/query-core": 5.85.9
react: 18.3.1
+ "@testing-library/dom@10.4.1":
+ dependencies:
+ "@babel/code-frame": 7.27.1
+ "@babel/runtime": 7.28.2
+ "@types/aria-query": 5.0.4
+ aria-query: 5.3.0
+ dom-accessibility-api: 0.5.16
+ lz-string: 1.5.0
+ picocolors: 1.1.1
+ pretty-format: 27.5.1
+
+ "@testing-library/jest-dom@6.9.1":
+ dependencies:
+ "@adobe/css-tools": 4.4.4
+ aria-query: 5.3.2
+ css.escape: 1.5.1
+ dom-accessibility-api: 0.6.3
+ picocolors: 1.1.1
+ redent: 3.0.0
+
+ "@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react@18.2.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)":
+ dependencies:
+ "@babel/runtime": 7.28.2
+ "@testing-library/dom": 10.4.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ "@types/react": 18.2.20
+
"@tsconfig/node10@1.0.12":
optional: true
@@ -10920,6 +11473,8 @@ snapshots:
tslib: 2.8.1
optional: true
+ "@types/aria-query@5.0.4": {}
+
"@types/babel__core@7.20.5":
dependencies:
"@babel/parser": 7.28.0
@@ -10943,7 +11498,7 @@ snapshots:
"@types/connect@3.4.38":
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
"@types/debug@4.1.12":
dependencies:
@@ -10992,6 +11547,12 @@ snapshots:
expect: 30.1.2
pretty-format: 30.0.5
+ "@types/jsdom@21.1.7":
+ dependencies:
+ "@types/node": 25.0.2
+ "@types/tough-cookie": 4.0.5
+ parse5: 7.3.0
+
"@types/json-schema@7.0.15": {}
"@types/json5@0.0.29": {}
@@ -11004,11 +11565,11 @@ snapshots:
"@types/mysql@2.15.27":
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
"@types/node-fetch@2.6.13":
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
form-data: 4.0.4
"@types/node@24.2.1":
@@ -11027,7 +11588,7 @@ snapshots:
"@types/pg@8.15.4":
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
pg-protocol: 1.10.3
pg-types: 2.2.0
@@ -11047,7 +11608,9 @@ snapshots:
"@types/tedious@4.0.14":
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
+
+ "@types/tough-cookie@4.0.5": {}
"@types/ua-parser-js@0.7.39": {}
@@ -11961,6 +12524,10 @@ snapshots:
dependencies:
tslib: 2.8.1
+ aria-query@5.3.0:
+ dependencies:
+ dequal: 2.0.3
+
aria-query@5.3.2: {}
array-buffer-byte-length@1.0.2:
@@ -12326,12 +12893,24 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ css.escape@1.5.1: {}
+
cssesc@3.0.0: {}
+ cssstyle@4.6.0:
+ dependencies:
+ "@asamuzakjp/css-color": 3.2.0
+ rrweb-cssom: 0.8.0
+
csstype@3.1.3: {}
damerau-levenshtein@1.0.8: {}
+ data-urls@5.0.0:
+ dependencies:
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+
data-view-buffer@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -12370,6 +12949,8 @@ snapshots:
optionalDependencies:
supports-color: 9.4.0
+ decimal.js@10.6.0: {}
+
decode-named-character-reference@1.2.0:
dependencies:
character-entities: 2.0.2
@@ -12427,6 +13008,10 @@ snapshots:
dependencies:
esutils: 2.0.3
+ dom-accessibility-api@0.5.16: {}
+
+ dom-accessibility-api@0.6.3: {}
+
domconstants@0.1.2: {}
domsanitizer@0.2.3:
@@ -12480,6 +13065,8 @@ snapshots:
graceful-fs: 4.2.11
tapable: 2.3.0
+ entities@6.0.1: {}
+
err-code@3.0.1: {}
error-ex@1.3.2:
@@ -13109,10 +13696,21 @@ snapshots:
dependencies:
react-is: 16.13.1
+ html-encoding-sniffer@4.0.0:
+ dependencies:
+ whatwg-encoding: 3.1.1
+
html-escaper@2.0.2: {}
html-url-attributes@3.0.1: {}
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.1(supports-color@9.4.0)
+ transitivePeerDependencies:
+ - supports-color
+
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
@@ -13120,6 +13718,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.1(supports-color@9.4.0)
+ transitivePeerDependencies:
+ - supports-color
+
https-proxy-agent@7.0.6(supports-color@10.2.0):
dependencies:
agent-base: 7.1.4
@@ -13131,6 +13736,10 @@ snapshots:
hyperhtml-style@0.1.3: {}
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
ieee754@1.2.1: {}
ignore@5.3.2: {}
@@ -13160,6 +13769,8 @@ snapshots:
imurmurhash@0.1.4: {}
+ indent-string@4.0.0: {}
+
index-to-position@1.1.0: {}
inflight@1.0.6:
@@ -13297,6 +13908,8 @@ snapshots:
is-plain-obj@4.1.0: {}
+ is-potential-custom-element-name@1.0.1: {}
+
is-reference@1.2.1:
dependencies:
"@types/estree": 1.0.8
@@ -13406,7 +14019,7 @@ snapshots:
"@jest/expect": 30.1.2
"@jest/test-result": 30.1.3
"@jest/types": 30.0.5
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
chalk: 4.1.2
co: 4.6.0
dedent: 1.7.0(babel-plugin-macros@3.1.0)
@@ -13497,12 +14110,24 @@ snapshots:
jest-util: 30.0.5
pretty-format: 30.0.5
+ jest-environment-jsdom@30.2.0:
+ dependencies:
+ "@jest/environment": 30.2.0
+ "@jest/environment-jsdom-abstract": 30.2.0(jsdom@26.1.0)
+ "@types/jsdom": 21.1.7
+ "@types/node": 25.0.2
+ jsdom: 26.1.0
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
jest-environment-node@30.1.2:
dependencies:
"@jest/environment": 30.1.2
"@jest/fake-timers": 30.1.2
"@jest/types": 30.0.5
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
jest-mock: 30.0.5
jest-util: 30.0.5
jest-validate: 30.1.0
@@ -13546,12 +14171,30 @@ snapshots:
slash: 3.0.0
stack-utils: 2.0.6
+ jest-message-util@30.2.0:
+ dependencies:
+ "@babel/code-frame": 7.27.1
+ "@jest/types": 30.2.0
+ "@types/stack-utils": 2.0.3
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ micromatch: 4.0.8
+ pretty-format: 30.2.0
+ slash: 3.0.0
+ stack-utils: 2.0.6
+
jest-mock@30.0.5:
dependencies:
"@jest/types": 30.0.5
"@types/node": 24.2.1
jest-util: 30.0.5
+ jest-mock@30.2.0:
+ dependencies:
+ "@jest/types": 30.2.0
+ "@types/node": 25.0.2
+ jest-util: 30.2.0
+
jest-pnp-resolver@1.2.3(jest-resolve@30.1.3):
optionalDependencies:
jest-resolve: 30.1.3
@@ -13674,6 +14317,15 @@ snapshots:
graceful-fs: 4.2.11
picomatch: 4.0.3
+ jest-util@30.2.0:
+ dependencies:
+ "@jest/types": 30.2.0
+ "@types/node": 25.0.2
+ chalk: 4.1.2
+ ci-info: 4.3.0
+ graceful-fs: 4.2.11
+ picomatch: 4.0.3
+
jest-validate@30.1.0:
dependencies:
"@jest/get-type": 30.1.0
@@ -13709,7 +14361,7 @@ snapshots:
jest-worker@30.1.0:
dependencies:
- "@types/node": 24.2.1
+ "@types/node": 25.0.2
"@ungap/structured-clone": 1.3.0
jest-util: 30.0.5
merge-stream: 2.0.0
@@ -13747,6 +14399,33 @@ snapshots:
jsbn@1.1.0: {}
+ jsdom@26.1.0:
+ dependencies:
+ cssstyle: 4.6.0
+ data-urls: 5.0.0
+ decimal.js: 10.6.0
+ html-encoding-sniffer: 4.0.0
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ is-potential-custom-element-name: 1.0.1
+ nwsapi: 2.2.23
+ parse5: 7.3.0
+ rrweb-cssom: 0.8.0
+ saxes: 6.0.0
+ symbol-tree: 3.2.4
+ tough-cookie: 5.1.2
+ w3c-xmlserializer: 5.0.0
+ webidl-conversions: 7.0.0
+ whatwg-encoding: 3.1.1
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+ ws: 8.19.0
+ xml-name-validator: 5.0.0
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
jsesc@3.1.0: {}
json-buffer@3.0.1: {}
@@ -13843,6 +14522,8 @@ snapshots:
dependencies:
react: 18.3.1
+ lz-string@1.5.0: {}
+
magic-string@0.30.19:
dependencies:
"@jridgewell/sourcemap-codec": 1.5.5
@@ -14118,6 +14799,8 @@ snapshots:
mimic-fn@2.1.0: {}
+ min-indent@1.0.1: {}
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -14233,6 +14916,8 @@ snapshots:
optionalDependencies:
next: 15.5.9(@babel/core@7.28.3)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.90.0)
+ nwsapi@2.2.23: {}
+
oauth@0.9.15: {}
object-assign@4.1.1: {}
@@ -14382,6 +15067,10 @@ snapshots:
index-to-position: 1.1.0
type-fest: 4.41.0
+ parse5@7.3.0:
+ dependencies:
+ entities: 6.0.1
+
path-exists@4.0.0: {}
path-is-absolute@1.0.1: {}
@@ -14494,6 +15183,12 @@ snapshots:
prettier@3.6.2: {}
+ pretty-format@27.5.1:
+ dependencies:
+ ansi-regex: 5.0.1
+ ansi-styles: 5.2.0
+ react-is: 17.0.2
+
pretty-format@3.8.0: {}
pretty-format@30.0.5:
@@ -14502,6 +15197,12 @@ snapshots:
ansi-styles: 5.2.0
react-is: 18.3.1
+ pretty-format@30.2.0:
+ dependencies:
+ "@jest/schemas": 30.0.5
+ ansi-styles: 5.2.0
+ react-is: 18.3.1
+
progress@2.0.3: {}
prop-types@15.8.1:
@@ -14550,6 +15251,8 @@ snapshots:
react-is@16.13.1: {}
+ react-is@17.0.2: {}
+
react-is@18.3.1: {}
react-markdown@9.1.0(@types/react@18.2.20)(react@18.3.1):
@@ -14634,6 +15337,11 @@ snapshots:
readdirp@4.1.2: {}
+ redent@3.0.0:
+ dependencies:
+ indent-string: 4.0.0
+ strip-indent: 3.0.0
+
redis-errors@1.2.0: {}
redis-parser@3.0.0:
@@ -14764,6 +15472,8 @@ snapshots:
"@rollup/rollup-win32-x64-msvc": 4.50.1
fsevents: 2.3.3
+ rrweb-cssom@0.8.0: {}
+
rtcstats@https://codeload.github.com/whereby/rtcstats/tar.gz/63bcb6420d76d34161b39e494524ae73aa6dd70d:
{}
@@ -14794,6 +15504,8 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
+ safer-buffer@2.1.2: {}
+
sass@1.90.0:
dependencies:
chokidar: 4.0.3
@@ -14802,6 +15514,10 @@ snapshots:
optionalDependencies:
"@parcel/watcher": 2.5.1
+ saxes@6.0.0:
+ dependencies:
+ xmlchars: 2.2.0
+
scheduler@0.23.2:
dependencies:
loose-envify: 1.4.0
@@ -15083,6 +15799,10 @@ snapshots:
strip-final-newline@2.0.0: {}
+ strip-indent@3.0.0:
+ dependencies:
+ min-indent: 1.0.1
+
strip-json-comments@3.1.1: {}
style-to-js@1.1.17:
@@ -15127,6 +15847,8 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ symbol-tree@3.2.4: {}
+
synckit@0.11.11:
dependencies:
"@pkgr/core": 0.2.9
@@ -15195,14 +15917,28 @@ snapshots:
fdir: 6.4.6(picomatch@4.0.3)
picomatch: 4.0.3
+ tldts-core@6.1.86: {}
+
+ tldts@6.1.86:
+ dependencies:
+ tldts-core: 6.1.86
+
tmpl@1.0.5: {}
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
+ tough-cookie@5.1.2:
+ dependencies:
+ tldts: 6.1.86
+
tr46@0.0.3: {}
+ tr46@5.1.1:
+ dependencies:
+ punycode: 2.3.1
+
trim-lines@3.0.1: {}
trough@2.2.0: {}
@@ -15213,7 +15949,7 @@ snapshots:
ts-interface-checker@0.1.13: {}
- ts-jest@29.4.1(@babel/core@7.28.3)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.3))(jest-util@30.0.5)(jest@30.1.3(@types/node@24.2.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2)))(typescript@5.9.2):
+ ts-jest@29.4.1(@babel/core@7.28.3)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.3))(jest-util@30.2.0)(jest@30.1.3(@types/node@24.2.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2)))(typescript@5.9.2):
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
@@ -15229,9 +15965,9 @@ snapshots:
optionalDependencies:
"@babel/core": 7.28.3
"@jest/transform": 30.1.2
- "@jest/types": 30.0.5
+ "@jest/types": 30.2.0
babel-jest: 30.1.2(@babel/core@7.28.3)
- jest-util: 30.0.5
+ jest-util: 30.2.0
ts-node@10.9.1(@types/node@24.2.1)(typescript@5.9.2):
dependencies:
@@ -15474,6 +16210,10 @@ snapshots:
"@types/unist": 3.0.3
vfile-message: 4.0.3
+ w3c-xmlserializer@5.0.0:
+ dependencies:
+ xml-name-validator: 5.0.0
+
walker@1.0.8:
dependencies:
makeerror: 1.0.12
@@ -15487,6 +16227,8 @@ snapshots:
webidl-conversions@3.0.1: {}
+ webidl-conversions@7.0.0: {}
+
webpack-sources@3.3.3: {}
webpack-virtual-modules@0.5.0: {}
@@ -15527,6 +16269,17 @@ snapshots:
dependencies:
sdp: 3.2.1
+ whatwg-encoding@3.1.1:
+ dependencies:
+ iconv-lite: 0.6.3
+
+ whatwg-mimetype@4.0.0: {}
+
+ whatwg-url@14.2.0:
+ dependencies:
+ tr46: 5.1.1
+ webidl-conversions: 7.0.0
+
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
@@ -15602,6 +16355,12 @@ snapshots:
ws@8.17.1: {}
+ ws@8.19.0: {}
+
+ xml-name-validator@5.0.0: {}
+
+ xmlchars@2.2.0: {}
+
xmlhttprequest-ssl@2.0.0: {}
xtend@4.0.2: {}