From 091346dfe80ce93e72b53464d2d13d597c861037 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 6 May 2026 21:10:51 -0400 Subject: [PATCH] chore: Migrate to vitest (#12272) * wip * Remove obsolete snapshots * simplify * chore(test): Convert mocks to TypeScript and tighten fetch mock types Co-Authored-By: Claude Opus 4.7 * Remove unneccessary patches * Migrate to msw instead of custom fetch mock * Address PR review comments - Split chained vi.useFakeTimers().setSystemTime() into separate calls. - Switch test setup to dynamic imports so EventEmitter.defaultMaxListeners assignment runs before module init (static imports were hoisted above it). - Drop redundant NODE_ENV guard in monkeyPatchSequelizeErrorsForJest; its sole caller already gates on env.isTest. Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: Claude Opus 4.7 --- .github/workflows/ci.yml | 21 +- .jestconfig.json | 63 - app/test/setup.ts | 6 +- app/utils/__mocks__/ApiClient.ts | 4 +- package.json | 24 +- plugins/email/server/auth/email.test.ts | 18 +- .../server/utils/NotionConverter.test.ts | 15 +- .../NotionConverter.test.ts.snap | 6 +- plugins/oidc/server/oidcDiscovery.test.ts | 127 +- .../server/PostgresSearchProvider.test.ts | 2 +- plugins/slack/server/api/hooks.test.ts | 12 +- plugins/storage/server/api/files.test.ts | 2 +- .../processors/WebhookProcessor.test.ts | 10 +- .../server/tasks/DeliverWebhookTask.test.ts | 83 +- server/__mocks__/fetch-with-proxy.ts | 9 - server/__mocks__/franc.js | 10 - server/__mocks__/franc.ts | 9 + .../__mocks__/{iso-639-3.js => iso-639-3.ts} | 7 +- server/__mocks__/request-filtering-agent.ts | 25 + .../ConnectionLimitExtension.test.ts | 7 +- server/commands/documentImporter.test.ts | 2 +- .../commands/documentPermanentDeleter.test.ts | 11 +- server/commands/documentUpdater.test.ts | 4 +- server/emails/templates/index.ts | 28 +- server/middlewares/authentication.test.ts | 60 +- server/middlewares/rateLimiter.test.ts | 110 +- server/middlewares/timeout.test.ts | 12 +- server/models/Collection.test.ts | 4 +- server/models/Document.test.ts | 2 +- server/models/DocumentInsight.ts | 14 +- server/models/Team.test.ts | 19 +- server/models/User.test.ts | 5 +- server/models/helpers/DocumentHelper.test.ts | 6 +- .../models/helpers/ProseMirrorHelper.test.ts | 2 +- server/models/helpers/ProsemirrorHelper.tsx | 63 +- server/models/helpers/TextHelper.test.ts | 2 +- server/onerror.test.ts | 19 +- .../__snapshots__/user.test.ts.snap | 2 +- .../processors/SearchIndexProcessor.test.ts | 4 +- server/queues/processors/index.ts | 26 +- ...DocumentPublishedNotificationsTask.test.ts | 12 +- ...entionedInCommentNotificationsTask.test.ts | 14 +- server/queues/tasks/ImportJSONTask.test.ts | 2 +- .../tasks/ImportMarkdownZipTask.test.ts | 8 +- .../queues/tasks/InviteReminderTask.test.ts | 2 +- .../RevisionCreatedNotificationsTask.test.ts | 28 +- .../tasks/RollupDocumentInsightsTask.test.ts | 6 +- ...ShareSubscriptionNotificationsTask.test.ts | 24 +- ...UpdateDocumentsPopularityScoreTask.test.ts | 18 +- server/queues/tasks/index.ts | 26 +- .../api/attachments/attachments.test.ts | 2 +- server/routes/api/auth/auth.test.ts | 2 +- .../__snapshots__/collections.test.ts.snap | 34 +- .../__snapshots__/comments.test.ts.snap | 18 +- .../__snapshots__/documents.test.ts.snap | 26 +- server/routes/api/documents/documents.test.ts | 12 +- .../events/__snapshots__/events.test.ts.snap | 4 +- .../api/fileOperations/fileOperations.test.ts | 2 +- .../groups/__snapshots__/groups.test.ts.snap | 22 +- .../oauthAuthentications.test.ts.snap | 6 +- .../__snapshots__/oauthClients.test.ts.snap | 14 +- .../__snapshots__/reactions.test.ts.snap | 4 +- .../shares/__snapshots__/shares.test.ts.snap | 10 +- server/routes/api/urls/urls.test.ts | 43 +- .../users/__snapshots__/users.test.ts.snap | 24 +- server/routes/api/users/users.test.ts | 6 +- .../views/__snapshots__/views.test.ts.snap | 6 +- server/storage/database.ts | 4 - server/storage/files/__mocks__/index.ts | 12 +- server/test/globalTeardown.js | 7 - server/test/globalTeardown.ts | 6 + server/test/msw.ts | 11 + server/test/setup.ts | 69 +- server/test/setupMocks.js | 11 - server/test/setupMocks.ts | 56 + server/test/support.ts | 22 + server/utils/__mocks__/MutexLock.ts | 19 +- server/utils/embeds.test.ts | 105 +- server/utils/fs.ts | 35 + server/utils/getInstallationInfo.test.ts | 33 +- server/utils/lazyRegistry.ts | 40 + server/utils/oauth.test.ts | 18 +- server/utils/parseAttachmentIds.test.ts | 1 - server/utils/url.test.ts | 5 +- server/utils/validators.test.ts | 1 - shared/test/setup.ts | 4 +- shared/utils/TextHelper.test.ts | 6 +- shared/utils/files.test.ts | 2 +- vitest.config.ts | 112 + vitest.d.ts | 1 + yarn.lock | 3449 ++++++----------- 91 files changed, 2298 insertions(+), 2961 deletions(-) delete mode 100644 .jestconfig.json delete mode 100644 server/__mocks__/fetch-with-proxy.ts delete mode 100644 server/__mocks__/franc.js create mode 100644 server/__mocks__/franc.ts rename server/__mocks__/{iso-639-3.js => iso-639-3.ts} (52%) create mode 100644 server/__mocks__/request-filtering-agent.ts delete mode 100644 server/test/globalTeardown.js create mode 100644 server/test/globalTeardown.ts create mode 100644 server/test/msw.ts delete mode 100644 server/test/setupMocks.js create mode 100644 server/test/setupMocks.ts create mode 100644 server/utils/lazyRegistry.ts create mode 100644 vitest.config.ts create mode 100644 vitest.d.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee77a3af35..7d4d299439 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,7 @@ jobs: config: - '.github/**' - 'vite.config.ts' + - 'vitest.config.ts' server: - 'server/**' - 'shared/**' @@ -82,15 +83,7 @@ jobs: steps: - uses: actions/checkout@v5 - uses: ./.github/actions/install - - name: Restore Jest transform cache - uses: actions/cache@v4 - with: - path: /tmp/jest_runner - key: jest-${{ matrix.test-group }}-${{ hashFiles('.babelrc', '.jestconfig.json', 'yarn.lock', 'app/**/*.ts', 'app/**/*.tsx', 'shared/**/*.ts', 'shared/**/*.tsx') }} - restore-keys: | - jest-${{ matrix.test-group }}-${{ hashFiles('.babelrc', '.jestconfig.json', 'yarn.lock') }}- - jest-${{ matrix.test-group }}- - - run: yarn test:${{ matrix.test-group }} --cacheDirectory=/tmp/jest_runner + - run: yarn test:${{ matrix.test-group }} test-server: needs: changes @@ -118,17 +111,9 @@ jobs: steps: - uses: actions/checkout@v5 - uses: ./.github/actions/install - - name: Restore Jest transform cache - uses: actions/cache@v4 - with: - path: /tmp/jest_runner - key: jest-server-${{ matrix.shard }}-${{ hashFiles('.babelrc', '.jestconfig.json', 'yarn.lock', 'server/**/*.ts', 'shared/**/*.ts', 'plugins/**/*.ts') }} - restore-keys: | - jest-server-${{ matrix.shard }}-${{ hashFiles('.babelrc', '.jestconfig.json', 'yarn.lock') }}- - jest-server-${{ matrix.shard }}- - run: yarn sequelize db:migrate - name: Run server tests - run: yarn test:server --maxWorkers=2 --shard=${{ matrix.shard }}/4 --cacheDirectory=/tmp/jest_runner + run: yarn test:server --maxWorkers=2 --shard=${{ matrix.shard }}/4 bundle-size: needs: changes diff --git a/.jestconfig.json b/.jestconfig.json deleted file mode 100644 index 3fd1bdd0b6..0000000000 --- a/.jestconfig.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "workerIdleMemoryLimit": "0.75", - "maxWorkers": "50%", - "transformIgnorePatterns": ["node_modules/(?!(franc|trigram-utils)/)"], - "projects": [ - { - "displayName": "server", - "roots": ["/server", "/plugins"], - "moduleNameMapper": { - "^@server/(.*)$": "/server/$1", - "^@shared/(.*)$": "/shared/$1" - }, - "setupFiles": [ - "/__mocks__/console.js", - "/server/test/setupMocks.js" - ], - "setupFilesAfterEnv": ["/server/test/setup.ts"], - "globalTeardown": "/server/test/globalTeardown.js", - "testEnvironment": "node" - }, - { - "displayName": "app", - "roots": ["/app"], - "moduleNameMapper": { - "^~/(.*)$": "/app/$1", - "^@shared/(.*)$": "/shared/$1", - "^.*[.](gif|ttf|eot|svg)$": "/__test__/fileMock.js" - }, - "modulePaths": ["/app"], - "setupFiles": ["/__mocks__/window.js"], - "setupFilesAfterEnv": ["/app/test/setup.ts"], - "testEnvironment": "jsdom", - "testEnvironmentOptions": { - "url": "http://localhost" - } - }, - { - "displayName": "shared-node", - "roots": ["/shared"], - "moduleNameMapper": { - "^@server/(.*)$": "/server/$1", - "^@shared/(.*)$": "/shared/$1" - }, - "setupFiles": ["/__mocks__/console.js"], - "setupFilesAfterEnv": ["/shared/test/setup.ts"], - "testEnvironment": "node" - }, - { - "displayName": "shared-jsdom", - "roots": ["/shared"], - "moduleNameMapper": { - "^~/(.*)$": "/app/$1", - "^@shared/(.*)$": "/shared/$1", - "^.*[.](gif|ttf|eot|svg)$": "/__test__/fileMock.js" - }, - "setupFiles": ["/__mocks__/window.js"], - "testEnvironment": "jsdom", - "testEnvironmentOptions": { - "url": "http://localhost" - } - } - ] -} diff --git a/app/test/setup.ts b/app/test/setup.ts index 8e7f2b23b5..0708133fa4 100644 --- a/app/test/setup.ts +++ b/app/test/setup.ts @@ -1,4 +1,6 @@ /* oxlint-disable */ +import "reflect-metadata"; +import { vi } from "vitest"; // @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module '../.... Remove this comment to see the full error message import localStorage from "../../__mocks__/localStorage"; import { initI18n } from "../utils/i18n"; @@ -7,6 +9,4 @@ initI18n(); global.localStorage = localStorage; -require("jest-fetch-mock").enableMocks(); - -jest.mock("~/utils/ApiClient"); +vi.mock("~/utils/ApiClient"); diff --git a/app/utils/__mocks__/ApiClient.ts b/app/utils/__mocks__/ApiClient.ts index 18ec9445e7..8cdd5475df 100644 --- a/app/utils/__mocks__/ApiClient.ts +++ b/app/utils/__mocks__/ApiClient.ts @@ -1,6 +1,8 @@ /* oxlint-disable */ +import { vi } from "vitest"; + export const client = { - post: jest.fn(() => + post: vi.fn(() => Promise.resolve({ data: { user: {}, diff --git a/package.json b/package.json index 077998ccab..b7180a3e5f 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,11 @@ "db:rollback": "sequelize db:migrate:undo", "db:reset": "sequelize db:drop && sequelize db:create && sequelize db:migrate", "upgrade": "git fetch && git pull && yarn install && yarn heroku-postbuild", - "test": "TZ=UTC jest --config=.jestconfig.json", - "test:app": "TZ=UTC jest --config=.jestconfig.json --selectProjects app", - "test:shared": "TZ=UTC jest --config=.jestconfig.json --selectProjects shared-node shared-jsdom", - "test:server": "TZ=UTC jest --config=.jestconfig.json --selectProjects server", + "test": "TZ=UTC vitest run", + "test:app": "TZ=UTC vitest run --project app", + "test:shared": "TZ=UTC vitest run --project shared-node --project shared-jsdom", + "test:server": "TZ=UTC vitest run --project server", + "test:watch": "TZ=UTC vitest", "vite:dev": "VITE_CJS_IGNORE_WARNING=true vite", "vite:build": "VITE_CJS_IGNORE_WARNING=true vite build", "vite:preview": "VITE_CJS_IGNORE_WARNING=true vite preview" @@ -283,6 +284,7 @@ "@babel/preset-typescript": "^7.28.5", "@faker-js/faker": "^8.4.1", "@relative-ci/agent": "^4.3.1", + "@swc/core": "^1.15.32", "@types/addressparser": "^1.0.3", "@types/cookie": "0.6.0", "@types/crypto-js": "^4.2.2", @@ -298,8 +300,8 @@ "@types/google.analytics": "^0.0.46", "@types/invariant": "^2.2.37", "@types/ioredis-mock": "^8.2.7", - "@types/jest": "^29.5.14", "@types/js-yaml": "^4.0.9", + "@types/jsdom": "^28.0.1", "@types/jsonwebtoken": "^8.5.9", "@types/katex": "^0.16.8", "@types/koa": "^2.15.0", @@ -346,7 +348,7 @@ "@types/utf8": "^3.0.3", "@types/validator": "^13.15.10", "@types/yauzl": "^2.10.3", - "babel-jest": "^30.3.0", + "@vitest/ui": "^4.1.5", "babel-plugin-module-resolver": "^5.0.3", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-inline-environment-variables": "^0.4.4", @@ -357,10 +359,8 @@ "husky": "^8.0.3", "i18next-parser": "^8.13.0", "ioredis-mock": "^8.13.1", - "jest-cli": "^30.3.0", - "jest-environment-jsdom": "^30.3.0", - "jest-fetch-mock": "^3.0.3", "lint-staged": "^16.4.0", + "msw": "^2.14.2", "nodemon": "^3.1.14", "oxlint": "1.50.0", "oxlint-tsgolint": "0.14.2", @@ -370,7 +370,11 @@ "rimraf": "^6.1.3", "rollup-plugin-webpack-stats": "2.1.11", "terser": "^5.44.1", - "typescript": "^5.9.3" + "typescript": "^5.9.3", + "unplugin-swc": "^1.5.9", + "vite-plugin-babel": "^1.6.0", + "vite-tsconfig-paths": "^6.1.1", + "vitest": "^4.1.5" }, "resolutions": { "@types/react": "17.0.91", diff --git a/plugins/email/server/auth/email.test.ts b/plugins/email/server/auth/email.test.ts index 901ea2dc85..5caf4dc7d0 100644 --- a/plugins/email/server/auth/email.test.ts +++ b/plugins/email/server/auth/email.test.ts @@ -28,7 +28,7 @@ describe("email", () => { }); it("should respond with redirect location when user is SSO enabled", async () => { - const spy = jest.spyOn(WelcomeEmail.prototype, "schedule"); + const spy = vi.spyOn(WelcomeEmail.prototype, "schedule"); const subdomain = faker.internet.domainWord(); const team = await buildTeam({ subdomain }); const user = await buildUser({ teamId: team.id }); @@ -48,7 +48,7 @@ describe("email", () => { }); it("should respond with success and email to be sent when user has SSO but disabled", async () => { - const spy = jest.spyOn(SigninEmail.prototype, "schedule"); + const spy = vi.spyOn(SigninEmail.prototype, "schedule"); const subdomain = faker.internet.domainWord(); const team = await buildTeam({ subdomain }); const user = await buildUser({ teamId: team.id }); @@ -83,7 +83,7 @@ describe("email", () => { it("should not send email when user is on another subdomain but respond with success", async () => { const user = await buildUser(); - const spy = jest.spyOn(WelcomeEmail.prototype, "schedule"); + const spy = vi.spyOn(WelcomeEmail.prototype, "schedule"); const subdomain = faker.internet.domainWord(); await buildTeam({ subdomain }); const res = await server.post("/auth/email", { @@ -103,7 +103,7 @@ describe("email", () => { }); it("should respond with success and email to be sent when user is not SSO enabled", async () => { - const spy = jest.spyOn(SigninEmail.prototype, "schedule"); + const spy = vi.spyOn(SigninEmail.prototype, "schedule"); const subdomain = faker.internet.domainWord(); const team = await buildTeam({ subdomain }); const user = await buildGuestUser({ @@ -125,7 +125,7 @@ describe("email", () => { }); it("should respond with success regardless of whether successful to prevent crawling email logins", async () => { - const spy = jest.spyOn(WelcomeEmail.prototype, "schedule"); + const spy = vi.spyOn(WelcomeEmail.prototype, "schedule"); const subdomain = faker.internet.domainWord(); await buildTeam({ subdomain }); const res = await server.post("/auth/email", { @@ -145,7 +145,7 @@ describe("email", () => { describe("with multiple users matching email", () => { it("should default to current subdomain with SSO", async () => { - const spy = jest.spyOn(SigninEmail.prototype, "schedule"); + const spy = vi.spyOn(SigninEmail.prototype, "schedule"); const email = "sso-user@example.org"; const subdomain = faker.internet.domainWord(); const team = await buildTeam({ @@ -174,7 +174,7 @@ describe("email", () => { }); it("should default to current subdomain with guest email", async () => { - const spy = jest.spyOn(SigninEmail.prototype, "schedule"); + const spy = vi.spyOn(SigninEmail.prototype, "schedule"); const email = "guest-user@example.org"; const subdomain = faker.internet.domainWord(); const team = await buildTeam({ @@ -203,7 +203,7 @@ describe("email", () => { }); it("should default to custom domain with SSO", async () => { - const spy = jest.spyOn(WelcomeEmail.prototype, "schedule"); + const spy = vi.spyOn(WelcomeEmail.prototype, "schedule"); const email = "sso-user-2@example.org"; const domain = faker.internet.domainName(); const team = await buildTeam({ @@ -232,7 +232,7 @@ describe("email", () => { }); it("should default to custom domain with guest email", async () => { - const spy = jest.spyOn(SigninEmail.prototype, "schedule"); + const spy = vi.spyOn(SigninEmail.prototype, "schedule"); const email = "guest-user-2@example.org"; const domain = faker.internet.domainName(); const team = await buildTeam({ diff --git a/plugins/notion/server/utils/NotionConverter.test.ts b/plugins/notion/server/utils/NotionConverter.test.ts index babc501a75..3fd168d40e 100644 --- a/plugins/notion/server/utils/NotionConverter.test.ts +++ b/plugins/notion/server/utils/NotionConverter.test.ts @@ -2,12 +2,19 @@ import { Node } from "prosemirror-model"; import { ProsemirrorHelper } from "@server/models/helpers/ProsemirrorHelper"; import nodesWithEmptyTextNode from "@server/test/fixtures/notion-page-with-empty-text-nodes.json"; import allNodes from "@server/test/fixtures/notion-page.json"; +import type { ProsemirrorData, ProsemirrorDoc } from "@shared/types"; import type { NotionPage } from "./NotionConverter"; import { NotionConverter } from "./NotionConverter"; -jest.mock("node:crypto", () => ({ - randomUUID: jest.fn(() => "550e8400-e29b-41d4-a716-446655440000"), -})); +const generatedId = "550e8400-e29b-41d4-a716-446655440000"; + +function normalizeGeneratedIds(node: ProsemirrorDoc | ProsemirrorData) { + if (node.type === "container_toggle" && node.attrs) { + node.attrs.id = generatedId; + } + + node.content?.forEach(normalizeGeneratedIds); +} describe("NotionConverter", () => { it("converts a page", () => { @@ -15,6 +22,7 @@ describe("NotionConverter", () => { children: allNodes, } as NotionPage); + normalizeGeneratedIds(response); expect(response).toMatchSnapshot(); expect(ProsemirrorHelper.toProsemirror(response)).toBeInstanceOf(Node); }); @@ -24,6 +32,7 @@ describe("NotionConverter", () => { children: nodesWithEmptyTextNode, } as NotionPage); + normalizeGeneratedIds(response); expect(response).toMatchSnapshot(); expect(ProsemirrorHelper.toProsemirror(response)).toBeInstanceOf(Node); }); diff --git a/plugins/notion/server/utils/__snapshots__/NotionConverter.test.ts.snap b/plugins/notion/server/utils/__snapshots__/NotionConverter.test.ts.snap index fa7a00d4c5..4e44a9db92 100644 --- a/plugins/notion/server/utils/__snapshots__/NotionConverter.test.ts.snap +++ b/plugins/notion/server/utils/__snapshots__/NotionConverter.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`NotionConverter converts a page 1`] = ` +exports[`NotionConverter > converts a page 1`] = ` { "content": [ { @@ -2093,7 +2093,7 @@ exports[`NotionConverter converts a page 1`] = ` } `; -exports[`NotionConverter converts a page with empty text nodes 1`] = ` +exports[`NotionConverter > converts a page with empty text nodes 1`] = ` { "content": [ { diff --git a/plugins/oidc/server/oidcDiscovery.test.ts b/plugins/oidc/server/oidcDiscovery.test.ts index 3f581b1dd4..654eaf4487 100644 --- a/plugins/oidc/server/oidcDiscovery.test.ts +++ b/plugins/oidc/server/oidcDiscovery.test.ts @@ -1,9 +1,22 @@ -import fetchMock from "jest-fetch-mock"; +import { + http, + HttpResponse, + type DefaultBodyType, + type StrictRequest, +} from "msw"; +import { server } from "@server/test/msw"; import { fetchOIDCConfiguration } from "./oidcDiscovery"; -beforeEach(() => { - fetchMock.resetMocks(); -}); +const captureRequest = (url: string, response: Response | (() => Response)) => { + const captured: { request?: StrictRequest } = {}; + server.use( + http.get(url, ({ request }) => { + captured.request = request; + return typeof response === "function" ? response() : response; + }) + ); + return captured; +}; describe("fetchOIDCConfiguration", () => { it("should fetch and parse OIDC configuration successfully", async () => { @@ -19,20 +32,18 @@ describe("fetchOIDCConfiguration", () => { grant_types_supported: ["authorization_code"], }; - fetchMock.mockResponseOnce(JSON.stringify(mockConfig)); + const captured = captureRequest( + "https://example.com/.well-known/openid-configuration", + () => HttpResponse.json(mockConfig) + ); const result = await fetchOIDCConfiguration("https://example.com"); - expect(fetchMock).toHaveBeenCalledWith( - "https://example.com/.well-known/openid-configuration", - expect.objectContaining({ - method: "GET", - headers: expect.objectContaining({ - Accept: "application/json", - }), - }) + expect(captured.request?.url).toBe( + "https://example.com/.well-known/openid-configuration" ); - + expect(captured.request?.method).toBe("GET"); + expect(captured.request?.headers.get("Accept")).toBe("application/json"); expect(result).toEqual(mockConfig); }); @@ -44,26 +55,37 @@ describe("fetchOIDCConfiguration", () => { userinfo_endpoint: "https://example.com/userinfo", }; - fetchMock.mockResponseOnce(JSON.stringify(mockConfig)); + const captured = captureRequest( + "https://example.com/.well-known/openid-configuration", + () => HttpResponse.json(mockConfig) + ); await fetchOIDCConfiguration("https://example.com/"); - expect(fetchMock).toHaveBeenCalledWith( - "https://example.com/.well-known/openid-configuration", - expect.any(Object) + expect(captured.request?.url).toBe( + "https://example.com/.well-known/openid-configuration" ); }); it("should throw error when HTTP request fails", async () => { - fetchMock.mockRejectOnce(new Error("Network error")); - - await expect(fetchOIDCConfiguration("https://example.com")).rejects.toThrow( - "Network error" + server.use( + http.get("https://example.com/.well-known/openid-configuration", () => + HttpResponse.error() + ) ); + + await expect( + fetchOIDCConfiguration("https://example.com") + ).rejects.toThrow(); }); it("should throw error when response is not ok", async () => { - fetchMock.mockResponseOnce("Not Found", { status: 404 }); + server.use( + http.get( + "https://example.com/.well-known/openid-configuration", + () => new HttpResponse("Not Found", { status: 404 }) + ) + ); await expect(fetchOIDCConfiguration("https://example.com")).rejects.toThrow( "Failed to fetch OIDC configuration: 404 Not Found" @@ -77,7 +99,11 @@ describe("fetchOIDCConfiguration", () => { // Missing token_endpoint and userinfo_endpoint }; - fetchMock.mockResponseOnce(JSON.stringify(incompleteConfig)); + server.use( + http.get("https://example.com/.well-known/openid-configuration", () => + HttpResponse.json(incompleteConfig) + ) + ); await expect(fetchOIDCConfiguration("https://example.com")).rejects.toThrow( "Missing token_endpoint in OIDC configuration" @@ -91,7 +117,11 @@ describe("fetchOIDCConfiguration", () => { userinfo_endpoint: "https://example.com/userinfo", }; - fetchMock.mockResponseOnce(JSON.stringify(configMissingAuth)); + server.use( + http.get("https://example.com/.well-known/openid-configuration", () => + HttpResponse.json(configMissingAuth) + ) + ); await expect(fetchOIDCConfiguration("https://example.com")).rejects.toThrow( "Missing authorization_endpoint in OIDC configuration" @@ -108,22 +138,20 @@ describe("fetchOIDCConfiguration", () => { "https://auth.example.com/application/o/outline/userinfo", }; - fetchMock.mockResponseOnce(JSON.stringify(mockConfig)); + const captured = captureRequest( + "https://auth.example.com/application/o/outline/.well-known/openid-configuration", + () => HttpResponse.json(mockConfig) + ); const result = await fetchOIDCConfiguration( "https://auth.example.com/application/o/outline/" ); - expect(fetchMock).toHaveBeenCalledWith( - "https://auth.example.com/application/o/outline/.well-known/openid-configuration", - expect.objectContaining({ - method: "GET", - headers: expect.objectContaining({ - Accept: "application/json", - }), - }) + expect(captured.request?.url).toBe( + "https://auth.example.com/application/o/outline/.well-known/openid-configuration" ); - + expect(captured.request?.method).toBe("GET"); + expect(captured.request?.headers.get("Accept")).toBe("application/json"); expect(result).toEqual(mockConfig); }); @@ -137,22 +165,20 @@ describe("fetchOIDCConfiguration", () => { "https://auth.example.com/application/o/outline/userinfo", }; - fetchMock.mockResponseOnce(JSON.stringify(mockConfig)); + const captured = captureRequest( + "https://auth.example.com/application/o/outline/.well-known/openid-configuration", + () => HttpResponse.json(mockConfig) + ); const result = await fetchOIDCConfiguration( "https://auth.example.com/application/o/outline" ); - expect(fetchMock).toHaveBeenCalledWith( - "https://auth.example.com/application/o/outline/.well-known/openid-configuration", - expect.objectContaining({ - method: "GET", - headers: expect.objectContaining({ - Accept: "application/json", - }), - }) + expect(captured.request?.url).toBe( + "https://auth.example.com/application/o/outline/.well-known/openid-configuration" ); - + expect(captured.request?.method).toBe("GET"); + expect(captured.request?.headers.get("Accept")).toBe("application/json"); expect(result).toEqual(mockConfig); }); @@ -164,17 +190,18 @@ describe("fetchOIDCConfiguration", () => { userinfo_endpoint: "https://example.com/userinfo", }; - fetchMock.mockResponseOnce(JSON.stringify(mockConfig)); + const captured = captureRequest( + "https://example.com/.well-known/openid-configuration", + () => HttpResponse.json(mockConfig) + ); const result = await fetchOIDCConfiguration( "https://example.com/.well-known/openid-configuration" ); - expect(fetchMock).toHaveBeenCalledWith( - "https://example.com/.well-known/openid-configuration", - expect.any(Object) + expect(captured.request?.url).toBe( + "https://example.com/.well-known/openid-configuration" ); - expect(result).toEqual(mockConfig); }); }); diff --git a/plugins/search-postgres/server/PostgresSearchProvider.test.ts b/plugins/search-postgres/server/PostgresSearchProvider.test.ts index cb78759f20..ad7fba7cd1 100644 --- a/plugins/search-postgres/server/PostgresSearchProvider.test.ts +++ b/plugins/search-postgres/server/PostgresSearchProvider.test.ts @@ -21,7 +21,7 @@ import PostgresSearchProvider from "./PostgresSearchProvider"; const provider = SearchProviderManager.getProvider(); beforeEach(async () => { - jest.resetAllMocks(); + vi.resetAllMocks(); await buildDocument(); }); diff --git a/plugins/slack/server/api/hooks.test.ts b/plugins/slack/server/api/hooks.test.ts index 3d91363aef..35769ce1ab 100644 --- a/plugins/slack/server/api/hooks.test.ts +++ b/plugins/slack/server/api/hooks.test.ts @@ -6,12 +6,16 @@ import { getTestServer } from "@server/test/support"; import env from "../env"; import * as Slack from "../slack"; -jest.mock("../slack", () => ({ - post: jest.fn(), -})); - const server = getTestServer(); +beforeEach(() => { + vi.spyOn(Slack, "post").mockResolvedValue({ ok: true }); +}); + +afterEach(() => { + vi.restoreAllMocks(); +}); + describe("#hooks.unfurl", () => { it("should return documents with matching SSO user", async () => { const user = await buildUser(); diff --git a/plugins/storage/server/api/files.test.ts b/plugins/storage/server/api/files.test.ts index 3a489486ec..670fbb437c 100644 --- a/plugins/storage/server/api/files.test.ts +++ b/plugins/storage/server/api/files.test.ts @@ -20,7 +20,7 @@ import { randomUUID } from "node:crypto"; const server = getTestServer(); // Increase timeout for all tests in this file -jest.setTimeout(10000); +vi.setConfig({ testTimeout: 10000 }); describe("#files.create", () => { it("should fail with status 400 bad request if key is invalid", async () => { diff --git a/plugins/webhooks/server/processors/WebhookProcessor.test.ts b/plugins/webhooks/server/processors/WebhookProcessor.test.ts index 4334c36cf3..e7c34edf97 100644 --- a/plugins/webhooks/server/processors/WebhookProcessor.test.ts +++ b/plugins/webhooks/server/processors/WebhookProcessor.test.ts @@ -1,16 +1,10 @@ import { buildUser, buildWebhookSubscription } from "@server/test/factories"; +import { mockTaskSchedule } from "@server/test/support"; import type { UserEvent } from "@server/types"; -import DeliverWebhookTask from "../tasks/DeliverWebhookTask"; import WebhookProcessor from "./WebhookProcessor"; -jest.mock("../tasks/DeliverWebhookTask"); const ip = "127.0.0.1"; -const schedule = jest.fn(); - -beforeEach(() => { - jest.resetAllMocks(); - DeliverWebhookTask.prototype.schedule = schedule; -}); +const schedule = mockTaskSchedule(); describe("WebhookProcessor", () => { it("it schedules a delivery for the event", async () => { diff --git a/plugins/webhooks/server/tasks/DeliverWebhookTask.test.ts b/plugins/webhooks/server/tasks/DeliverWebhookTask.test.ts index 63648a70a6..0381365aec 100644 --- a/plugins/webhooks/server/tasks/DeliverWebhookTask.test.ts +++ b/plugins/webhooks/server/tasks/DeliverWebhookTask.test.ts @@ -1,4 +1,10 @@ -import fetchMock from "jest-fetch-mock"; +import { + http, + HttpResponse, + type DefaultBodyType, + type StrictRequest, +} from "msw"; +import { server } from "@server/test/msw"; import { WebhookDelivery } from "@server/models"; import { buildUser, @@ -8,14 +14,28 @@ import { import type { UserEvent } from "@server/types"; import DeliverWebhookTask from "./DeliverWebhookTask"; -beforeEach(async () => { - jest.resetAllMocks(); - fetchMock.resetMocks(); - fetchMock.doMock(); -}); - const ip = "127.0.0.1"; +type CapturedRequest = { + request: StrictRequest; + body: string; +}; + +const captureWebhook = ( + url: string, + response: () => Response = () => new HttpResponse(null, { status: 200 }) +) => { + const captured: CapturedRequest[] = []; + server.use( + http.post(url, async ({ request }) => { + const cloned = request.clone(); + captured.push({ request, body: await cloned.text() }); + return response(); + }) + ); + return captured; +}; + describe("DeliverWebhookTask", () => { test("should hit the subscription url and record a delivery", async () => { const subscription = await buildWebhookSubscription({ @@ -25,7 +45,10 @@ describe("DeliverWebhookTask", () => { const signedInUser = await buildUser({ teamId: subscription.teamId }); const processor = new DeliverWebhookTask(); - fetchMock.mockResponse("SUCCESS", { status: 200 }); + const captured = captureWebhook( + "http://example.com", + () => new HttpResponse("SUCCESS", { status: 200 }) + ); const event: UserEvent = { name: "users.signin", @@ -39,12 +62,9 @@ describe("DeliverWebhookTask", () => { event, }); - expect(fetchMock).toHaveBeenCalledTimes(1); - expect(fetchMock).toHaveBeenCalledWith( - "http://example.com", - expect.anything() - ); - const parsedBody = JSON.parse(fetchMock.mock.calls[0]![1]!.body as string); + expect(captured.length).toBe(1); + expect(captured[0].request.url).toBe("http://example.com/"); + const parsedBody = JSON.parse(captured[0].body); expect(parsedBody.webhookSubscriptionId).toBe(subscription.id); expect(parsedBody.event).toBe("users.signin"); expect(parsedBody.payload.id).toBe(signedInUser.id); @@ -70,6 +90,8 @@ describe("DeliverWebhookTask", () => { const signedInUser = await buildUser({ teamId: subscription.teamId }); const processor = new DeliverWebhookTask(); + const captured = captureWebhook("http://example.com"); + const event: UserEvent = { name: "users.signin", userId: signedInUser.id, @@ -82,13 +104,10 @@ describe("DeliverWebhookTask", () => { event, }); - const headers = fetchMock.mock.calls[0]![1]!.headers! as Record< - string, - string - >; - - expect(fetchMock).toHaveBeenCalledTimes(1); - expect(headers["Outline-Signature"]).toMatch(/^t=[0-9]+,s=[a-z0-9]+$/); + expect(captured.length).toBe(1); + expect(captured[0].request.headers.get("Outline-Signature")).toMatch( + /^t=[0-9]+,s=[a-z0-9]+$/ + ); }); test("should hit the subscription url when the eventing model doesn't exist", async () => { @@ -108,17 +127,16 @@ describe("DeliverWebhookTask", () => { ip, }; + const captured = captureWebhook("http://example.com"); + await task.perform({ event, subscriptionId: subscription.id, }); - expect(fetchMock).toHaveBeenCalledTimes(1); - expect(fetchMock).toHaveBeenCalledWith( - "http://example.com", - expect.anything() - ); - const parsedBody = JSON.parse(fetchMock.mock.calls[0]![1]!.body as string); + expect(captured.length).toBe(1); + expect(captured[0].request.url).toBe("http://example.com/"); + const parsedBody = JSON.parse(captured[0].body); expect(parsedBody.webhookSubscriptionId).toBe(subscription.id); expect(parsedBody.event).toBe("users.delete"); expect(parsedBody.payload.id).toBe(deletedUserId); @@ -140,7 +158,10 @@ describe("DeliverWebhookTask", () => { events: ["*"], }); - fetchMock.mockResponse("FAILED", { status: 500 }); + captureWebhook( + "http://example.com", + () => new HttpResponse("FAILED", { status: 500 }) + ); const signedInUser = await buildUser({ teamId: subscription.teamId }); const task = new DeliverWebhookTask(); @@ -186,9 +207,9 @@ describe("DeliverWebhookTask", () => { }); } - fetchMock.mockResponse(JSON.stringify({ message: "Failure" }), { - status: 500, - }); + captureWebhook("http://example.com", () => + HttpResponse.json({ message: "Failure" }, { status: 500 }) + ); const signedInUser = await buildUser({ teamId: subscription.teamId }); const task = new DeliverWebhookTask(); diff --git a/server/__mocks__/fetch-with-proxy.ts b/server/__mocks__/fetch-with-proxy.ts deleted file mode 100644 index e52013f8d3..0000000000 --- a/server/__mocks__/fetch-with-proxy.ts +++ /dev/null @@ -1,9 +0,0 @@ -import fetchMock from "jest-fetch-mock"; - -fetchMock.enableMocks(); - -// changes default behavior of fetchMock to use the real 'fetch' implementation. -// Mocks can now be enabled in each individual test with fetchMock.doMock() -fetchMock.dontMock(); - -export default fetch; diff --git a/server/__mocks__/franc.js b/server/__mocks__/franc.js deleted file mode 100644 index 8ca1da9b9b..0000000000 --- a/server/__mocks__/franc.js +++ /dev/null @@ -1,10 +0,0 @@ -// Mock for franc language detection library -const franc = jest.fn((text) => { - // Return 'eng' (English) by default, or 'und' (undetermined) for empty text - if (!text || text.trim().length === 0) { - return "und"; - } - return "eng"; -}); - -module.exports = { franc }; diff --git a/server/__mocks__/franc.ts b/server/__mocks__/franc.ts new file mode 100644 index 0000000000..feeca5467d --- /dev/null +++ b/server/__mocks__/franc.ts @@ -0,0 +1,9 @@ +import { vi } from "vitest"; + +export const franc = vi.fn((text: string) => { + if (!text || text.trim().length === 0) { + return "und"; + } + + return "eng"; +}); diff --git a/server/__mocks__/iso-639-3.js b/server/__mocks__/iso-639-3.ts similarity index 52% rename from server/__mocks__/iso-639-3.js rename to server/__mocks__/iso-639-3.ts index 6d18ef4f83..401fa7c02c 100644 --- a/server/__mocks__/iso-639-3.js +++ b/server/__mocks__/iso-639-3.ts @@ -1,5 +1,4 @@ -// Mock for iso-639-3 language code conversion library -const iso6393To1 = { +export const iso6393To1: Record = { eng: "en", fra: "fr", deu: "de", @@ -12,7 +11,5 @@ const iso6393To1 = { ara: "ar", hin: "hi", ben: "bn", - und: undefined, // undetermined + und: undefined, }; - -module.exports = { iso6393To1 }; diff --git a/server/__mocks__/request-filtering-agent.ts b/server/__mocks__/request-filtering-agent.ts new file mode 100644 index 0000000000..9408632e3f --- /dev/null +++ b/server/__mocks__/request-filtering-agent.ts @@ -0,0 +1,25 @@ +import http from "node:http"; +import https from "node:https"; + +interface MockAgentOptions + extends http.AgentOptions, Pick {} + +export function useAgent(url: string, options: MockAgentOptions = {}) { + const parsedUrl = new URL(url); + const agentOptions = { + keepAlive: options.keepAlive, + timeout: options.timeout, + keepAliveMsecs: options.keepAliveMsecs, + maxSockets: options.maxSockets, + maxFreeSockets: options.maxFreeSockets, + }; + + if (parsedUrl.protocol === "https:") { + return new https.Agent({ + ...agentOptions, + maxCachedSessions: options.maxCachedSessions, + }); + } + + return new http.Agent(agentOptions); +} diff --git a/server/collaboration/ConnectionLimitExtension.test.ts b/server/collaboration/ConnectionLimitExtension.test.ts index d73ffd8ead..60fd2aa538 100644 --- a/server/collaboration/ConnectionLimitExtension.test.ts +++ b/server/collaboration/ConnectionLimitExtension.test.ts @@ -5,7 +5,10 @@ import { sleep } from "@shared/utils/timers"; import { ConnectionLimitExtension } from "./ConnectionLimitExtension"; import { EditorVersionExtension } from "./EditorVersionExtension"; -jest.mock("@server/env", () => ({ +vi.mock("@server/env", () => ({ + default: { + COLLABORATION_MAX_CLIENTS_PER_DOCUMENT: 2, + }, COLLABORATION_MAX_CLIENTS_PER_DOCUMENT: 2, })); @@ -13,7 +16,7 @@ describe("ConnectionLimitExtension", () => { let server: typeof Server; let extension: ConnectionLimitExtension; const port = 12345; - const url = `ws://localhost:${port}`; + const url = `ws://127.0.0.1:${port}`; const documentName = "test"; beforeEach(async () => { diff --git a/server/commands/documentImporter.test.ts b/server/commands/documentImporter.test.ts index 1356f99cec..1f6a32f067 100644 --- a/server/commands/documentImporter.test.ts +++ b/server/commands/documentImporter.test.ts @@ -6,7 +6,7 @@ import { sequelize } from "@server/storage/database"; import { buildUser } from "@server/test/factories"; import documentImporter from "./documentImporter"; -jest.mock("@server/storage/files"); +vi.mock("@server/storage/files"); describe("documentImporter", () => { it("should convert Word Document to markdown", async () => { diff --git a/server/commands/documentPermanentDeleter.test.ts b/server/commands/documentPermanentDeleter.test.ts index bf14cae22c..08eb7166bf 100644 --- a/server/commands/documentPermanentDeleter.test.ts +++ b/server/commands/documentPermanentDeleter.test.ts @@ -1,17 +1,10 @@ import { subDays } from "date-fns"; import { Attachment, Document } from "@server/models"; -import DeleteAttachmentTask from "@server/queues/tasks/DeleteAttachmentTask"; import { buildAttachment, buildDocument } from "@server/test/factories"; +import { mockTaskSchedule } from "@server/test/support"; import documentPermanentDeleter from "./documentPermanentDeleter"; -jest.mock("@server/queues/tasks/DeleteAttachmentTask"); - -const schedule = jest.fn(); - -beforeEach(() => { - jest.resetAllMocks(); - DeleteAttachmentTask.prototype.schedule = schedule; -}); +const schedule = mockTaskSchedule(); describe("documentPermanentDeleter", () => { it("should destroy documents", async () => { diff --git a/server/commands/documentUpdater.test.ts b/server/commands/documentUpdater.test.ts index 0051eb7cfe..0ee4db3c94 100644 --- a/server/commands/documentUpdater.test.ts +++ b/server/commands/documentUpdater.test.ts @@ -68,7 +68,7 @@ describe("documentUpdater", () => { }); it("should notify collaboration server when text changes", async () => { - const notifyUpdateSpy = jest + const notifyUpdateSpy = vi .spyOn(APIUpdateExtension, "notifyUpdate") .mockResolvedValue(undefined); @@ -95,7 +95,7 @@ describe("documentUpdater", () => { }); it("should not notify collaboration server when only title changes", async () => { - const notifyUpdateSpy = jest + const notifyUpdateSpy = vi .spyOn(APIUpdateExtension, "notifyUpdate") .mockResolvedValue(undefined); diff --git a/server/emails/templates/index.ts b/server/emails/templates/index.ts index e5c86cfb72..f2fcf6de6a 100644 --- a/server/emails/templates/index.ts +++ b/server/emails/templates/index.ts @@ -1,22 +1,24 @@ import { Hook, PluginManager } from "@server/utils/PluginManager"; import { requireDirectory } from "@server/utils/fs"; +import { createLazyRegistry } from "@server/utils/lazyRegistry"; import type BaseEmail from "./BaseEmail"; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- registry of heterogeneous template Props subtypes; BaseEmail isn't assignable from BaseEmail. -const emails: Record> = {}; - -requireDirectory<{ default: typeof BaseEmail }>(__dirname).forEach( - ([module, id]) => { - if (id === "index") { - return; +const emails = createLazyRegistry>(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const registry: Record> = {}; + requireDirectory<{ default: typeof BaseEmail }>(__dirname).forEach( + ([module, id]) => { + if (id === "index") { + return; + } + registry[id] = module.default; } - - emails[id] = module.default; - } -); - -PluginManager.getHooks(Hook.EmailTemplate).forEach((hook) => { - emails[hook.value.name] = hook.value; + ); + PluginManager.getHooks(Hook.EmailTemplate).forEach((hook) => { + registry[hook.value.name] = hook.value; + }); + return registry; }); export default emails; diff --git a/server/middlewares/authentication.test.ts b/server/middlewares/authentication.test.ts index f92acca961..661d553e2e 100644 --- a/server/middlewares/authentication.test.ts +++ b/server/middlewares/authentication.test.ts @@ -21,12 +21,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${user.getJwtToken()}`), + get: vi.fn(() => `Bearer ${user.getJwtToken()}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -41,12 +41,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${user.getJwtToken()}error`), + get: vi.fn(() => `Bearer ${user.getJwtToken()}error`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toBe("Invalid token"); @@ -65,12 +65,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${user.getJwtToken()}`), + get: vi.fn(() => `Bearer ${user.getJwtToken()}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toBe("Invalid authentication type"); @@ -88,12 +88,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${key.value}`), + get: vi.fn(() => `Bearer ${key.value}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -112,12 +112,12 @@ describe("Authentication middleware", () => { // @ts-expect-error mock request request: { url: "/auth.info", - get: jest.fn(() => `Bearer ${key.value}`), + get: vi.fn(() => `Bearer ${key.value}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -138,12 +138,12 @@ describe("Authentication middleware", () => { // @ts-expect-error mock request request: { url: "/documents.create", - get: jest.fn(() => `Bearer ${key.value}`), + get: vi.fn(() => `Bearer ${key.value}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); throw new Error("Expected error to be thrown"); } catch (e) { @@ -162,12 +162,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${randomString(38)}`), + get: vi.fn(() => `Bearer ${randomString(38)}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toBe("Invalid API key"); @@ -191,12 +191,12 @@ describe("Authentication middleware", () => { // @ts-expect-error mock request request: { url: "/users.info", - get: jest.fn(() => `Bearer ${authentication.accessToken}`), + get: vi.fn(() => `Bearer ${authentication.accessToken}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -217,12 +217,12 @@ describe("Authentication middleware", () => { // @ts-expect-error mock request request: { url: "/documents.create", - get: jest.fn(() => `Bearer ${authentication.accessToken}`), + get: vi.fn(() => `Bearer ${authentication.accessToken}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toContain("does not have access to this resource"); @@ -244,7 +244,7 @@ describe("Authentication middleware", () => { request: { url: "/users.info", // @ts-expect-error mock request - get: jest.fn(() => null), + get: vi.fn(() => null), body: { token: authentication.accessToken, }, @@ -252,7 +252,7 @@ describe("Authentication middleware", () => { state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toContain( @@ -271,12 +271,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => "error"), + get: vi.fn(() => "error"), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (e) { expect(e.message).toBe( @@ -293,7 +293,7 @@ describe("Authentication middleware", () => { { request: { // @ts-expect-error mock request - get: jest.fn(() => null), + get: vi.fn(() => null), query: { token: user.getJwtToken(), }, @@ -301,7 +301,7 @@ describe("Authentication middleware", () => { state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -314,7 +314,7 @@ describe("Authentication middleware", () => { { request: { // @ts-expect-error mock request - get: jest.fn(() => null), + get: vi.fn(() => null), body: { token: user.getJwtToken(), }, @@ -322,7 +322,7 @@ describe("Authentication middleware", () => { state, cache: {}, }, - jest.fn() + vi.fn() ); expect(state.auth.user.id).toEqual(user.id); }); @@ -342,12 +342,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${user.getJwtToken()}`), + get: vi.fn(() => `Bearer ${user.getJwtToken()}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (err) { error = err; @@ -372,12 +372,12 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${user.getJwtToken()}`), + get: vi.fn(() => `Bearer ${user.getJwtToken()}`), }, state, cache: {}, }, - jest.fn() + vi.fn() ); } catch (err) { error = err; diff --git a/server/middlewares/rateLimiter.test.ts b/server/middlewares/rateLimiter.test.ts index c745365861..4500d54d66 100644 --- a/server/middlewares/rateLimiter.test.ts +++ b/server/middlewares/rateLimiter.test.ts @@ -18,7 +18,7 @@ describe("rateLimiter middleware", () => { afterEach(() => { env.RATE_LIMITER_ENABLED = originalRateLimiterEnabled; env.RATE_LIMITER_MULTIPLIER = originalApiMultiplier; - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it("should register and enforce custom rate limiter with matching paths (no mountPath)", async () => { @@ -29,11 +29,11 @@ describe("rateLimiter middleware", () => { path: "/documents.export", mountPath: undefined, ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: {}, } as unknown as Context; - await registerMiddleware(mockCtx, jest.fn()); + await registerMiddleware(mockCtx, vi.fn()); const registeredPath = "/documents.export"; expect(RateLimiter.hasRateLimiter(registeredPath)).toBe(true); @@ -51,11 +51,11 @@ describe("rateLimiter middleware", () => { path: "/documents.export", mountPath: "/api", ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: {}, } as unknown as Context; - await registerMiddleware(mockCtxRegister, jest.fn()); + await registerMiddleware(mockCtxRegister, vi.fn()); const registrationPath = "/api/documents.export"; expect(RateLimiter.hasRateLimiter(registrationPath)).toBe(true); @@ -73,11 +73,11 @@ describe("rateLimiter middleware", () => { path: "/documents.export", mountPath: undefined, ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: {}, } as unknown as Context; - await registerMiddleware(mockCtx, jest.fn()); + await registerMiddleware(mockCtx, vi.fn()); const limiter = RateLimiter.getRateLimiter("/documents.export"); expect(limiter.points).toBe(10); @@ -91,11 +91,11 @@ describe("rateLimiter middleware", () => { path: "/shares.subscribe", mountPath: undefined, ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: {}, } as unknown as Context; - await registerMiddleware(mockCtx, jest.fn()); + await registerMiddleware(mockCtx, vi.fn()); const limiter = RateLimiter.getRateLimiter("/shares.subscribe"); expect(limiter.points).toBe(1); @@ -112,16 +112,16 @@ describe("rateLimiter middleware", () => { describe("cache-keyed rate limiting", () => { it("falls back to IP when no token is present", async () => { const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - const cacheSpy = jest.spyOn(RateLimiter, "getCachedUserIdForToken"); + const cacheSpy = vi.spyOn(RateLimiter, "getCachedUserIdForToken"); const mockCtx = { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => undefined, body: {}, @@ -130,7 +130,7 @@ describe("rateLimiter middleware", () => { cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(cacheSpy).not.toHaveBeenCalled(); expect(consumeSpy).toHaveBeenCalledWith("192.168.1.1"); @@ -139,22 +139,22 @@ describe("rateLimiter middleware", () => { it("short-circuits to IP for API key tokens without hitting Redis or JWT verify", async () => { const apiKeyToken = `${ApiKey.prefix}${"a".repeat(38)}`; const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - const cacheReadSpy = jest.spyOn(RateLimiter, "getCachedUserIdForToken"); - const verifySpy = jest.spyOn(jwtUtils, "getUserForJWT"); + const cacheReadSpy = vi.spyOn(RateLimiter, "getCachedUserIdForToken"); + const verifySpy = vi.spyOn(jwtUtils, "getUserForJWT"); const mockCtx = { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => `Bearer ${apiKeyToken}` }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(cacheReadSpy).not.toHaveBeenCalled(); expect(verifySpy).not.toHaveBeenCalled(); @@ -163,29 +163,27 @@ describe("rateLimiter middleware", () => { it("falls back to IP when token fails verification (forged or expired)", async () => { const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - jest - .spyOn(RateLimiter, "getCachedUserIdForToken") - .mockResolvedValue(null); - const cacheWriteSpy = jest + vi.spyOn(RateLimiter, "getCachedUserIdForToken").mockResolvedValue(null); + const cacheWriteSpy = vi .spyOn(RateLimiter, "cacheUserForToken") .mockResolvedValue(); - jest - .spyOn(jwtUtils, "getUserForJWT") - .mockRejectedValue(new Error("invalid token")); + vi.spyOn(jwtUtils, "getUserForJWT").mockRejectedValue( + new Error("invalid token") + ); const mockCtx = { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => "Bearer forged-or-unknown-token" }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(consumeSpy).toHaveBeenCalledWith("192.168.1.1"); expect(cacheWriteSpy).not.toHaveBeenCalled(); @@ -193,16 +191,14 @@ describe("rateLimiter middleware", () => { it("verifies and caches the user on cache miss, then keys by user", async () => { const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - jest - .spyOn(RateLimiter, "getCachedUserIdForToken") - .mockResolvedValue(null); - const cacheWriteSpy = jest + vi.spyOn(RateLimiter, "getCachedUserIdForToken").mockResolvedValue(null); + const cacheWriteSpy = vi .spyOn(RateLimiter, "cacheUserForToken") .mockResolvedValue(); - jest.spyOn(jwtUtils, "getUserForJWT").mockResolvedValue({ + vi.spyOn(jwtUtils, "getUserForJWT").mockResolvedValue({ user: { id: "user-abc" }, } as never); @@ -210,12 +206,12 @@ describe("rateLimiter middleware", () => { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => "Bearer valid-token" }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(cacheWriteSpy).toHaveBeenCalledWith("valid-token", "user-abc"); expect(consumeSpy).toHaveBeenCalledWith("user-abc"); @@ -223,24 +219,24 @@ describe("rateLimiter middleware", () => { it("keys on user id when token is in cache without re-verifying", async () => { const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - jest - .spyOn(RateLimiter, "getCachedUserIdForToken") - .mockResolvedValue("user-abc"); - const verifySpy = jest.spyOn(jwtUtils, "getUserForJWT"); + vi.spyOn(RateLimiter, "getCachedUserIdForToken").mockResolvedValue( + "user-abc" + ); + const verifySpy = vi.spyOn(jwtUtils, "getUserForJWT"); const mockCtx = { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => "Bearer verified-token" }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(verifySpy).not.toHaveBeenCalled(); expect(consumeSpy).toHaveBeenCalledWith("user-abc"); @@ -248,23 +244,23 @@ describe("rateLimiter middleware", () => { it("falls back to IP when the cache lookup throws", async () => { const middleware = defaultRateLimiter(); - const consumeSpy = jest + const consumeSpy = vi .spyOn(RateLimiter.defaultRateLimiter, "consume") .mockResolvedValue({} as never); - jest - .spyOn(RateLimiter, "getCachedUserIdForToken") - .mockRejectedValue(new Error("redis down")); + vi.spyOn(RateLimiter, "getCachedUserIdForToken").mockRejectedValue( + new Error("redis down") + ); const mockCtx = { path: "/some/path", mountPath: undefined, ip: "192.168.1.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => "Bearer some-token" }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(consumeSpy).toHaveBeenCalledWith("192.168.1.1"); }); @@ -275,30 +271,30 @@ describe("rateLimiter middleware", () => { path: "/documents.export", mountPath: "/api", ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: {}, } as unknown as Context; - await registerMiddleware(registerCtx, jest.fn()); + await registerMiddleware(registerCtx, vi.fn()); const customLimiter = RateLimiter.getRateLimiter("/api/documents.export"); - const consumeSpy = jest + const consumeSpy = vi .spyOn(customLimiter, "consume") .mockResolvedValue({} as never); - jest - .spyOn(RateLimiter, "getCachedUserIdForToken") - .mockResolvedValue("user-abc"); + vi.spyOn(RateLimiter, "getCachedUserIdForToken").mockResolvedValue( + "user-abc" + ); const middleware = defaultRateLimiter(); const mockCtx = { path: "/documents.export", mountPath: "/api", ip: "127.0.0.1", - set: jest.fn(), + set: vi.fn(), request: { get: () => "Bearer verified-token" }, cookies: { get: () => undefined }, } as unknown as Context; - await middleware(mockCtx, jest.fn()); + await middleware(mockCtx, vi.fn()); expect(consumeSpy).toHaveBeenCalledWith("/api/documents.export:user-abc"); }); diff --git a/server/middlewares/timeout.test.ts b/server/middlewares/timeout.test.ts index 30a95e74e2..d1646280fe 100644 --- a/server/middlewares/timeout.test.ts +++ b/server/middlewares/timeout.test.ts @@ -6,7 +6,7 @@ describe("Timeout middleware", () => { const originalTimeout = 10000; const newTimeout = 1800000; // 30 minutes - const setTimeout = jest.fn(); + const setTimeout = vi.fn(); const mockSocket = { timeout: originalTimeout, setTimeout, @@ -18,7 +18,7 @@ describe("Timeout middleware", () => { }, }; - const next = jest.fn(); + const next = vi.fn(); const middleware = timeout(newTimeout); await middleware( @@ -39,7 +39,7 @@ describe("Timeout middleware", () => { const originalTimeout = 10000; const newTimeout = 1800000; // 30 minutes - const setTimeout = jest.fn(); + const setTimeout = vi.fn(); const mockSocket = { timeout: originalTimeout, setTimeout, @@ -52,7 +52,7 @@ describe("Timeout middleware", () => { }; const error = new Error("Test error"); - const next = jest.fn().mockRejectedValue(error); + const next = vi.fn().mockRejectedValue(error); const middleware = timeout(newTimeout); await expect( @@ -74,7 +74,7 @@ describe("Timeout middleware", () => { it("should handle undefined original timeout", async () => { const newTimeout = 1800000; // 30 minutes - const setTimeout = jest.fn(); + const setTimeout = vi.fn(); const mockSocket = { timeout: undefined, setTimeout, @@ -86,7 +86,7 @@ describe("Timeout middleware", () => { }, }; - const next = jest.fn(); + const next = vi.fn(); const middleware = timeout(newTimeout); await middleware( diff --git a/server/models/Collection.test.ts b/server/models/Collection.test.ts index 22d8b8208d..50c971901c 100644 --- a/server/models/Collection.test.ts +++ b/server/models/Collection.test.ts @@ -13,7 +13,7 @@ import Collection from "./Collection"; import Document from "./Document"; beforeEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); describe("#url", () => { @@ -311,7 +311,7 @@ describe("#removeDocument", () => { const document = await buildDocument({ collectionId: collection.id }); await collection.reload(); - const saveSpy = jest.spyOn(collection, "save"); + const saveSpy = vi.spyOn(collection, "save"); await collection.deleteDocument(document); expect(saveSpy).toHaveBeenCalled(); }); diff --git a/server/models/Document.test.ts b/server/models/Document.test.ts index dbafb667be..e8636b5dc6 100644 --- a/server/models/Document.test.ts +++ b/server/models/Document.test.ts @@ -15,7 +15,7 @@ import { withAPIContext } from "@server/test/support"; import UserMembership from "./UserMembership"; beforeEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); describe("#getSummary", () => { diff --git a/server/models/DocumentInsight.ts b/server/models/DocumentInsight.ts index 591527635b..81d62632d9 100644 --- a/server/models/DocumentInsight.ts +++ b/server/models/DocumentInsight.ts @@ -13,7 +13,19 @@ import IdModel from "./base/IdModel"; import { SkipChangeset } from "./decorators/Changeset"; import Fix from "./decorators/Fix"; -@Table({ tableName: "document_insights", modelName: "documentInsight" }) +@Table({ + tableName: "document_insights", + modelName: "documentInsight", + indexes: [ + { + fields: ["documentId", "date"], + unique: true, + }, + { + fields: ["teamId", "date"], + }, + ], +}) @Fix class DocumentInsight extends IdModel< InferAttributes, diff --git a/server/models/Team.test.ts b/server/models/Team.test.ts index 31d5cf9560..d78108df38 100644 --- a/server/models/Team.test.ts +++ b/server/models/Team.test.ts @@ -16,7 +16,7 @@ describe("Team", () => { }); it("should normalize domain to lowercase", async () => { - const id = randomUUID(); + const id = randomUUID().split("-")[0]; const team = await buildTeam({ domain: `${id}.example.com` }); const result = await Team.findByDomain(`${id}.Example.COM`); expect(result?.id).toEqual(team.id); @@ -70,21 +70,23 @@ describe("Team", () => { describe("previousSubdomains", () => { it("should list the previous subdomains", async () => { + const id = randomUUID(); + const originalSubdomain = `example-${id}`; + const subdomain = `updated-${id}`; + const subdomain2 = `another-${id}`; const team = await buildTeam({ - subdomain: "example", + subdomain: originalSubdomain, }); - const subdomain = "updated"; await team.update({ subdomain }); expect(team.subdomain).toEqual(subdomain); expect(team.previousSubdomains?.length).toEqual(1); - expect(team.previousSubdomains?.[0]).toEqual("example"); + expect(team.previousSubdomains?.[0]).toEqual(originalSubdomain); - const subdomain2 = "another"; await team.update({ subdomain: subdomain2 }); expect(team.subdomain).toEqual(subdomain2); expect(team.previousSubdomains?.length).toEqual(2); - expect(team.previousSubdomains?.[0]).toEqual("example"); + expect(team.previousSubdomains?.[0]).toEqual(originalSubdomain); expect(team.previousSubdomains?.[1]).toEqual(subdomain); }); }); @@ -104,7 +106,8 @@ describe("Team", () => { }); it("should return signed URL for private-bucket attachment redirect", async () => { - jest.useFakeTimers().setSystemTime(new Date("2026-04-16T00:00:00.000Z")); + vi.useFakeTimers(); + vi.setSystemTime(new Date("2026-04-16T00:00:00.000Z")); try { const team = await buildTeam(); const attachment = await buildAttachment({ @@ -119,7 +122,7 @@ describe("Team", () => { const result = await team.publicAvatarUrl(); expect(result).toEqual(await attachment.signedUrl); } finally { - jest.useRealTimers(); + vi.useRealTimers(); } }); diff --git a/server/models/User.test.ts b/server/models/User.test.ts index 7d4298e5c5..48f7b0af32 100644 --- a/server/models/User.test.ts +++ b/server/models/User.test.ts @@ -15,11 +15,12 @@ import User from "./User"; import UserMembership from "./UserMembership"; beforeAll(() => { - jest.useFakeTimers().setSystemTime(new Date("2018-01-02T00:00:00.000Z")); + vi.useFakeTimers(); + vi.setSystemTime(new Date("2018-01-02T00:00:00.000Z")); }); afterAll(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); describe("user model", () => { diff --git a/server/models/helpers/DocumentHelper.test.ts b/server/models/helpers/DocumentHelper.test.ts index e82d956b3b..8616bca215 100644 --- a/server/models/helpers/DocumentHelper.test.ts +++ b/server/models/helpers/DocumentHelper.test.ts @@ -6,12 +6,12 @@ import { DocumentHelper } from "./DocumentHelper"; describe("DocumentHelper", () => { beforeAll(() => { - jest.useFakeTimers(); - jest.setSystemTime(Date.parse("2021-01-01T00:00:00.000Z")); + vi.useFakeTimers(); + vi.setSystemTime(Date.parse("2021-01-01T00:00:00.000Z")); }); afterAll(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); describe("replaceInternalUrls", () => { diff --git a/server/models/helpers/ProseMirrorHelper.test.ts b/server/models/helpers/ProseMirrorHelper.test.ts index 0dfb697dc8..feeb3fc96a 100644 --- a/server/models/helpers/ProseMirrorHelper.test.ts +++ b/server/models/helpers/ProseMirrorHelper.test.ts @@ -7,7 +7,7 @@ import { buildProseMirrorDoc, buildUser } from "@server/test/factories"; import type { MentionAttrs } from "./ProsemirrorHelper"; import { ProsemirrorHelper } from "./ProsemirrorHelper"; -jest.mock("@server/storage/files"); +vi.mock("@server/storage/files"); describe("ProsemirrorHelper", () => { describe("processMentions", () => { diff --git a/server/models/helpers/ProsemirrorHelper.tsx b/server/models/helpers/ProsemirrorHelper.tsx index b4dddf6846..c87920cf4b 100644 --- a/server/models/helpers/ProsemirrorHelper.tsx +++ b/server/models/helpers/ProsemirrorHelper.tsx @@ -1,8 +1,12 @@ import emojiRegex from "emoji-regex"; import { JSDOM } from "jsdom"; import { chunk, isMatch } from "es-toolkit/compat"; -import { EditorState } from "prosemirror-state"; -import { EditorView } from "prosemirror-view"; +import { EditorState, type Plugin } from "prosemirror-state"; +import { + DecorationSet, + EditorView, + type DecorationSource, +} from "prosemirror-view"; import { Node, Fragment } from "prosemirror-model"; import { renderToString } from "react-dom/server"; import styled, { ServerStyleSheet, ThemeProvider } from "styled-components"; @@ -63,6 +67,30 @@ export type MentionAttrs = { unfurl?: UnfurlResponse[keyof UnfurlResponse]; }; +const pluginsWithSafeDecorations = new WeakSet(); + +function isDecorationSource(value: unknown): value is DecorationSource { + if (typeof value !== "object" || value === null) { + return false; + } + + if (!("forChild" in value) || typeof value.forChild !== "function") { + return false; + } + + if ("members" in value && Array.isArray(value.members)) { + return value.members.every( + (member) => + typeof member === "object" && + member !== null && + "localsInner" in member && + typeof member.localsInner === "function" + ); + } + + return true; +} + @trace() export class ProsemirrorHelper extends SharedProsemirrorHelper { /** @@ -513,10 +541,39 @@ export class ProsemirrorHelper extends SharedProsemirrorHelper { const diffPlugins = options?.changes ? new Diff({ changes: options.changes }).plugins : []; + const editorPlugins = [...plugins, ...diffPlugins]; + + for (const plugin of plugins) { + if ( + !plugin.props.decorations || + pluginsWithSafeDecorations.has(plugin) + ) { + continue; + } + + plugin.props.decorations = () => DecorationSet.empty; + pluginsWithSafeDecorations.add(plugin); + } + + for (const plugin of diffPlugins) { + if ( + !plugin.props.decorations || + pluginsWithSafeDecorations.has(plugin) + ) { + continue; + } + + const decorations = plugin.props.decorations.bind(plugin); + plugin.props.decorations = (state) => { + const result = decorations(state); + return isDecorationSource(result) ? result : DecorationSet.empty; + }; + pluginsWithSafeDecorations.add(plugin); + } const state = EditorState.create({ doc: node, - plugins: [...plugins, ...diffPlugins], + plugins: editorPlugins, schema, }); diff --git a/server/models/helpers/TextHelper.test.ts b/server/models/helpers/TextHelper.test.ts index 4be7e6f509..3259882332 100644 --- a/server/models/helpers/TextHelper.test.ts +++ b/server/models/helpers/TextHelper.test.ts @@ -2,7 +2,7 @@ import { createContext } from "@server/context"; import { buildProseMirrorDoc, buildUser } from "@server/test/factories"; import { ProsemirrorHelper } from "./ProsemirrorHelper"; -jest.mock("@server/storage/files"); +vi.mock("@server/storage/files"); describe("ProsemirrorHelper", () => { describe("replaceImagesWithAttachments", () => { diff --git a/server/onerror.test.ts b/server/onerror.test.ts index e1833c3467..e4c5a26577 100644 --- a/server/onerror.test.ts +++ b/server/onerror.test.ts @@ -1,20 +1,21 @@ import type Koa from "koa"; +import type { Mock } from "vitest"; import { requestErrorHandler } from "@server/logging/sentry"; import { InternalError, ValidationError, NotFoundError } from "./errors"; import onerror from "./onerror"; // Mock the requestErrorHandler from Sentry -jest.mock("@server/logging/sentry", () => ({ - requestErrorHandler: jest.fn(), +vi.mock("@server/logging/sentry", () => ({ + requestErrorHandler: vi.fn(), })); type MockCtx = { headers: Record; headerSent: boolean; writable: boolean; - accepts: jest.Mock; - set: jest.Mock; - res: { end: jest.Mock }; + accepts: Mock; + set: Mock; + res: { end: Mock }; status: number | undefined; type: string | undefined; body: unknown; @@ -43,10 +44,10 @@ describe("onerror", () => { headers: {}, headerSent: false, writable: true, - accepts: jest.fn(() => "json"), - set: jest.fn(), + accepts: vi.fn(() => "json"), + set: vi.fn(), res: { - end: jest.fn(), + end: vi.fn(), }, status: undefined, type: undefined, @@ -54,7 +55,7 @@ describe("onerror", () => { }; // Clear mock calls - (requestErrorHandler as jest.Mock).mockClear(); + (requestErrorHandler as Mock).mockClear(); }); it("should report InternalError to Sentry", () => { diff --git a/server/presenters/__snapshots__/user.test.ts.snap b/server/presenters/__snapshots__/user.test.ts.snap index 7d37fbfbaa..42152df444 100644 --- a/server/presenters/__snapshots__/user.test.ts.snap +++ b/server/presenters/__snapshots__/user.test.ts.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`presents a user 1`] = ` { diff --git a/server/queues/processors/SearchIndexProcessor.test.ts b/server/queues/processors/SearchIndexProcessor.test.ts index 0bd114adc5..c4f9186381 100644 --- a/server/queues/processors/SearchIndexProcessor.test.ts +++ b/server/queues/processors/SearchIndexProcessor.test.ts @@ -42,7 +42,7 @@ describe("SearchIndexProcessor", () => { }); const provider = SearchProviderManager.getProvider(); - const indexSpy = jest.spyOn(provider, "index"); + const indexSpy = vi.spyOn(provider, "index"); await processor.perform({ name: "documents.publish", @@ -63,7 +63,7 @@ describe("SearchIndexProcessor", () => { it("should call provider.remove for documents.permanent_delete", async () => { const user = await buildUser(); const provider = SearchProviderManager.getProvider(); - const removeSpy = jest.spyOn(provider, "remove"); + const removeSpy = vi.spyOn(provider, "remove"); await processor.perform({ name: "documents.permanent_delete", diff --git a/server/queues/processors/index.ts b/server/queues/processors/index.ts index a6758bc0cf..2ac4fee972 100644 --- a/server/queues/processors/index.ts +++ b/server/queues/processors/index.ts @@ -1,22 +1,24 @@ import { Hook, PluginManager } from "@server/utils/PluginManager"; import { requireDirectory } from "@server/utils/fs"; +import { createLazyRegistry } from "@server/utils/lazyRegistry"; import type BaseProcessor from "./BaseProcessor"; -const processors: Record = {}; - const AbstractProcessors = ["ImportsProcessor"]; -requireDirectory<{ default: typeof BaseProcessor }>(__dirname).forEach( - ([module, id]) => { - if (id === "index" || AbstractProcessors.includes(id)) { - return; +const processors = createLazyRegistry(() => { + const processors: Record = {}; + requireDirectory<{ default: typeof BaseProcessor }>(__dirname).forEach( + ([module, id]) => { + if (id === "index" || AbstractProcessors.includes(id)) { + return; + } + processors[id] = module.default; } - processors[id] = module.default; - } -); - -PluginManager.getHooks(Hook.Processor).forEach((hook) => { - processors[hook.value.name] = hook.value; + ); + PluginManager.getHooks(Hook.Processor).forEach((hook) => { + processors[hook.value.name] = hook.value; + }); + return processors; }); export default processors; diff --git a/server/queues/tasks/DocumentPublishedNotificationsTask.test.ts b/server/queues/tasks/DocumentPublishedNotificationsTask.test.ts index 2ecee51d1f..303ee09baa 100644 --- a/server/queues/tasks/DocumentPublishedNotificationsTask.test.ts +++ b/server/queues/tasks/DocumentPublishedNotificationsTask.test.ts @@ -13,12 +13,12 @@ import DocumentPublishedNotificationsTask from "./DocumentPublishedNotifications const ip = "127.0.0.1"; beforeEach(async () => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); describe("documents.publish", () => { test("should not send a notification to author", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); const document = await buildDocument({ teamId: user.teamId, @@ -40,7 +40,7 @@ describe("documents.publish", () => { }); test("should send a notification to other users in team", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); const document = await buildDocument({ teamId: user.teamId, @@ -61,7 +61,7 @@ describe("documents.publish", () => { }); test("should send only one notification in a 12-hour window", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); const document = await buildDocument({ teamId: user.teamId, @@ -98,7 +98,7 @@ describe("documents.publish", () => { }); test("should not send a notification to users without collection access", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); const collection = await buildCollection({ teamId: user.teamId, @@ -124,7 +124,7 @@ describe("documents.publish", () => { }); test("should not send a notification for group mentions when disableMentions is true", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const group = await buildGroup({ teamId: actor.teamId, diff --git a/server/queues/tasks/GroupMentionedInCommentNotificationsTask.test.ts b/server/queues/tasks/GroupMentionedInCommentNotificationsTask.test.ts index b40e00150c..d90884d971 100644 --- a/server/queues/tasks/GroupMentionedInCommentNotificationsTask.test.ts +++ b/server/queues/tasks/GroupMentionedInCommentNotificationsTask.test.ts @@ -12,12 +12,12 @@ import GroupMentionedInCommentNotificationsTask from "./GroupMentionedInCommentN const ip = "127.0.0.1"; beforeEach(async () => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); describe("GroupMentionedInCommentNotificationsTask", () => { it("should send notifications to all group members with access", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, @@ -91,7 +91,7 @@ describe("GroupMentionedInCommentNotificationsTask", () => { }); it("should not send notification to actor", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, @@ -133,7 +133,7 @@ describe("GroupMentionedInCommentNotificationsTask", () => { }); it("should not send notification if group has mentions disabled", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, @@ -177,7 +177,7 @@ describe("GroupMentionedInCommentNotificationsTask", () => { }); it("should not send notification to users without subscription", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, @@ -222,7 +222,7 @@ describe("GroupMentionedInCommentNotificationsTask", () => { }); it("should handle large groups with batching", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, @@ -269,7 +269,7 @@ describe("GroupMentionedInCommentNotificationsTask", () => { }); it("should not send notification if document does not exist", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const document = await buildDocument({ teamId: actor.teamId, diff --git a/server/queues/tasks/ImportJSONTask.test.ts b/server/queues/tasks/ImportJSONTask.test.ts index 29767dfa81..a5a752f3f2 100644 --- a/server/queues/tasks/ImportJSONTask.test.ts +++ b/server/queues/tasks/ImportJSONTask.test.ts @@ -32,7 +32,7 @@ function mockHandle(fileOperation: FileOperation) { }; }, }); - jest.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); + vi.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); } describe("ImportJSONTask", () => { diff --git a/server/queues/tasks/ImportMarkdownZipTask.test.ts b/server/queues/tasks/ImportMarkdownZipTask.test.ts index 8d010cdd80..d4bb91f3dc 100644 --- a/server/queues/tasks/ImportMarkdownZipTask.test.ts +++ b/server/queues/tasks/ImportMarkdownZipTask.test.ts @@ -22,7 +22,7 @@ describe("ImportMarkdownZipTask", () => { }; }, }); - jest.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); + vi.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); const props = { fileOperationId: fileOperation.id, @@ -53,7 +53,7 @@ describe("ImportMarkdownZipTask", () => { }; }, }); - jest.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); + vi.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); const props = { fileOperationId: fileOperation.id, @@ -84,7 +84,7 @@ describe("ImportMarkdownZipTask", () => { }; }, }); - jest.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); + vi.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); const props = { fileOperationId: fileOperation.id, @@ -118,7 +118,7 @@ describe("ImportMarkdownZipTask", () => { }; }, }); - jest.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); + vi.spyOn(FileOperation, "findByPk").mockResolvedValue(fileOperation); const props = { fileOperationId: fileOperation.id, diff --git a/server/queues/tasks/InviteReminderTask.test.ts b/server/queues/tasks/InviteReminderTask.test.ts index c1a3c15e72..dc7338ba4a 100644 --- a/server/queues/tasks/InviteReminderTask.test.ts +++ b/server/queues/tasks/InviteReminderTask.test.ts @@ -5,7 +5,7 @@ import InviteReminderTask from "./InviteReminderTask"; describe("InviteReminderTask", () => { it("should send reminder emails", async () => { - const spy = jest.spyOn(InviteReminderEmail.prototype, "schedule"); + const spy = vi.spyOn(InviteReminderEmail.prototype, "schedule"); // too old await buildInvite({ diff --git a/server/queues/tasks/RevisionCreatedNotificationsTask.test.ts b/server/queues/tasks/RevisionCreatedNotificationsTask.test.ts index 3ad9ed6d9c..d22948854b 100644 --- a/server/queues/tasks/RevisionCreatedNotificationsTask.test.ts +++ b/server/queues/tasks/RevisionCreatedNotificationsTask.test.ts @@ -23,7 +23,7 @@ import RevisionCreatedNotificationsTask from "./RevisionCreatedNotificationsTask const ip = "127.0.0.1"; beforeEach(async () => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); function updateDocumentText(document: Document, text: string) { @@ -34,7 +34,7 @@ function updateDocumentText(document: Document, text: string) { describe("revisions.create", () => { test("should send a notification to other collaborators", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); let document = await buildDocument({ teamId: user.teamId, @@ -64,7 +64,7 @@ describe("revisions.create", () => { }); test("should not send a notification if viewed since update", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); let document = await buildDocument({ teamId: user.teamId, @@ -99,7 +99,7 @@ describe("revisions.create", () => { }); test("should not send a notification to last editor", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); let document = await buildDocument({ teamId: user.teamId, @@ -125,7 +125,7 @@ describe("revisions.create", () => { }); test("should send a notification for subscriptions, even to collaborator", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); let document = await buildDocument({ teamId: user.teamId, @@ -225,7 +225,7 @@ describe("revisions.create", () => { }); test("should not send multiple emails", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const collaborator0 = await buildUser(); const collaborator1 = await buildUser({ teamId: collaborator0.teamId }); const collaborator2 = await buildUser({ teamId: collaborator0.teamId }); @@ -265,7 +265,7 @@ describe("revisions.create", () => { }); test("should not create subscriptions if previously unsubscribed", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const collaborator0 = await buildUser(); const collaborator1 = await buildUser({ teamId: collaborator0.teamId }); const collaborator2 = await buildUser({ teamId: collaborator0.teamId }); @@ -333,7 +333,7 @@ describe("revisions.create", () => { }); test("should send a notification for subscriptions to non-collaborators", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); let document = await buildDocument(); const collaborator = await buildUser({ teamId: document.teamId }); const subscriber = await buildUser({ teamId: document.teamId }); @@ -375,7 +375,7 @@ describe("revisions.create", () => { }); test("should not send a notification for subscriptions to collaborators if unsubscribed", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); let document = await buildDocument(); const collaborator = await buildUser({ teamId: document.teamId }); @@ -421,7 +421,7 @@ describe("revisions.create", () => { }); test("should not send a notification for subscriptions to members outside of the team", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); let document = await buildDocument(); const collaborator = await buildUser({ teamId: document.teamId }); @@ -470,7 +470,7 @@ describe("revisions.create", () => { }); test("should not send a notification if viewed since update", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const document = await buildDocument(); const collaborator = await buildUser({ teamId: document.teamId }); @@ -500,7 +500,7 @@ describe("revisions.create", () => { }); test("should not send a notification to last editor", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const user = await buildUser(); const document = await buildDocument({ @@ -525,7 +525,7 @@ describe("revisions.create", () => { }); test("should send a mention notification even when change is below threshold", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const mentioned = await buildUser({ teamId: actor.teamId, name: "Kim" }); @@ -590,7 +590,7 @@ describe("revisions.create", () => { }); test("should not send a notification for group mentions when disableMentions is true", async () => { - const spy = jest.spyOn(Notification, "create"); + const spy = vi.spyOn(Notification, "create"); const actor = await buildUser(); const group = await buildGroup({ teamId: actor.teamId, diff --git a/server/queues/tasks/RollupDocumentInsightsTask.test.ts b/server/queues/tasks/RollupDocumentInsightsTask.test.ts index 4c0b72d39d..1a5a45cc06 100644 --- a/server/queues/tasks/RollupDocumentInsightsTask.test.ts +++ b/server/queues/tasks/RollupDocumentInsightsTask.test.ts @@ -16,16 +16,14 @@ const props = { }, }; +vi.setConfig({ testTimeout: 30000 }); + const daysAgo = (n: number) => subDays(new Date(), n); const dayStr = (d: Date) => format(d, "yyyy-MM-dd"); describe("RollupDocumentInsightsTask", () => { let task: RollupDocumentInsightsTask; - beforeAll(() => { - jest.setTimeout(30000); - }); - beforeEach(() => { task = new RollupDocumentInsightsTask(); }); diff --git a/server/queues/tasks/ShareSubscriptionNotificationsTask.test.ts b/server/queues/tasks/ShareSubscriptionNotificationsTask.test.ts index 30ed7253b5..95f1948f69 100644 --- a/server/queues/tasks/ShareSubscriptionNotificationsTask.test.ts +++ b/server/queues/tasks/ShareSubscriptionNotificationsTask.test.ts @@ -8,12 +8,12 @@ import ShareSubscriptionNotificationsTask from "./ShareSubscriptionNotifications const ip = "127.0.0.1"; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe("ShareSubscriptionNotificationsTask", () => { it("should send email to confirmed subscriber", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -43,7 +43,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should not send email to unconfirmed subscriber", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -72,7 +72,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should not send email to unsubscribed subscriber", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -103,7 +103,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should throttle notifications to once per 6 hours", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -134,7 +134,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should send if last notified more than 6 hours ago", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -165,7 +165,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should not send for unpublished shares", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -196,7 +196,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should update lastNotifiedAt after sending", async () => { - jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -229,7 +229,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should send to multiple subscribers", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const share = await buildShare({ @@ -268,7 +268,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should not send if document has no shares", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const document = await buildDocument(); const task = new ShareSubscriptionNotificationsTask(); @@ -285,7 +285,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should send when child document is updated and subscription is scoped to parent", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const parent = await buildDocument(); const child = await buildDocument({ @@ -321,7 +321,7 @@ describe("ShareSubscriptionNotificationsTask", () => { }); it("should not send when updated document is outside subscription scope", async () => { - const spy = jest.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); + const spy = vi.spyOn(ShareDocumentUpdatedEmail.prototype, "schedule"); const parent = await buildDocument(); const sibling = await buildDocument({ diff --git a/server/queues/tasks/UpdateDocumentsPopularityScoreTask.test.ts b/server/queues/tasks/UpdateDocumentsPopularityScoreTask.test.ts index b38c5528f8..77488254c3 100644 --- a/server/queues/tasks/UpdateDocumentsPopularityScoreTask.test.ts +++ b/server/queues/tasks/UpdateDocumentsPopularityScoreTask.test.ts @@ -17,32 +17,30 @@ const props = { }, }; +vi.setConfig({ testTimeout: 30000 }); + describe("UpdateDocumentsPopularityScoreTask", () => { let task: UpdateDocumentsPopularityScoreTask; - beforeAll(() => { - jest.setTimeout(30000); - }); - beforeEach(() => { task = new UpdateDocumentsPopularityScoreTask(); - jest.spyOn(Date.prototype, "getHours").mockReturnValue(0); + vi.spyOn(Date.prototype, "getHours").mockReturnValue(0); // Ensure calculation query sees data created in tests by redirecting to main sequelize instance. // We only mock if the instances are different to avoid infinite recursion. if (sequelizeReadOnly !== sequelize) { - jest - .spyOn(sequelizeReadOnly, "query") - .mockImplementation(sequelize.query.bind(sequelize)); + vi.spyOn(sequelizeReadOnly, "query").mockImplementation( + sequelize.query.bind(sequelize) + ); } }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it("should skip execution if not at a 6-hour interval", async () => { - jest.spyOn(Date.prototype, "getHours").mockReturnValue(1); + vi.spyOn(Date.prototype, "getHours").mockReturnValue(1); const team = await buildTeam(); const document = await buildDocument({ teamId: team.id, diff --git a/server/queues/tasks/index.ts b/server/queues/tasks/index.ts index 8ebae48998..e0ae3dc84d 100644 --- a/server/queues/tasks/index.ts +++ b/server/queues/tasks/index.ts @@ -1,20 +1,22 @@ import { Hook, PluginManager } from "@server/utils/PluginManager"; import { requireDirectory } from "@server/utils/fs"; +import { createLazyRegistry } from "@server/utils/lazyRegistry"; import type { BaseTask } from "./base/BaseTask"; -const tasks: Record = {}; - -requireDirectory<{ default: typeof BaseTask }>(__dirname).forEach( - ([module, id]) => { - if (id === "index") { - return; +const tasks = createLazyRegistry(() => { + const tasks: Record = {}; + requireDirectory<{ default: typeof BaseTask }>(__dirname).forEach( + ([module, id]) => { + if (id === "index") { + return; + } + tasks[id] = module.default; } - tasks[id] = module.default; - } -); - -PluginManager.getHooks(Hook.Task).forEach((hook) => { - tasks[hook.value.name] = hook.value; + ); + PluginManager.getHooks(Hook.Task).forEach((hook) => { + tasks[hook.value.name] = hook.value; + }); + return tasks; }); export default tasks; diff --git a/server/routes/api/attachments/attachments.test.ts b/server/routes/api/attachments/attachments.test.ts index 27d052d172..a113e162cf 100644 --- a/server/routes/api/attachments/attachments.test.ts +++ b/server/routes/api/attachments/attachments.test.ts @@ -12,7 +12,7 @@ import { } from "@server/test/factories"; import { getTestServer } from "@server/test/support"; -jest.mock("@server/storage/files"); +vi.mock("@server/storage/files"); const server = getTestServer(); diff --git a/server/routes/api/auth/auth.test.ts b/server/routes/api/auth/auth.test.ts index f0cf2a1fb4..5da0e784e0 100644 --- a/server/routes/api/auth/auth.test.ts +++ b/server/routes/api/auth/auth.test.ts @@ -5,7 +5,7 @@ import { getTestServer, setSelfHosted } from "@server/test/support"; const mockTeamInSessionId = randomUUID(); -jest.mock("@server/utils/authentication", () => ({ +vi.mock("@server/utils/authentication", () => ({ getSessionsInCookie() { return { [mockTeamInSessionId]: {} }; }, diff --git a/server/routes/api/collections/__snapshots__/collections.test.ts.snap b/server/routes/api/collections/__snapshots__/collections.test.ts.snap index ff5e80de5a..d0fc65685d 100644 --- a/server/routes/api/collections/__snapshots__/collections.test.ts.snap +++ b/server/routes/api/collections/__snapshots__/collections.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#collections.add_group should require group in team 1`] = ` +exports[`#collections.add_group > should require group in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -9,7 +9,7 @@ exports[`#collections.add_group should require group in team 1`] = ` } `; -exports[`#collections.add_user should not allow add self 1`] = ` +exports[`#collections.add_user > should not allow add self 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -18,7 +18,7 @@ exports[`#collections.add_user should not allow add self 1`] = ` } `; -exports[`#collections.add_user should require user in team 1`] = ` +exports[`#collections.add_user > should require user in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -27,7 +27,7 @@ exports[`#collections.add_user should require user in team 1`] = ` } `; -exports[`#collections.create should require authentication 1`] = ` +exports[`#collections.create > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -36,7 +36,7 @@ exports[`#collections.create should require authentication 1`] = ` } `; -exports[`#collections.delete should require authentication 1`] = ` +exports[`#collections.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -45,7 +45,7 @@ exports[`#collections.delete should require authentication 1`] = ` } `; -exports[`#collections.export should require authentication 1`] = ` +exports[`#collections.export > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -54,7 +54,7 @@ exports[`#collections.export should require authentication 1`] = ` } `; -exports[`#collections.export_all should require authentication 1`] = ` +exports[`#collections.export_all > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -63,7 +63,7 @@ exports[`#collections.export_all should require authentication 1`] = ` } `; -exports[`#collections.group_memberships should require authentication 1`] = ` +exports[`#collections.group_memberships > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -72,7 +72,7 @@ exports[`#collections.group_memberships should require authentication 1`] = ` } `; -exports[`#collections.import should require authentication 1`] = ` +exports[`#collections.import > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -81,7 +81,7 @@ exports[`#collections.import should require authentication 1`] = ` } `; -exports[`#collections.info should require authentication 1`] = ` +exports[`#collections.info > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -90,7 +90,7 @@ exports[`#collections.info should require authentication 1`] = ` } `; -exports[`#collections.list should require authentication 1`] = ` +exports[`#collections.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -99,7 +99,7 @@ exports[`#collections.list should require authentication 1`] = ` } `; -exports[`#collections.memberships should require authentication 1`] = ` +exports[`#collections.memberships > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -108,7 +108,7 @@ exports[`#collections.memberships should require authentication 1`] = ` } `; -exports[`#collections.move should require authentication 1`] = ` +exports[`#collections.move > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -117,7 +117,7 @@ exports[`#collections.move should require authentication 1`] = ` } `; -exports[`#collections.remove_group should require group in team 1`] = ` +exports[`#collections.remove_group > should require group in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -126,7 +126,7 @@ exports[`#collections.remove_group should require group in team 1`] = ` } `; -exports[`#collections.remove_user should require user in team 1`] = ` +exports[`#collections.remove_user > should require user in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -135,7 +135,7 @@ exports[`#collections.remove_user should require user in team 1`] = ` } `; -exports[`#collections.update should require authentication 1`] = ` +exports[`#collections.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/comments/__snapshots__/comments.test.ts.snap b/server/routes/api/comments/__snapshots__/comments.test.ts.snap index 6e82c26bc3..77dd86e0be 100644 --- a/server/routes/api/comments/__snapshots__/comments.test.ts.snap +++ b/server/routes/api/comments/__snapshots__/comments.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#comments.add_reaction should require authentication 1`] = ` +exports[`#comments.add_reaction > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -9,7 +9,7 @@ exports[`#comments.add_reaction should require authentication 1`] = ` } `; -exports[`#comments.create should require authentication 1`] = ` +exports[`#comments.create > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -18,7 +18,7 @@ exports[`#comments.create should require authentication 1`] = ` } `; -exports[`#comments.info should require authentication 1`] = ` +exports[`#comments.info > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -27,7 +27,7 @@ exports[`#comments.info should require authentication 1`] = ` } `; -exports[`#comments.list should require authentication 1`] = ` +exports[`#comments.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -36,7 +36,7 @@ exports[`#comments.list should require authentication 1`] = ` } `; -exports[`#comments.remove_reaction should require authentication 1`] = ` +exports[`#comments.remove_reaction > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -45,7 +45,7 @@ exports[`#comments.remove_reaction should require authentication 1`] = ` } `; -exports[`#comments.resolve should require authentication 1`] = ` +exports[`#comments.resolve > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -54,7 +54,7 @@ exports[`#comments.resolve should require authentication 1`] = ` } `; -exports[`#comments.unresolve should require authentication 1`] = ` +exports[`#comments.unresolve > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -63,7 +63,7 @@ exports[`#comments.unresolve should require authentication 1`] = ` } `; -exports[`#comments.update should require authentication 1`] = ` +exports[`#comments.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/documents/__snapshots__/documents.test.ts.snap b/server/routes/api/documents/__snapshots__/documents.test.ts.snap index f982bd627e..7e3bb6a6da 100644 --- a/server/routes/api/documents/__snapshots__/documents.test.ts.snap +++ b/server/routes/api/documents/__snapshots__/documents.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#documents.create should error with invalid parentDocument 1`] = ` +exports[`#documents.create > should error with invalid parentDocument 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -9,7 +9,7 @@ exports[`#documents.create should error with invalid parentDocument 1`] = ` } `; -exports[`#documents.delete should require authentication 1`] = ` +exports[`#documents.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -18,7 +18,7 @@ exports[`#documents.delete should require authentication 1`] = ` } `; -exports[`#documents.documents should require authentication 1`] = ` +exports[`#documents.documents > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -27,7 +27,7 @@ exports[`#documents.documents should require authentication 1`] = ` } `; -exports[`#documents.documents should return 403 if user does not have access to the document 1`] = ` +exports[`#documents.documents > should return 403 if user does not have access to the document 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -36,7 +36,7 @@ exports[`#documents.documents should return 403 if user does not have access to } `; -exports[`#documents.empty_trash should not allow non-admin users 1`] = ` +exports[`#documents.empty_trash > should not allow non-admin users 1`] = ` { "error": "authorization_error", "message": "Admin role required", @@ -45,7 +45,7 @@ exports[`#documents.empty_trash should not allow non-admin users 1`] = ` } `; -exports[`#documents.empty_trash should require authentication 1`] = ` +exports[`#documents.empty_trash > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -54,7 +54,7 @@ exports[`#documents.empty_trash should require authentication 1`] = ` } `; -exports[`#documents.list should require authentication 1`] = ` +exports[`#documents.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -63,7 +63,7 @@ exports[`#documents.list should require authentication 1`] = ` } `; -exports[`#documents.restore should require authentication 1`] = ` +exports[`#documents.restore > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -72,7 +72,7 @@ exports[`#documents.restore should require authentication 1`] = ` } `; -exports[`#documents.search should require authentication 1`] = ` +exports[`#documents.search > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication error", @@ -81,7 +81,7 @@ exports[`#documents.search should require authentication 1`] = ` } `; -exports[`#documents.update should require authentication 1`] = ` +exports[`#documents.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -90,7 +90,7 @@ exports[`#documents.update should require authentication 1`] = ` } `; -exports[`#documents.update should require text while appending 1`] = ` +exports[`#documents.update > should require text while appending 1`] = ` { "error": "validation_error", "message": "text is required when using append, prepend, or editMode", @@ -99,7 +99,7 @@ exports[`#documents.update should require text while appending 1`] = ` } `; -exports[`#documents.viewed should require authentication 1`] = ` +exports[`#documents.viewed > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/documents/documents.test.ts b/server/routes/api/documents/documents.test.ts index 211445a338..1e06fe1b24 100644 --- a/server/routes/api/documents/documents.test.ts +++ b/server/routes/api/documents/documents.test.ts @@ -3335,11 +3335,11 @@ describe("#documents.import", () => { collectionId: collection.id, }); - jest - .spyOn(FileStorage, "store") - .mockResolvedValue(undefined as unknown as string); - jest.spyOn(DocumentImportTask.prototype, "schedule").mockResolvedValue({ - finished: jest.fn().mockResolvedValue({ documentId: document.id }), + vi.spyOn(FileStorage, "store").mockResolvedValue( + undefined as unknown as string + ); + vi.spyOn(DocumentImportTask.prototype, "schedule").mockResolvedValue({ + finished: vi.fn().mockResolvedValue({ documentId: document.id }), } as unknown as Awaited>); const content = await readFile( @@ -3366,7 +3366,7 @@ describe("#documents.import", () => { expect(res.status).toEqual(200); expect(body.data.id).toEqual(document.id); - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it("should require authentication", async () => { diff --git a/server/routes/api/events/__snapshots__/events.test.ts.snap b/server/routes/api/events/__snapshots__/events.test.ts.snap index 2ebdce02b5..3e20252b0d 100644 --- a/server/routes/api/events/__snapshots__/events.test.ts.snap +++ b/server/routes/api/events/__snapshots__/events.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#events.list should require authentication 1`] = ` +exports[`#events.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/fileOperations/fileOperations.test.ts b/server/routes/api/fileOperations/fileOperations.test.ts index f0b27e3e43..8902aa16f4 100644 --- a/server/routes/api/fileOperations/fileOperations.test.ts +++ b/server/routes/api/fileOperations/fileOperations.test.ts @@ -12,7 +12,7 @@ import { getTestServer } from "@server/test/support"; const server = getTestServer(); -jest.mock("@server/storage/files"); +vi.mock("@server/storage/files"); describe("#fileOperations.info", () => { it("should return fileOperation", async () => { diff --git a/server/routes/api/groups/__snapshots__/groups.test.ts.snap b/server/routes/api/groups/__snapshots__/groups.test.ts.snap index 687c4555df..a0c0f93d07 100644 --- a/server/routes/api/groups/__snapshots__/groups.test.ts.snap +++ b/server/routes/api/groups/__snapshots__/groups.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#groups.add_user should require admin 1`] = ` +exports[`#groups.add_user > should require admin 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -9,7 +9,7 @@ exports[`#groups.add_user should require admin 1`] = ` } `; -exports[`#groups.add_user should require user in team 1`] = ` +exports[`#groups.add_user > should require user in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -18,7 +18,7 @@ exports[`#groups.add_user should require user in team 1`] = ` } `; -exports[`#groups.delete should require authentication 1`] = ` +exports[`#groups.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -27,7 +27,7 @@ exports[`#groups.delete should require authentication 1`] = ` } `; -exports[`#groups.info should require authentication 1`] = ` +exports[`#groups.info > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -36,7 +36,7 @@ exports[`#groups.info should require authentication 1`] = ` } `; -exports[`#groups.list should require authentication 1`] = ` +exports[`#groups.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -45,7 +45,7 @@ exports[`#groups.list should require authentication 1`] = ` } `; -exports[`#groups.memberships should require authentication 1`] = ` +exports[`#groups.memberships > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -54,7 +54,7 @@ exports[`#groups.memberships should require authentication 1`] = ` } `; -exports[`#groups.remove_user should require admin 1`] = ` +exports[`#groups.remove_user > should require admin 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -63,7 +63,7 @@ exports[`#groups.remove_user should require admin 1`] = ` } `; -exports[`#groups.remove_user should require user in team 1`] = ` +exports[`#groups.remove_user > should require user in team 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -72,7 +72,7 @@ exports[`#groups.remove_user should require user in team 1`] = ` } `; -exports[`#groups.update should require authentication 1`] = ` +exports[`#groups.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -81,7 +81,7 @@ exports[`#groups.update should require authentication 1`] = ` } `; -exports[`#groups.update when checking for noop updates fails with validation error when name already taken 1`] = ` +exports[`#groups.update > when checking for noop updates > fails with validation error when name already taken 1`] = ` { "error": "validation_error", "message": "The name of this group is already in use (isUniqueNameInTeam)", diff --git a/server/routes/api/oauthAuthentications/__snapshots__/oauthAuthentications.test.ts.snap b/server/routes/api/oauthAuthentications/__snapshots__/oauthAuthentications.test.ts.snap index 503e418e09..5ef0a1aa23 100644 --- a/server/routes/api/oauthAuthentications/__snapshots__/oauthAuthentications.test.ts.snap +++ b/server/routes/api/oauthAuthentications/__snapshots__/oauthAuthentications.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`oauthAuthentications.delete should require authentication 1`] = ` +exports[`oauthAuthentications.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -9,7 +9,7 @@ exports[`oauthAuthentications.delete should require authentication 1`] = ` } `; -exports[`oauthAuthentications.list should require authentication 1`] = ` +exports[`oauthAuthentications.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/oauthClients/__snapshots__/oauthClients.test.ts.snap b/server/routes/api/oauthClients/__snapshots__/oauthClients.test.ts.snap index 16a23f4362..89f9c8f5fc 100644 --- a/server/routes/api/oauthClients/__snapshots__/oauthClients.test.ts.snap +++ b/server/routes/api/oauthClients/__snapshots__/oauthClients.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`oauthClients.create should require authentication 1`] = ` +exports[`oauthClients.create > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -9,7 +9,7 @@ exports[`oauthClients.create should require authentication 1`] = ` } `; -exports[`oauthClients.delete should require authentication 1`] = ` +exports[`oauthClients.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -18,7 +18,7 @@ exports[`oauthClients.delete should require authentication 1`] = ` } `; -exports[`oauthClients.info should require authentication 1`] = ` +exports[`oauthClients.info > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -27,7 +27,7 @@ exports[`oauthClients.info should require authentication 1`] = ` } `; -exports[`oauthClients.list should require authentication 1`] = ` +exports[`oauthClients.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -36,7 +36,7 @@ exports[`oauthClients.list should require authentication 1`] = ` } `; -exports[`oauthClients.rotate_secret should require authentication 1`] = ` +exports[`oauthClients.rotate_secret > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -45,7 +45,7 @@ exports[`oauthClients.rotate_secret should require authentication 1`] = ` } `; -exports[`oauthclients.update should require authentication 1`] = ` +exports[`oauthclients.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/reactions/__snapshots__/reactions.test.ts.snap b/server/routes/api/reactions/__snapshots__/reactions.test.ts.snap index 96e669d425..0461f04bbc 100644 --- a/server/routes/api/reactions/__snapshots__/reactions.test.ts.snap +++ b/server/routes/api/reactions/__snapshots__/reactions.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#reactions.list should require authentication 1`] = ` +exports[`#reactions.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/shares/__snapshots__/shares.test.ts.snap b/server/routes/api/shares/__snapshots__/shares.test.ts.snap index d4d1d69ec0..8ec8db09df 100644 --- a/server/routes/api/shares/__snapshots__/shares.test.ts.snap +++ b/server/routes/api/shares/__snapshots__/shares.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#shares.create should require authentication 1`] = ` +exports[`#shares.create > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -9,7 +9,7 @@ exports[`#shares.create should require authentication 1`] = ` } `; -exports[`#shares.list should require authentication 1`] = ` +exports[`#shares.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -18,7 +18,7 @@ exports[`#shares.list should require authentication 1`] = ` } `; -exports[`#shares.revoke should require authentication 1`] = ` +exports[`#shares.revoke > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -27,7 +27,7 @@ exports[`#shares.revoke should require authentication 1`] = ` } `; -exports[`#shares.update should require authentication 1`] = ` +exports[`#shares.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/urls/urls.test.ts b/server/routes/api/urls/urls.test.ts index b20a8b5557..dd41ceeed5 100644 --- a/server/routes/api/urls/urls.test.ts +++ b/server/routes/api/urls/urls.test.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { UnfurlResourceType } from "@shared/types"; import env from "@server/env"; import type { User } from "@server/models"; @@ -10,22 +11,38 @@ import { import { getTestServer } from "@server/test/support"; import Iframely from "plugins/iframely/server/iframely"; -jest.mock("dns", () => ({ - resolveCname: ( - input: string, - callback: (err: Error | null, addresses: string[]) => void - ) => { - if (input.includes("valid.custom.domain")) { - callback(null, ["secure.outline.dev"]); - } else { +const resolveCname = vi.hoisted( + () => + ( + input: string, + callback: (err: Error | null, addresses: string[]) => void + ) => { + if (input.includes("valid.custom.domain")) { + callback(null, ["secure.outline.dev"]); + return; + } + callback(null, []); } +); + +vi.mock("node:dns", () => ({ + default: { + resolveCname, }, + resolveCname, })); -jest - .spyOn(Iframely, "requestResource") - .mockImplementation(() => Promise.resolve({})); +vi.mock("dns", () => ({ + default: { + resolveCname, + }, + resolveCname, +})); + +vi.spyOn(Iframely, "requestResource").mockImplementation(() => + Promise.resolve({}) +); const server = getTestServer(); @@ -287,7 +304,7 @@ describe("#urls.unfurl", () => { }); it("should succeed with status 200 ok for a valid external url", async () => { - (Iframely.requestResource as jest.Mock).mockResolvedValue( + (Iframely.requestResource as Mock).mockResolvedValue( Promise.resolve({ url: "https://www.flickr.com", type: "rich", @@ -343,7 +360,7 @@ describe("#urls.unfurl", () => { }); it("should succeed with status 204 no content for a non-existing external url", async () => { - (Iframely.requestResource as jest.Mock).mockResolvedValue( + (Iframely.requestResource as Mock).mockResolvedValue( Promise.resolve({ status: 404, error: diff --git a/server/routes/api/users/__snapshots__/users.test.ts.snap b/server/routes/api/users/__snapshots__/users.test.ts.snap index 6f7d5b30e9..8fdcb7623b 100644 --- a/server/routes/api/users/__snapshots__/users.test.ts.snap +++ b/server/routes/api/users/__snapshots__/users.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#users.activate should require admin 1`] = ` +exports[`#users.activate > should require admin 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -9,7 +9,7 @@ exports[`#users.activate should require admin 1`] = ` } `; -exports[`#users.delete should require authentication 1`] = ` +exports[`#users.delete > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -18,7 +18,7 @@ exports[`#users.delete should require authentication 1`] = ` } `; -exports[`#users.demote should not allow demoting self 1`] = ` +exports[`#users.demote > should not allow demoting self 1`] = ` { "error": "validation_error", "message": "You cannot change your own role", @@ -27,7 +27,7 @@ exports[`#users.demote should not allow demoting self 1`] = ` } `; -exports[`#users.demote should require admin 1`] = ` +exports[`#users.demote > should require admin 1`] = ` { "error": "authorization_error", "message": "Admin role required", @@ -36,7 +36,7 @@ exports[`#users.demote should require admin 1`] = ` } `; -exports[`#users.promote should require admin 1`] = ` +exports[`#users.promote > should require admin 1`] = ` { "error": "authorization_error", "message": "Admin role required", @@ -45,7 +45,7 @@ exports[`#users.promote should require admin 1`] = ` } `; -exports[`#users.suspend should not allow suspending self 1`] = ` +exports[`#users.suspend > should not allow suspending self 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -54,7 +54,7 @@ exports[`#users.suspend should not allow suspending self 1`] = ` } `; -exports[`#users.suspend should require admin 1`] = ` +exports[`#users.suspend > should require admin 1`] = ` { "error": "authorization_error", "message": "Authorization error", @@ -63,7 +63,7 @@ exports[`#users.suspend should require admin 1`] = ` } `; -exports[`#users.update should require authentication 1`] = ` +exports[`#users.update > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -72,7 +72,7 @@ exports[`#users.update should require authentication 1`] = ` } `; -exports[`#users.updateEmail post should fail if email not in allowed domains 1`] = ` +exports[`#users.updateEmail > post > should fail if email not in allowed domains 1`] = ` { "error": "validation_error", "message": "The domain is not allowed for this workspace", @@ -81,7 +81,7 @@ exports[`#users.updateEmail post should fail if email not in allowed domains 1`] } `; -exports[`#users.updateEmail post should fail if email not unique in workspace 1`] = ` +exports[`#users.updateEmail > post > should fail if email not unique in workspace 1`] = ` { "error": "validation_error", "message": "User with email already exists", @@ -90,7 +90,7 @@ exports[`#users.updateEmail post should fail if email not unique in workspace 1` } `; -exports[`#users.updateEmail post should require authentication 1`] = ` +exports[`#users.updateEmail > post > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/routes/api/users/users.test.ts b/server/routes/api/users/users.test.ts index f5759a0ad5..998512ae88 100644 --- a/server/routes/api/users/users.test.ts +++ b/server/routes/api/users/users.test.ts @@ -14,10 +14,10 @@ import { getTestServer } from "@server/test/support"; const server = getTestServer(); beforeAll(() => { - jest.useFakeTimers().setSystemTime(new Date("2018-01-02T00:00:00.000Z")); + vi.useFakeTimers().setSystemTime(new Date("2018-01-02T00:00:00.000Z")); }); afterAll(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); describe("#users.list", () => { @@ -766,7 +766,7 @@ describe("#users.update", () => { describe("#users.updateEmail", () => { describe("post", () => { it("should trigger verification email", async () => { - const spy = jest.spyOn(ConfirmUpdateEmail.prototype, "schedule"); + const spy = vi.spyOn(ConfirmUpdateEmail.prototype, "schedule"); const user = await buildUser(); const res = await server.post("/api/users.updateEmail", { body: { diff --git a/server/routes/api/views/__snapshots__/views.test.ts.snap b/server/routes/api/views/__snapshots__/views.test.ts.snap index 495d7d596f..c14a6dc984 100644 --- a/server/routes/api/views/__snapshots__/views.test.ts.snap +++ b/server/routes/api/views/__snapshots__/views.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`#views.create should require authentication 1`] = ` +exports[`#views.create > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", @@ -9,7 +9,7 @@ exports[`#views.create should require authentication 1`] = ` } `; -exports[`#views.list should require authentication 1`] = ` +exports[`#views.list > should require authentication 1`] = ` { "error": "authentication_required", "message": "Authentication required", diff --git a/server/storage/database.ts b/server/storage/database.ts index f533fa6296..75de980358 100644 --- a/server/storage/database.ts +++ b/server/storage/database.ts @@ -233,10 +233,6 @@ export function createMigrationRunner( * See https://github.com/sequelize/sequelize/issues/14807#issuecomment-1854398131 */ export function monkeyPatchSequelizeErrorsForJest(instance: Sequelize) { - if (typeof jest === "undefined") { - return instance; - } - const sequelizeVersion = (Sequelize as unknown as { version: string }) .version; const major = sequelizeVersion.split(".").map(Number)[0]; diff --git a/server/storage/files/__mocks__/index.ts b/server/storage/files/__mocks__/index.ts index 0c8716df87..7c81325c4a 100644 --- a/server/storage/files/__mocks__/index.ts +++ b/server/storage/files/__mocks__/index.ts @@ -1,11 +1,13 @@ +import { vi } from "vitest"; + export default { - upload: jest.fn().mockReturnValue("/endpoint/key"), + upload: vi.fn().mockReturnValue("/endpoint/key"), - getUploadUrl: jest.fn().mockReturnValue("http://mock/create"), + getUploadUrl: vi.fn().mockReturnValue("http://mock/create"), - getUrlForKey: jest.fn().mockReturnValue("http://mock/get"), + getUrlForKey: vi.fn().mockReturnValue("http://mock/get"), - getSignedUrl: jest.fn().mockReturnValue("http://s3mock"), + getSignedUrl: vi.fn().mockReturnValue("http://s3mock"), - getPresignedPost: jest.fn().mockReturnValue({}), + getPresignedPost: vi.fn().mockReturnValue({}), }; diff --git a/server/test/globalTeardown.js b/server/test/globalTeardown.js deleted file mode 100644 index 8118405998..0000000000 --- a/server/test/globalTeardown.js +++ /dev/null @@ -1,7 +0,0 @@ -import { sequelize } from "@server/storage/database"; - -module.exports = async function (opts) { - if (!opts.watch && !opts.watchAll) { - await sequelize.close(); - } -}; diff --git a/server/test/globalTeardown.ts b/server/test/globalTeardown.ts new file mode 100644 index 0000000000..b247862908 --- /dev/null +++ b/server/test/globalTeardown.ts @@ -0,0 +1,6 @@ +export default function setup() { + return async () => { + const { sequelize } = await import("@server/storage/database"); + await sequelize.close(); + }; +} diff --git a/server/test/msw.ts b/server/test/msw.ts new file mode 100644 index 0000000000..5af89d06cd --- /dev/null +++ b/server/test/msw.ts @@ -0,0 +1,11 @@ +import { http, passthrough } from "msw"; +import { setupServer } from "msw/node"; + +// Pass-through handlers for in-process supertest requests. Registered as +// initial handlers so they survive server.resetHandlers() between tests. +const passthroughLocalhost = http.all( + /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?(\/|$)/, + () => passthrough() +); + +export const server = setupServer(passthroughLocalhost); diff --git a/server/test/setup.ts b/server/test/setup.ts index 9bdea08dbe..c9e3f2bba8 100644 --- a/server/test/setup.ts +++ b/server/test/setup.ts @@ -1,55 +1,60 @@ import "reflect-metadata"; +import { EventEmitter } from "node:events"; +import { afterAll, afterEach, beforeAll, beforeEach, vi } from "vitest"; import sharedEnv from "@shared/env"; import env from "@server/env"; -import { EventEmitter } from "node:events"; +import { server } from "./msw"; + +beforeAll(() => server.listen({ onUnhandledRequest: "error" })); +afterEach(() => server.resetHandlers()); +afterAll(() => server.close()); // Increase the default max listeners for EventEmitter to prevent warnings in tests // This needs to be done before any modules that use EventEmitter are loaded EventEmitter.defaultMaxListeners = 100; -// Save native Response/Request before jest-fetch-mock replaces them with -// cross-fetch polyfills that don't support Web Streams (e.g. ReadableStream -// bodies lose their getReader method). The MCP SDK's @hono/node-server adapter -// depends on proper Web Streams support. -const NativeResponse = globalThis.Response; -const NativeRequest = globalThis.Request; -const NativeHeaders = globalThis.Headers; - -// Enable fetch mocks for testing -require("jest-fetch-mock").enableMocks(); -fetchMock.dontMock(); - -// Restore native Web API classes -globalThis.Response = NativeResponse; -globalThis.Request = NativeRequest; -globalThis.Headers = NativeHeaders; - // Mock AWS SDK S3 client and related commands -jest.mock("@aws-sdk/client-s3", () => ({ - S3Client: jest.fn(() => ({ - send: jest.fn(), +vi.mock("@aws-sdk/client-s3", () => ({ + S3Client: vi.fn(() => ({ + send: vi.fn(), })), - DeleteObjectCommand: jest.fn(), - GetObjectCommand: jest.fn(), + DeleteObjectCommand: vi.fn(), + GetObjectCommand: vi.fn(), ObjectCannedACL: {}, })); -jest.mock("@aws-sdk/lib-storage", () => ({ - Upload: jest.fn(() => ({ - done: jest.fn(), +vi.mock("@aws-sdk/lib-storage", () => ({ + Upload: vi.fn(() => ({ + done: vi.fn(), })), })); -jest.mock("@aws-sdk/s3-presigned-post", () => ({ - createPresignedPost: jest.fn(), +vi.mock("@aws-sdk/s3-presigned-post", () => ({ + createPresignedPost: vi.fn(), })); -jest.mock("@aws-sdk/s3-request-presigner", () => ({ - getSignedUrl: jest.fn(), +vi.mock("@aws-sdk/s3-request-presigner", () => ({ + getSignedUrl: vi.fn(), })); -// Initialize the database models -require("@server/storage/database"); +// Initialize the database models. Loaded dynamically so the +// EventEmitter.defaultMaxListeners assignment above runs first; static imports +// would be hoisted ahead of it. +await import("@server/storage/database"); + +// Eagerly load plugin server entry points so that PluginManager.getHooks() +// returns the registered plugins. Vitest does not support require() of TS +// files with bare imports (e.g. `@server/...`), so we use Vite's +// import.meta.glob to load them through the Vite resolver instead. +const { PluginManager } = await import("@server/utils/PluginManager"); +const pluginModules = import.meta.glob( + "../../plugins/*/server/!(*.test|schema).{js,ts}", + { eager: true } +); +void pluginModules; +// Mark as loaded so PluginManager.loadPlugins() (which uses require()) is a +// no-op during tests. +(PluginManager as unknown as { loaded: boolean }).loaded = true; beforeEach(() => { env.URL = sharedEnv.URL = "https://app.outline.dev"; diff --git a/server/test/setupMocks.js b/server/test/setupMocks.js deleted file mode 100644 index 56ab55d1ed..0000000000 --- a/server/test/setupMocks.js +++ /dev/null @@ -1,11 +0,0 @@ -// This file runs before the test environment is set up to ensure mocks are registered early -// It prevents real Redis clients from being initialized during module imports - -// Mock ioredis with ioredis-mock before any imports -jest.mock("ioredis", () => require("ioredis-mock")); - -// Mock other Redis-dependent modules -jest.mock("@server/utils/MutexLock"); - -// Mock AWS SDK signature module to prevent aws_logger open handle -jest.mock("@aws-sdk/signature-v4-crt", () => ({})); diff --git a/server/test/setupMocks.ts b/server/test/setupMocks.ts new file mode 100644 index 0000000000..b328deb3a2 --- /dev/null +++ b/server/test/setupMocks.ts @@ -0,0 +1,56 @@ +// This file runs before the test environment is set up to ensure mocks are registered early. +// It prevents real Redis clients from being initialized during module imports. + +import { vi } from "vitest"; +import type * as IORedisMock from "ioredis-mock"; +import { __setRequireDirectoryCache } from "@server/utils/fs"; + +// Pre-populate the requireDirectory cache used by @server/utils/fs so that +// tasks/processors/email-templates can be looked up via their pre-loaded +// modules instead of via Node's require(), which cannot resolve TypeScript +// files with aliased imports under Vitest. The eager globs intentionally +// exclude index.ts files (which call requireDirectory themselves and would +// recurse) and any files whose imports would themselves load the directory +// they live in. +__setRequireDirectoryCache( + "emails/templates", + import.meta.glob("../emails/templates/!(index|*.test).{js,ts}", { + eager: true, + }) +); +__setRequireDirectoryCache( + "queues/processors", + import.meta.glob("../queues/processors/!(index|*.test).{js,ts}", { + eager: true, + }) +); +__setRequireDirectoryCache( + "queues/tasks", + import.meta.glob("../queues/tasks/!(index|*.test).{js,ts}", { + eager: true, + }) +); + +vi.mock("ioredis", async () => { + const mod = await vi.importActual("ioredis-mock"); + return mod; +}); + +vi.mock("@server/utils/MutexLock"); + +vi.mock("@aws-sdk/signature-v4-crt", () => ({})); + +// Auto-mock these modules using the corresponding files under server/__mocks__/. +// In Jest, __mocks__ next to a `roots` directory is auto-applied; vitest +// requires an explicit vi.mock() call to wire them up. +vi.mock("bull", () => import("../__mocks__/bull")); +vi.mock("dd-trace", async () => { + const mod = await import("../__mocks__/dd-trace"); + return { default: mod.mockTracer, ...mod }; +}); +vi.mock("franc", () => import("../__mocks__/franc")); +vi.mock("iso-639-3", () => import("../__mocks__/iso-639-3")); +vi.mock( + "request-filtering-agent", + () => import("../__mocks__/request-filtering-agent") +); diff --git a/server/test/support.ts b/server/test/support.ts index f2a1afbd5e..747e86538e 100644 --- a/server/test/support.ts +++ b/server/test/support.ts @@ -1,10 +1,12 @@ import { faker } from "@faker-js/faker"; import type { Transaction } from "sequelize"; +import { afterEach, beforeEach, vi } from "vitest"; import sharedEnv from "@shared/env"; import { createContext } from "@server/context"; import env from "@server/env"; import type { User } from "@server/models"; import onerror from "@server/onerror"; +import { BaseTask } from "@server/queues/tasks/base/BaseTask"; import webService from "@server/services/web"; import { sequelize } from "@server/storage/database"; import type { APIContext } from "@server/types"; @@ -33,6 +35,26 @@ export function setSelfHosted() { env.URL = sharedEnv.URL = `https://${faker.internet.domainName()}`; } +/** + * Mock scheduling for all task subclasses in the current test file. + * + * @returns the schedule mock for assertions. + */ +export function mockTaskSchedule() { + const schedule = vi.fn["schedule"]>(); + + beforeEach(() => { + schedule.mockReset(); + vi.spyOn(BaseTask.prototype, "schedule").mockImplementation(schedule); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + return schedule; +} + export function withAPIContext( user: User, fn: (ctx: APIContext) => T diff --git a/server/utils/__mocks__/MutexLock.ts b/server/utils/__mocks__/MutexLock.ts index bf843901b0..2e1a5f9af5 100644 --- a/server/utils/__mocks__/MutexLock.ts +++ b/server/utils/__mocks__/MutexLock.ts @@ -1,14 +1,29 @@ +import { vi } from "vitest"; + export class MutexLock { // Default expiry time for acquiring lock in milliseconds public static defaultLockTimeout = 4000; + /** + * Acquires a mock lock. + */ + public static acquire = vi.fn().mockResolvedValue({ + release: vi.fn().mockResolvedValue(true), + expiration: Date.now() + 10000, + }); + + /** + * Releases a mock lock. + */ + public static release = vi.fn().mockResolvedValue(true); + /** * Returns the mock redlock instance */ public static get lock() { return { - acquire: jest.fn().mockResolvedValue({ - release: jest.fn().mockResolvedValue(true), + acquire: vi.fn().mockResolvedValue({ + release: vi.fn().mockResolvedValue(true), expiration: Date.now() + 10000, }), }; diff --git a/server/utils/embeds.test.ts b/server/utils/embeds.test.ts index a04210c55a..7eec9c00bd 100644 --- a/server/utils/embeds.test.ts +++ b/server/utils/embeds.test.ts @@ -1,9 +1,24 @@ -import fetchMock from "jest-fetch-mock"; +import { http, HttpResponse } from "msw"; +import { server } from "@server/test/msw"; import { checkEmbeddability, convertBareUrlsToEmbedMarkdown } from "./embeds"; -beforeEach(() => { - fetchMock.resetMocks(); -}); +const embedUrl = "https://www.example.com/embed"; + +const mockEmbedResponse = ( + url: string, + init: { status?: number; headers?: Record } = {} +) => { + server.use( + http.get( + url, + () => + new HttpResponse(null, { + status: init.status ?? 200, + headers: init.headers ?? {}, + }) + ) + ); +}; describe("checkEmbeddability", () => { describe("when URL doesn't match any embed pattern", () => { @@ -21,55 +36,48 @@ describe("checkEmbeddability", () => { describe("when URL matches an embed pattern", () => { it("should return embeddable: true when no restrictive headers", async () => { - fetchMock.mockResponseOnce("", { - status: 200, - headers: {}, - }); + mockEmbedResponse(embedUrl); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: true }); }); it("should return embeddable: false when X-Frame-Options: DENY", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "X-Frame-Options": "DENY" }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "x-frame-options" }); }); it("should return embeddable: false when X-Frame-Options: SAMEORIGIN", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "X-Frame-Options": "SAMEORIGIN" }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "x-frame-options" }); }); it("should return embeddable: false when X-Frame-Options: ALLOW-FROM", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "X-Frame-Options": "ALLOW-FROM https://example.com" }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "x-frame-options" }); }); it("should return embeddable: false when CSP frame-ancestors is 'none'", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Content-Security-Policy": "default-src 'self'; frame-ancestors 'none'", }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "csp-frame-ancestors", @@ -77,14 +85,13 @@ describe("checkEmbeddability", () => { }); it("should return embeddable: false when CSP frame-ancestors is 'self'", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Content-Security-Policy": "frame-ancestors 'self'", }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "csp-frame-ancestors", @@ -92,26 +99,24 @@ describe("checkEmbeddability", () => { }); it("should return embeddable: true when CSP frame-ancestors is *", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Content-Security-Policy": "frame-ancestors *", }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: true }); }); it("should return embeddable: false when CSP frame-ancestors has specific origins", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Content-Security-Policy": "frame-ancestors https://allowed-site.com", }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "csp-frame-ancestors", @@ -119,60 +124,52 @@ describe("checkEmbeddability", () => { }); it("should return embeddable: false when COEP is require-corp", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Cross-Origin-Embedder-Policy": "require-corp" }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: false, reason: "coep" }); }); it("should return embeddable: true when COEP is unsafe-none", async () => { - fetchMock.mockResponseOnce("", { - status: 200, + mockEmbedResponse(embedUrl, { headers: { "Cross-Origin-Embedder-Policy": "unsafe-none" }, }); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: true }); }); it("should return embeddable: false when server returns 403", async () => { - fetchMock.mockResponseOnce("", { - status: 403, - headers: {}, - }); + const url = "https://www.example.com/forbiddenpage"; + mockEmbedResponse(url, { status: 403 }); - const result = await checkEmbeddability( - "https://www.example.com/forbiddenpage" - ); + const result = await checkEmbeddability(url); expect(result).toEqual({ embeddable: false, reason: "http-error" }); }); it("should return embeddable: false when server returns 404", async () => { - fetchMock.mockResponseOnce("", { - status: 404, - headers: {}, - }); + const url = "https://www.example.com/nonexistentpage"; + mockEmbedResponse(url, { status: 404 }); - const result = await checkEmbeddability( - "https://www.example.com/nonexistentpage" - ); + const result = await checkEmbeddability(url); expect(result).toEqual({ embeddable: false, reason: "http-error" }); }); it("should return embeddable: true on timeout (optimistic)", async () => { - fetchMock.mockAbortOnce(); + // Network errors and aborts both land in the catch branch and return + // { embeddable: true, reason: "timeout" }. + server.use(http.get(embedUrl, () => HttpResponse.error())); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: true, reason: "timeout" }); }); it("should return embeddable: true on network error (optimistic)", async () => { - fetchMock.mockRejectOnce(new Error("Network error")); + server.use(http.get(embedUrl, () => HttpResponse.error())); - const result = await checkEmbeddability("https://www.example.com/embed"); + const result = await checkEmbeddability(embedUrl); expect(result).toEqual({ embeddable: true, reason: "timeout" }); }); }); diff --git a/server/utils/fs.ts b/server/utils/fs.ts index 226ae4bb9c..a9db935eff 100644 --- a/server/utils/fs.ts +++ b/server/utils/fs.ts @@ -112,6 +112,25 @@ export function getFilenamesInDirectory(dirName: string): string[] { ); } +// Optional cache used in tests, where Node's require() cannot resolve +// TypeScript files with aliased imports. Populated by the test setup with +// modules pre-loaded via Vite's import.meta.glob, keyed by directory suffix. +const requireDirectoryCache = new Map>(); + +/** + * Pre-populate requireDirectory's module cache. Intended for use only by the + * Vitest test setup; production code should not call this. + * + * @param suffix The directory path suffix to match against. + * @param modules The eagerly-loaded modules. + */ +export function __setRequireDirectoryCache( + suffix: string, + modules: Record +): void { + requireDirectoryCache.set(suffix, modules); +} + /** * Require all files in a directory and return them as an array of tuples. * @@ -119,6 +138,22 @@ export function getFilenamesInDirectory(dirName: string): string[] { * @returns An array of tuples containing the required files and their names. */ export function requireDirectory(dirName: string): [T, string][] { + for (const [suffix, modules] of requireDirectoryCache) { + if (dirName.endsWith(suffix)) { + return Object.entries(modules) + .filter( + ([filePath]) => + !filePath.endsWith("/index.ts") && + !filePath.endsWith("/index.js") && + !filePath.includes(".test.") + ) + .map(([filePath, mod]) => { + const base = filePath.split("/").pop() ?? filePath; + const id = base.replace(/\.[jt]s$/, ""); + return [mod as T, id]; + }); + } + } return getFilenamesInDirectory(dirName).map((fileName) => { const filePath = path.join(dirName, fileName); const name = path.basename(filePath.replace(/\.[jt]s$/, "")); diff --git a/server/utils/getInstallationInfo.test.ts b/server/utils/getInstallationInfo.test.ts index 7b3c3d03a3..7487d20739 100644 --- a/server/utils/getInstallationInfo.test.ts +++ b/server/utils/getInstallationInfo.test.ts @@ -1,9 +1,9 @@ -import fetchMock from "jest-fetch-mock"; +import { http, HttpResponse } from "msw"; +import { server } from "@server/test/msw"; import { getVersionInfo, getVersion } from "./getInstallationInfo"; -beforeEach(() => { - fetchMock.resetMocks(); -}); +const dockerHubUrl = + "https://hub.docker.com/v2/repositories/outlinewiki/outline/tags"; describe("getVersion", () => { it("should return the current version", () => { @@ -17,11 +17,13 @@ describe("getVersionInfo", () => { const currentVersion = "0.80.0"; it("should return version info when Docker Hub is accessible", async () => { - fetchMock.mockResponseOnce( - JSON.stringify({ - results: [{ name: "0.81.0" }, { name: "0.80.0" }, { name: "0.79.0" }], - next: null, - }) + server.use( + http.get(dockerHubUrl, () => + HttpResponse.json({ + results: [{ name: "0.81.0" }, { name: "0.80.0" }, { name: "0.79.0" }], + next: null, + }) + ) ); const result = await getVersionInfo(currentVersion); @@ -33,7 +35,7 @@ describe("getVersionInfo", () => { }); it("should return fallback values when Docker Hub is unreachable", async () => { - fetchMock.mockRejectOnce(new Error("Network request failed")); + server.use(http.get(dockerHubUrl, () => HttpResponse.error())); const result = await getVersionInfo(currentVersion); @@ -44,7 +46,7 @@ describe("getVersionInfo", () => { }); it("should return fallback values when fetch times out", async () => { - fetchMock.mockRejectOnce(new Error("Request timeout after 10000ms")); + server.use(http.get(dockerHubUrl, () => HttpResponse.error())); const result = await getVersionInfo(currentVersion); @@ -55,7 +57,7 @@ describe("getVersionInfo", () => { }); it("should return fallback values when DNS lookup fails", async () => { - fetchMock.mockRejectOnce(new Error("DNS lookup failed")); + server.use(http.get(dockerHubUrl, () => HttpResponse.error())); const result = await getVersionInfo(currentVersion); @@ -66,7 +68,12 @@ describe("getVersionInfo", () => { }); it("should return fallback values when response is not JSON", async () => { - fetchMock.mockResponseOnce("Not JSON"); + server.use( + http.get( + dockerHubUrl, + () => new HttpResponse("Not JSON", { status: 200 }) + ) + ); const result = await getVersionInfo(currentVersion); diff --git a/server/utils/lazyRegistry.ts b/server/utils/lazyRegistry.ts new file mode 100644 index 0000000000..c20f71396a --- /dev/null +++ b/server/utils/lazyRegistry.ts @@ -0,0 +1,40 @@ +/** + * Create a lazily-loaded object registry. The loader runs only when the + * registry is first accessed. + * + * @param load A function that returns the registry contents. + * @returns A proxy that exposes the lazily-loaded registry. + */ +export function createLazyRegistry( + load: () => Record +): Record { + let cache: Record | undefined; + + const getRegistry = () => { + if (cache) { + return cache; + } + + cache = load(); + return cache; + }; + + return new Proxy({} as Record, { + get(_target, prop: string | symbol) { + if (typeof prop === "symbol") { + return undefined; + } + + return getRegistry()[prop]; + }, + has(_target, prop: string | symbol) { + return typeof prop === "string" && prop in getRegistry(); + }, + ownKeys() { + return Reflect.ownKeys(getRegistry()); + }, + getOwnPropertyDescriptor(_target, prop: string | symbol) { + return Reflect.getOwnPropertyDescriptor(getRegistry(), prop); + }, + }); +} diff --git a/server/utils/oauth.test.ts b/server/utils/oauth.test.ts index 03ac31fc7e..eb47b9174f 100644 --- a/server/utils/oauth.test.ts +++ b/server/utils/oauth.test.ts @@ -1,4 +1,5 @@ -import fetchMock from "jest-fetch-mock"; +import { http, HttpResponse } from "msw"; +import { server } from "@server/test/msw"; import OAuthClient from "./oauth"; class MinimalOAuthClient extends OAuthClient { @@ -9,16 +10,15 @@ class MinimalOAuthClient extends OAuthClient { }; } -beforeEach(() => { - fetchMock.resetMocks(); -}); - describe("userInfo", () => { it("should work with empty-body 401 Unauthorized responses", async () => { - fetchMock.mockResponseOnce("", { - status: 401, - statusText: "unauthorized", - }); + server.use( + http.get( + "http://example.com/userinfo", + () => + new HttpResponse(null, { status: 401, statusText: "unauthorized" }) + ) + ); const client = new MinimalOAuthClient("clientid", "clientsecret"); try { diff --git a/server/utils/parseAttachmentIds.test.ts b/server/utils/parseAttachmentIds.test.ts index 6508bb6ec1..906851ab82 100644 --- a/server/utils/parseAttachmentIds.test.ts +++ b/server/utils/parseAttachmentIds.test.ts @@ -1,4 +1,3 @@ -import { expect } from "@jest/globals"; import { randomUUID } from "node:crypto"; import env from "@server/env"; import parseAttachmentIds from "./parseAttachmentIds"; diff --git a/server/utils/url.test.ts b/server/utils/url.test.ts index cb37632ae4..132a221997 100644 --- a/server/utils/url.test.ts +++ b/server/utils/url.test.ts @@ -1,12 +1,13 @@ import dns from "node:dns"; +import type { MockInstance } from "vitest"; import env from "@server/env"; import { validateUrlNotPrivate } from "./url"; describe("validateUrlNotPrivate", () => { - let lookupSpy: jest.SpyInstance; + let lookupSpy: MockInstance; beforeEach(() => { - lookupSpy = jest + lookupSpy = vi .spyOn(dns.promises, "lookup") .mockResolvedValue({ address: "93.184.216.34", family: 4 }); }); diff --git a/server/utils/validators.test.ts b/server/utils/validators.test.ts index 841cb0f5b7..6416b316b3 100644 --- a/server/utils/validators.test.ts +++ b/server/utils/validators.test.ts @@ -1,4 +1,3 @@ -import { describe, it, expect } from "@jest/globals"; import { isDatabaseUrl, isMailboxAddress } from "./validators"; describe("isDatabaseUrl", () => { diff --git a/shared/test/setup.ts b/shared/test/setup.ts index df86846314..e3309427fb 100644 --- a/shared/test/setup.ts +++ b/shared/test/setup.ts @@ -1,3 +1,5 @@ -jest.mock("i18next-http-backend"); +import { vi } from "vitest"; + +vi.mock("i18next-http-backend"); export {}; diff --git a/shared/utils/TextHelper.test.ts b/shared/utils/TextHelper.test.ts index e1e2ddca97..bdbbab52ed 100644 --- a/shared/utils/TextHelper.test.ts +++ b/shared/utils/TextHelper.test.ts @@ -2,12 +2,12 @@ import { TextHelper } from "./TextHelper"; describe("TextHelper", () => { beforeAll(() => { - jest.useFakeTimers(); - jest.setSystemTime(Date.parse("2021-01-01T00:00:00.000Z")); + vi.useFakeTimers(); + vi.setSystemTime(Date.parse("2021-01-01T00:00:00.000Z")); }); afterAll(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); describe("replaceTemplateVariables", () => { diff --git a/shared/utils/files.test.ts b/shared/utils/files.test.ts index ec45b52ff6..efac48d6b0 100644 --- a/shared/utils/files.test.ts +++ b/shared/utils/files.test.ts @@ -3,7 +3,7 @@ import { bytesToHumanReadable, getFileNameFromUrl } from "./files"; // Mock the browser detection with a mutable value let mockIsMacValue = false; -jest.mock("./browser", () => ({ +vi.mock("./browser", () => ({ get isMac() { return mockIsMacValue; }, diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000000..538affe50a --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,112 @@ +import path from "node:path"; +import babel from "vite-plugin-babel"; +import { defineConfig } from "vitest/config"; + +const aliases = { + "@server": path.resolve(__dirname, "./server"), + "@shared": path.resolve(__dirname, "./shared"), + "~": path.resolve(__dirname, "./app"), + plugins: path.resolve(__dirname, "./plugins"), +}; + +const fileMock = path.resolve(__dirname, "./__mocks__/fileMock.js"); + +const babelPlugin = () => + babel({ + filter: /\.(t|j)sx?$/, + babelConfig: { + babelrc: false, + configFile: false, + sourceMaps: "inline", + presets: [ + ["@babel/preset-react", { runtime: "automatic" }], + ["@babel/preset-typescript", { allowDeclareFields: true }], + ], + plugins: [ + "babel-plugin-transform-typescript-metadata", + ["@babel/plugin-proposal-decorators", { legacy: true }], + "@babel/plugin-transform-class-properties", + ], + }, + }); + +const sharedConfig = { + resolve: { alias: aliases }, + plugins: [babelPlugin()], + esbuild: false as const, + oxc: false as const, +}; + +const aliasesAsArray = Object.entries(aliases).map(([find, replacement]) => ({ + find, + replacement, +})); + +const fileMockAlias = { find: /\.(gif|ttf|eot|svg)$/, replacement: fileMock }; + +export default defineConfig({ + ...sharedConfig, + test: { + globals: true, + pool: "threads", + // Match Jest's default behavior — unhandled promise rejections are + // logged but don't fail tests on their own. + dangerouslyIgnoreUnhandledErrors: true, + projects: [ + { + ...sharedConfig, + test: { + name: "server", + globals: true, + environment: "node", + include: ["server/**/*.test.{ts,tsx}", "plugins/**/*.test.{ts,tsx}"], + setupFiles: [ + "./__mocks__/console.js", + "./server/test/setupMocks.ts", + "./server/test/setup.ts", + ], + globalSetup: ["./server/test/globalTeardown.ts"], + fileParallelism: true, + }, + }, + { + ...sharedConfig, + resolve: { alias: [fileMockAlias, ...aliasesAsArray] }, + test: { + name: "app", + globals: true, + environment: "jsdom", + environmentOptions: { + jsdom: { url: "http://localhost" }, + }, + include: ["app/**/*.test.{ts,tsx}"], + setupFiles: ["./__mocks__/window.js", "./app/test/setup.ts"], + }, + }, + { + ...sharedConfig, + test: { + name: "shared-node", + globals: true, + environment: "node", + include: ["shared/**/*.test.{ts,tsx}"], + setupFiles: ["./__mocks__/console.js", "./shared/test/setup.ts"], + }, + }, + { + ...sharedConfig, + resolve: { alias: [fileMockAlias, ...aliasesAsArray] }, + test: { + name: "shared-jsdom", + globals: true, + environment: "jsdom", + environmentOptions: { + jsdom: { url: "http://localhost" }, + }, + include: ["shared/**/*.test.{ts,tsx}"], + setupFiles: ["./__mocks__/window.js"], + }, + }, + ], + }, +}); diff --git a/vitest.d.ts b/vitest.d.ts new file mode 100644 index 0000000000..9896c472fb --- /dev/null +++ b/vitest.d.ts @@ -0,0 +1 @@ +/// diff --git a/yarn.lock b/yarn.lock index b7643fc5b7..c4aa0e5f77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,19 +28,6 @@ __metadata: languageName: node linkType: hard -"@asamuzakjp/css-color@npm:^3.2.0": - version: 3.2.0 - resolution: "@asamuzakjp/css-color@npm:3.2.0" - dependencies: - "@csstools/css-calc": "npm:^2.1.3" - "@csstools/css-color-parser": "npm:^3.0.9" - "@csstools/css-parser-algorithms": "npm:^3.0.4" - "@csstools/css-tokenizer": "npm:^3.0.3" - lru-cache: "npm:^10.4.3" - checksum: 10c0/a4bf1c831751b1fae46b437e37e8a38c0b5bd58d23230157ae210bd1e905fe509b89b7c243e63d1522d852668a6292ed730a160e21342772b4e5b7b8ea14c092 - languageName: node - linkType: hard - "@aws-crypto/crc32@npm:5.2.0": version: 5.2.0 resolution: "@aws-crypto/crc32@npm:5.2.0" @@ -801,7 +788,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": version: 7.29.0 resolution: "@babel/code-frame@npm:7.29.0" dependencies: @@ -819,7 +806,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.27.4, @babel/core@npm:^7.28.6": +"@babel/core@npm:^7.24.4, @babel/core@npm:^7.28.6": version: 7.29.0 resolution: "@babel/core@npm:7.29.0" dependencies: @@ -842,7 +829,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.29.0": +"@babel/generator@npm:^7.29.0": version: 7.29.1 resolution: "@babel/generator@npm:7.29.1" dependencies: @@ -971,7 +958,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" checksum: 10c0/3f5f8acc152fdbb69a84b8624145ff4f9b9f6e776cb989f9f968f8606eb7185c5c3cfcf3ba08534e37e1e0e1c118ac67080610333f56baa4f7376c99b5f1143d @@ -1056,7 +1043,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": +"@babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.2 resolution: "@babel/parser@npm:7.29.2" dependencies: @@ -1160,50 +1147,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-async-generators@npm:^7.8.4": - version: 7.8.4 - resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/d13efb282838481348c71073b6be6245b35d4f2f964a8f71e4174f235009f929ef7613df25f8d2338e2d3e44bc4265a9f8638c6aaa136d7a61fe95985f9725c8 - languageName: node - linkType: hard - -"@babel/plugin-syntax-bigint@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/686891b81af2bc74c39013655da368a480f17dd237bf9fbc32048e5865cb706d5a8f65438030da535b332b1d6b22feba336da8fa931f663b6b34e13147d12dde - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-properties@npm:^7.12.13": - version: 7.12.13 - resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.12.13" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-static-block@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 - languageName: node - linkType: hard - "@babel/plugin-syntax-decorators@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-syntax-decorators@npm:7.28.6" @@ -1226,7 +1169,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.28.6": +"@babel/plugin-syntax-import-attributes@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" dependencies: @@ -1237,28 +1180,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0b08b5e4c3128523d8e346f8cfc86824f0da2697b1be12d71af50a31aff7a56ceb873ed28779121051475010c28d6146a6bfea8518b150b71eeb4e46190172ee - languageName: node - linkType: hard - -"@babel/plugin-syntax-json-strings@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e98f31b2ec406c57757d115aac81d0336e8434101c224edd9a5c93cefa53faf63eacc69f3138960c8b25401315af03df37f68d316c151c4b933136716ed6906e - languageName: node - linkType: hard - "@babel/plugin-syntax-jsx@npm:^7.22.5, @babel/plugin-syntax-jsx@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" @@ -1270,94 +1191,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2594cfbe29411ad5bc2ad4058de7b2f6a8c5b86eda525a993959438615479e59c012c14aec979e538d60a584a1a799b60d1b8942c3b18468cb9d99b8fd34cd0b - languageName: node - linkType: hard - -"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2024fbb1162899094cfc81152449b12bd0cc7053c6d4bda8ac2852545c87d0a851b1b72ed9560673cbf3ef6248257262c3c04aabf73117215c1b9cc7dd2542ce - languageName: node - linkType: hard - -"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c55a82b3113480942c6aa2fcbe976ff9caa74b7b1109ff4369641dfbc88d1da348aceb3c31b6ed311c84d1e7c479440b961906c735d0ab494f688bf2fd5b9bb9 - languageName: node - linkType: hard - -"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/27e2493ab67a8ea6d693af1287f7e9acec206d1213ff107a928e85e173741e1d594196f99fec50e9dde404b09164f39dec5864c767212154ffe1caa6af0bc5af - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/46edddf2faa6ebf94147b8e8540dfc60a5ab718e2de4d01b2c0bdf250a4d642c2bd47cbcbb739febcb2bf75514dbcefad3c52208787994b8d0f8822490f55e81 - languageName: node - linkType: hard - -"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 - languageName: node - linkType: hard - -"@babel/plugin-syntax-top-level-await@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/14bf6e65d5bc1231ffa9def5f0ef30b19b51c218fcecaa78cd1bdf7939dfdf23f90336080b7f5196916368e399934ce5d581492d8292b46a2fb569d8b2da106f - languageName: node - linkType: hard - "@babel/plugin-syntax-typescript@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" @@ -2220,7 +2053,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.4.4": +"@babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.4.4": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -2230,13 +2063,6 @@ __metadata: languageName: node linkType: hard -"@bcoe/v8-coverage@npm:^0.2.3": - version: 0.2.3 - resolution: "@bcoe/v8-coverage@npm:0.2.3" - checksum: 10c0/6b80ae4cb3db53f486da2dc63b6e190a74c8c3cca16bb2733f234a0b6a9382b09b146488ae08e2b22cf00f6c83e20f3e040a2f7894f05c045c946d6a090b1d52 - languageName: node - linkType: hard - "@benrbray/prosemirror-math@npm:^0.2.2": version: 0.2.2 resolution: "@benrbray/prosemirror-math@npm:0.2.2" @@ -2377,52 +2203,6 @@ __metadata: languageName: node linkType: hard -"@csstools/color-helpers@npm:^5.1.0": - version: 5.1.0 - resolution: "@csstools/color-helpers@npm:5.1.0" - checksum: 10c0/b7f99d2e455cf1c9b41a67a5327d5d02888cd5c8802a68b1887dffef537d9d4bc66b3c10c1e62b40bbed638b6c1d60b85a232f904ed7b39809c4029cb36567db - languageName: node - linkType: hard - -"@csstools/css-calc@npm:^2.1.3, @csstools/css-calc@npm:^2.1.4": - version: 2.1.4 - resolution: "@csstools/css-calc@npm:2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/42ce5793e55ec4d772083808a11e9fb2dfe36db3ec168713069a276b4c3882205b3507c4680224c28a5d35fe0bc2d308c77f8f2c39c7c09aad8747708eb8ddd8 - languageName: node - linkType: hard - -"@csstools/css-color-parser@npm:^3.0.9": - version: 3.1.0 - resolution: "@csstools/css-color-parser@npm:3.1.0" - dependencies: - "@csstools/color-helpers": "npm:^5.1.0" - "@csstools/css-calc": "npm:^2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/0e0c670ad54ec8ec4d9b07568b80defd83b9482191f5e8ca84ab546b7be6db5d7cc2ba7ac9fae54488b129a4be235d6183d3aab4416fec5e89351f73af4222c5 - languageName: node - linkType: hard - -"@csstools/css-parser-algorithms@npm:^3.0.4": - version: 3.0.5 - resolution: "@csstools/css-parser-algorithms@npm:3.0.5" - peerDependencies: - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/d9a1c888bd43849ae3437ca39251d5c95d2c8fd6b5ccdb7c45491dfd2c1cbdc3075645e80901d120e4d2c1993db9a5b2d83793b779dbbabcfb132adb142eb7f7 - languageName: node - linkType: hard - -"@csstools/css-tokenizer@npm:^3.0.3": - version: 3.0.4 - resolution: "@csstools/css-tokenizer@npm:3.0.4" - checksum: 10c0/3b589f8e9942075a642213b389bab75a2d50d05d203727fcdac6827648a5572674caff07907eff3f9a2389d86a4ee47308fafe4f8588f4a77b7167c588d2559f - languageName: node - linkType: hard - "@dabh/diagnostics@npm:^2.0.8": version: 2.0.8 resolution: "@dabh/diagnostics@npm:2.0.8" @@ -2610,31 +2390,31 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.4.3": - version: 1.7.1 - resolution: "@emnapi/core@npm:1.7.1" +"@emnapi/core@npm:1.10.0": + version: 1.10.0 + resolution: "@emnapi/core@npm:1.10.0" dependencies: - "@emnapi/wasi-threads": "npm:1.1.0" + "@emnapi/wasi-threads": "npm:1.2.1" tslib: "npm:^2.4.0" - checksum: 10c0/f3740be23440b439333e3ae3832163f60c96c4e35337f3220ceba88f36ee89a57a871d27c94eb7a9ff98a09911ed9a2089e477ab549f4d30029f8b907f84a351 + checksum: 10c0/f51d08227857b60632de7714d708124f0e100a1462dde6df8221760939aa3204a73193830371830fac0716f3ccd2129f2cac1b17cd7d7958bc4da9018a296edb languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.3": - version: 1.7.1 - resolution: "@emnapi/runtime@npm:1.7.1" +"@emnapi/runtime@npm:1.10.0": + version: 1.10.0 + resolution: "@emnapi/runtime@npm:1.10.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/26b851cd3e93877d8732a985a2ebf5152325bbacc6204ef5336a47359dedcc23faeb08cdfcb8bb389b5401b3e894b882bc1a1e55b4b7c1ed1e67c991a760ddd5 + checksum: 10c0/953f14991d1aefb92ee6f8eb27dea725e484791a53a0cb5f47d9e0087b9a2c929ff2e92adf95af15d6ad456db6300c6b761ebf72b50a875b874a83520b3ba093 languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.1.0": - version: 1.1.0 - resolution: "@emnapi/wasi-threads@npm:1.1.0" +"@emnapi/wasi-threads@npm:1.2.1": + version: 1.2.1 + resolution: "@emnapi/wasi-threads@npm:1.2.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 + checksum: 10c0/32fcfa81ab396533b2ec1f4082b1ff779a05d9c836bbbd3f4398405b0e6814c0d9503b7993130e37bc6941dbc1ded49f55e9700ae9ca4e803bab2b5bc5deb331 languageName: node linkType: hard @@ -3146,6 +2926,67 @@ __metadata: languageName: node linkType: hard +"@inquirer/ansi@npm:^2.0.5": + version: 2.0.5 + resolution: "@inquirer/ansi@npm:2.0.5" + checksum: 10c0/ad61532e5bb47473e3d987c32d4015499a8ce5f4f86e46467e8e672fc52670beb303905d6b324e453935a61671f59f3b9b1b6a1edbbe1f64085e2bb87735e295 + languageName: node + linkType: hard + +"@inquirer/confirm@npm:^6.0.11": + version: 6.0.12 + resolution: "@inquirer/confirm@npm:6.0.12" + dependencies: + "@inquirer/core": "npm:^11.1.9" + "@inquirer/type": "npm:^4.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/36e9b1ef60e08562f07bcbcd78ba0a681b2fa3e5f54fa5e12303fc5982e8ba875ed782c24161e2295028b2b404ba690e841837303d16eeeb28df7aa9eb8aa835 + languageName: node + linkType: hard + +"@inquirer/core@npm:^11.1.9": + version: 11.1.9 + resolution: "@inquirer/core@npm:11.1.9" + dependencies: + "@inquirer/ansi": "npm:^2.0.5" + "@inquirer/figures": "npm:^2.0.5" + "@inquirer/type": "npm:^4.0.5" + cli-width: "npm:^4.1.0" + fast-wrap-ansi: "npm:^0.2.0" + mute-stream: "npm:^3.0.0" + signal-exit: "npm:^4.1.0" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/f7b162ce5f67fb75aab00a3668fdd8c8629aec790087840ea66ee8ead6009ab2066bec9cbf5bcc394ccdf130e6139051d6bace334b3a66c4f05349585213172c + languageName: node + linkType: hard + +"@inquirer/figures@npm:^2.0.5": + version: 2.0.5 + resolution: "@inquirer/figures@npm:2.0.5" + checksum: 10c0/139671b88f33f059aec85ed3fdf464999115573350c6dea61141adc1cfd43d14742b6cb68150c2ca9baf5a1bae618f990ed89b4430ae768d415bbd19944c56df + languageName: node + linkType: hard + +"@inquirer/type@npm:^4.0.5": + version: 4.0.5 + resolution: "@inquirer/type@npm:4.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/390edb0fd1f027f9c8dc26bac28486d38bbde6c19974ef1588ea187f54a2cb58db639ebca31fa81a8fe4a4e84c2f0953ab3f5a6768ba86649368c5e806148a6f + languageName: node + linkType: hard + "@ioredis/as-callback@npm:^3.0.0": version: 3.0.0 resolution: "@ioredis/as-callback@npm:3.0.0" @@ -3183,343 +3024,6 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/load-nyc-config@npm:^1.0.0": - version: 1.1.0 - resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" - dependencies: - camelcase: "npm:^5.3.1" - find-up: "npm:^4.1.0" - get-package-type: "npm:^0.1.0" - js-yaml: "npm:^3.13.1" - resolve-from: "npm:^5.0.0" - checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 - languageName: node - linkType: hard - -"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": - version: 0.1.3 - resolution: "@istanbuljs/schema@npm:0.1.3" - checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a - languageName: node - linkType: hard - -"@jest/console@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/console@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - slash: "npm:^3.0.0" - checksum: 10c0/5458f26b0591b847b719a707cbd1d6b2b99960784a1480a28d19200a807b6092f066c1bd1810df8c6adebf934a64de7b6022dc35082cd7c8f09f35940da104d9 - languageName: node - linkType: hard - -"@jest/core@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/core@npm:30.3.0" - dependencies: - "@jest/console": "npm:30.3.0" - "@jest/pattern": "npm:30.0.1" - "@jest/reporters": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-changed-files: "npm:30.3.0" - jest-config: "npm:30.3.0" - jest-haste-map: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-resolve-dependencies: "npm:30.3.0" - jest-runner: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - jest-watcher: "npm:30.3.0" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/1735f2263cca10c6cae4e1dbde9c3ccb36e2cbd1cc10bac6fc45e187b06c4e33a6a029f9a6444a3cd43a2a44ffaec3b686d94f70965cebf2b885b198c8615322 - languageName: node - linkType: hard - -"@jest/diff-sequences@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/diff-sequences@npm:30.3.0" - checksum: 10c0/8922c16a869b839b6c05f677023b3e5a9aa1610ad78a9c5ec8bd6654e35e8136ea1c7b60ad561910e2ad964bfdb0b09b0254ff8dcfacd4562095766f60c63d76 - languageName: node - linkType: hard - -"@jest/environment-jsdom-abstract@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment-jsdom-abstract@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/jsdom": "npm:^21.1.7" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - peerDependencies: - canvas: ^3.0.0 - jsdom: "*" - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/95ec44bc3cc4cf91660acd4bf7da547414a1d797a32442dd6c4f6d47c82bb4b6eb2ee6b7a5d177d0827378793433a743462d24f5e445075b69edfbc28ab5ca40 - languageName: node - linkType: hard - -"@jest/environment@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment@npm:30.3.0" - dependencies: - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - checksum: 10c0/4068ccc2e4761e52909239c21e71f73b57ad087bd120b75d3232c68d911686d68fd0fb20e19725517a624b0aa9d45431b00503bd1d5ab2f4958e1a18d265d8d5 - languageName: node - linkType: hard - -"@jest/expect-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect-utils@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - checksum: 10c0/4bb60fb434cb8ed325735bd39171b61621e110502ecc502089805d203ecb17b9fc5a400aeffb83b41fabcc819628a9c38c955f90a716d6aaff193d10926fc854 - languageName: node - linkType: hard - -"@jest/expect-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/expect-utils@npm:29.7.0" - dependencies: - jest-get-type: "npm:^29.6.3" - checksum: 10c0/60b79d23a5358dc50d9510d726443316253ecda3a7fb8072e1526b3e0d3b14f066ee112db95699b7a43ad3f0b61b750c72e28a5a1cac361d7a2bb34747fa938a - languageName: node - linkType: hard - -"@jest/expect@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect@npm:30.3.0" - dependencies: - expect: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - checksum: 10c0/1e052975fdf2b977a63dc9f3db1de56be9dce8e5cd660d9c72cc25093324b990b3e93318cd0c1ff9df7cb30ec7eef71331bc7e19d39700eb3f4498e17ee4c9e0 - languageName: node - linkType: hard - -"@jest/fake-timers@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/fake-timers@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@sinonjs/fake-timers": "npm:^15.0.0" - "@types/node": "npm:*" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - checksum: 10c0/114855ca14d6b34c886855445852a5b960bc3df0ef97c4b971b375747fe0206b3111ec60efc6e658565677022f0d790acd7e232e478f3390ea854d04dea0c4d8 - languageName: node - linkType: hard - -"@jest/get-type@npm:30.1.0": - version: 30.1.0 - resolution: "@jest/get-type@npm:30.1.0" - checksum: 10c0/3e65fd5015f551c51ec68fca31bbd25b466be0e8ee8075d9610fa1c686ea1e70a942a0effc7b10f4ea9a338c24337e1ad97ff69d3ebacc4681b7e3e80d1b24ac - languageName: node - linkType: hard - -"@jest/globals@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/globals@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/expect": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - jest-mock: "npm:30.3.0" - checksum: 10c0/013554dcbf75867e715801e98a5c6eefbea67cb388efd019be9e0d83979d7354874c4b33bbabc95de698215f5b891e921c26a284841504f9825fd789432b1cd0 - languageName: node - linkType: hard - -"@jest/pattern@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/pattern@npm:30.0.1" - dependencies: - "@types/node": "npm:*" - jest-regex-util: "npm:30.0.1" - checksum: 10c0/32c5a7bfb6c591f004dac0ed36d645002ed168971e4c89bd915d1577031672870032594767557b855c5bc330aa1e39a2f54bf150d2ee88a7a0886e9cb65318bc - languageName: node - linkType: hard - -"@jest/reporters@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/reporters@npm:30.3.0" - dependencies: - "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - collect-v8-coverage: "npm:^1.0.2" - exit-x: "npm:^0.2.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - istanbul-lib-coverage: "npm:^3.0.0" - istanbul-lib-instrument: "npm:^6.0.0" - istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^5.0.0" - istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-worker: "npm:30.3.0" - slash: "npm:^3.0.0" - string-length: "npm:^4.0.2" - v8-to-istanbul: "npm:^9.0.1" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/e1b6fb13df94435d4b8e6f4d4bd1c27dfc572ca7393b0a95d14c98013abe3c962aa28e2c56864f3ddd0894834d21c9a67485d11e6c31532aaaeea66ca6a2a026 - languageName: node - linkType: hard - -"@jest/schemas@npm:30.0.5": - version: 30.0.5 - resolution: "@jest/schemas@npm:30.0.5" - dependencies: - "@sinclair/typebox": "npm:^0.34.0" - checksum: 10c0/449dcd7ec5c6505e9ac3169d1143937e67044ae3e66a729ce4baf31812dfd30535f2b3b2934393c97cfdf5984ff581120e6b38f62b8560c8b5b7cc07f4175f65 - languageName: node - linkType: hard - -"@jest/schemas@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/schemas@npm:29.6.3" - dependencies: - "@sinclair/typebox": "npm:^0.27.8" - checksum: 10c0/b329e89cd5f20b9278ae1233df74016ebf7b385e0d14b9f4c1ad18d096c4c19d1e687aa113a9c976b16ec07f021ae53dea811fb8c1248a50ac34fbe009fdf6be - languageName: node - linkType: hard - -"@jest/snapshot-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/snapshot-utils@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - natural-compare: "npm:^1.4.0" - checksum: 10c0/ba4fea05a418b257d128d8f9eb7672a9004952563a45ad577bed80e5b2ea2ec6e6d3a24535781cc6530d9904d8fda7b27d15952d079ccdbe88f87a5e71112df0 - languageName: node - linkType: hard - -"@jest/source-map@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/source-map@npm:30.0.1" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.25" - callsites: "npm:^3.1.0" - graceful-fs: "npm:^4.2.11" - checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 - languageName: node - linkType: hard - -"@jest/test-result@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-result@npm:30.3.0" - dependencies: - "@jest/console": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - collect-v8-coverage: "npm:^1.0.2" - checksum: 10c0/67bcd405d0a1ac85b55afabf26e0ee0f184f9cfe0e659a44e0e4a4456c1c7fed9d2288f0116b017eaddfa49ded8c44426b8694c44f9a8a2af35be9202b8a9165 - languageName: node - linkType: hard - -"@jest/test-sequencer@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-sequencer@npm:30.3.0" - dependencies: - "@jest/test-result": "npm:30.3.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - slash: "npm:^3.0.0" - checksum: 10c0/698be35e7145e79ea9d66071d4ec255f6cef4b5972b5142d299f3edbcbc0428cadf8ddecc6d21e938c98ed72b73b15a6d5f81e7b8b370aaa130d2f6b26fd017c - languageName: node - linkType: hard - -"@jest/transform@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/transform@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/types": "npm:30.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" - babel-plugin-istanbul: "npm:^7.0.1" - chalk: "npm:^4.1.2" - convert-source-map: "npm:^2.0.0" - fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.3.0" - pirates: "npm:^4.0.7" - slash: "npm:^3.0.0" - write-file-atomic: "npm:^5.0.1" - checksum: 10c0/5ad0b5361910680b5160e3dc347c0beb75b4edc35a165ef4fc55837d01365179c276dd6f9cc80f7db94048c641b0c188757e1c98c6d4e9b55577956efbc00574 - languageName: node - linkType: hard - -"@jest/types@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/types@npm:30.3.0" - dependencies: - "@jest/pattern": "npm:30.0.1" - "@jest/schemas": "npm:30.0.5" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - "@types/istanbul-reports": "npm:^3.0.4" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.33" - chalk: "npm:^4.1.2" - checksum: 10c0/c3e3f4de0b77a7ced345f47d3687b1094c1b6c1521529a7ca66a76f9a80194f79179a1dbc32d6761a5b67914a8f78be1e65d1408107efcb1f252c4a63b5ddd92 - languageName: node - linkType: hard - -"@jest/types@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/types@npm:29.6.3" - dependencies: - "@jest/schemas": "npm:^29.6.3" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.8" - chalk: "npm:^4.0.0" - checksum: 10c0/ea4e493dd3fb47933b8ccab201ae573dcc451f951dc44ed2a86123cd8541b82aa9d2b1031caf9b1080d6673c517e2dcc25a44b2dc4f3fbc37bfc965d444888c0 - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.13 resolution: "@jridgewell/gen-mapping@npm:0.3.13" @@ -3557,14 +3061,14 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": version: 1.5.5 resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": version: 0.3.31 resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: @@ -3971,18 +3475,21 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^0.2.11": - version: 0.2.12 - resolution: "@napi-rs/wasm-runtime@npm:0.2.12" +"@mswjs/interceptors@npm:^0.41.3": + version: 0.41.8 + resolution: "@mswjs/interceptors@npm:0.41.8" dependencies: - "@emnapi/core": "npm:^1.4.3" - "@emnapi/runtime": "npm:^1.4.3" - "@tybys/wasm-util": "npm:^0.10.0" - checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + "@open-draft/deferred-promise": "npm:^2.2.0" + "@open-draft/logger": "npm:^0.3.0" + "@open-draft/until": "npm:^2.0.0" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + strict-event-emitter: "npm:^0.5.1" + checksum: 10c0/6ffe97fc7a84acc3d25464542b061e2525b6964c694c4fb325b91d01b61229124c457d5af75cf5eeb96969741769cc104d5d2d11e26d6dbae995aa9398fd9a7e languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^1.1.0, @napi-rs/wasm-runtime@npm:^1.1.1": +"@napi-rs/wasm-runtime@npm:^1.1.0, @napi-rs/wasm-runtime@npm:^1.1.1, @napi-rs/wasm-runtime@npm:^1.1.4": version: 1.1.4 resolution: "@napi-rs/wasm-runtime@npm:1.1.4" dependencies: @@ -4425,6 +3932,37 @@ __metadata: languageName: node linkType: hard +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 10c0/eafc1b1d0fc8edb5e1c753c5e0f3293410b40dde2f92688211a54806d4136887051f39b98c1950370be258483deac9dfd17cf8b96557553765198ef2547e4549 + languageName: node + linkType: hard + +"@open-draft/deferred-promise@npm:^3.0.0": + version: 3.0.0 + resolution: "@open-draft/deferred-promise@npm:3.0.0" + checksum: 10c0/4dd697e55495e436be9536413cc9975e792e9ca7472e81e3d3d69e9b65cb678465aac90b463ac02f2b490c0581c4e9aa8a33d2a5857decbe2c6d9ffb310f8e1f + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.0" + checksum: 10c0/90010647b22e9693c16258f4f9adb034824d1771d3baa313057b9a37797f571181005bc50415a934eaf7c891d90ff71dcd7a9d5048b0b6bb438f31bef2c7c5c1 + languageName: node + linkType: hard + +"@open-draft/until@npm:^2.0.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 10c0/61d3f99718dd86bb393fee2d7a785f961dcaf12f2055f0c693b27f4d0cd5f7a03d498a6d9289773b117590d794a43cd129366fd8e99222e4832f67b1653d54cf + languageName: node + linkType: hard + "@opentelemetry/api-logs@npm:<1.0.0": version: 0.208.0 resolution: "@opentelemetry/api-logs@npm:0.208.0" @@ -4615,6 +4153,13 @@ __metadata: languageName: node linkType: hard +"@oxc-project/types@npm:=0.127.0": + version: 0.127.0 + resolution: "@oxc-project/types@npm:0.127.0" + checksum: 10c0/52c0947ac64a9ca119fe971f947e784a35ecd14a072fa3f542a58a5f6c42010b53f2bf92731e39b9899b83c990a9517bbd29d1e5a5b7b489e52616685c6a9278 + languageName: node + linkType: hard + "@oxc-project/types@npm:^0.121.0": version: 0.121.0 resolution: "@oxc-project/types@npm:0.121.0" @@ -4969,10 +4514,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.2.9": - version: 0.2.9 - resolution: "@pkgr/core@npm:0.2.9" - checksum: 10c0/ac8e4e8138b1a7a4ac6282873aef7389c352f1f8b577b4850778f5182e4a39a5241facbe48361fec817f56d02b51691b383010843fb08b34a8e8ea3614688fd5 +"@polka/url@npm:^1.0.0-next.24": + version: 1.0.0-next.29 + resolution: "@polka/url@npm:1.0.0-next.29" + checksum: 10c0/0d58e081844095cb029d3c19a659bfefd09d5d51a2f791bc61eba7ea826f13d6ee204a8a448c2f5a855c17df07b37517373ff916dd05801063c0568ae9937684 languageName: node linkType: hard @@ -5978,6 +5523,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-android-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-android-arm64@npm:1.0.0-rc.17" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rolldown/binding-darwin-arm64@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-beta.53" @@ -5985,6 +5537,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-rc.17" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rolldown/binding-darwin-x64@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-beta.53" @@ -5992,6 +5551,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-darwin-x64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-rc.17" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rolldown/binding-freebsd-x64@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-beta.53" @@ -5999,6 +5565,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-rc.17" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-beta.53" @@ -6006,6 +5579,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-beta.53" @@ -6013,6 +5593,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rolldown/binding-linux-arm64-musl@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-beta.53" @@ -6020,6 +5607,27 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rolldown/binding-linux-x64-gnu@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-beta.53" @@ -6027,6 +5635,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rolldown/binding-linux-x64-musl@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-beta.53" @@ -6034,6 +5649,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.17" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rolldown/binding-openharmony-arm64@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0-beta.53" @@ -6041,6 +5663,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.17" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@rolldown/binding-wasm32-wasi@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-beta.53" @@ -6050,6 +5679,17 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.17" + dependencies: + "@emnapi/core": "npm:1.10.0" + "@emnapi/runtime": "npm:1.10.0" + "@napi-rs/wasm-runtime": "npm:^1.1.4" + conditions: cpu=wasm32 + languageName: node + linkType: hard + "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-beta.53" @@ -6057,6 +5697,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.17" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rolldown/binding-win32-x64-msvc@npm:1.0.0-beta.53": version: 1.0.0-beta.53 resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-beta.53" @@ -6064,6 +5711,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.17" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rolldown/pluginutils@npm:1.0.0-beta.11": version: 1.0.0-beta.11 resolution: "@rolldown/pluginutils@npm:1.0.0-beta.11" @@ -6078,6 +5732,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/pluginutils@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/pluginutils@npm:1.0.0-rc.17" + checksum: 10c0/5e840b20cc531910c093c1ca36e550952cf4936465a50d89f0a98fc9d0dfd7d319d06a10a5f4376209d89e9bf4d60af6cc8363ebf0dcc5e60842f7fef438b2f0 + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -6154,7 +5815,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1": +"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.3.0": version: 5.3.0 resolution: "@rollup/pluginutils@npm:5.3.0" dependencies: @@ -6379,38 +6040,6 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 10c0/ef6351ae073c45c2ac89494dbb3e1f87cc60a93ce4cde797b782812b6f97da0d620ae81973f104b43c9b7eaa789ad20ba4f6a1359f1cc62f63729a55a7d22d4e - languageName: node - linkType: hard - -"@sinclair/typebox@npm:^0.34.0": - version: 0.34.45 - resolution: "@sinclair/typebox@npm:0.34.45" - checksum: 10c0/05b8e0107f38f06632811156ebac86d2ab72c4f1876a440eeb9f0e02be1b245959552a7a5515f4d56a2a18c2dc147dcdb60ccabb43608cead87ab4359de89142 - languageName: node - linkType: hard - -"@sinonjs/commons@npm:^3.0.1": - version: 3.0.1 - resolution: "@sinonjs/commons@npm:3.0.1" - dependencies: - type-detect: "npm:4.0.8" - checksum: 10c0/1227a7b5bd6c6f9584274db996d7f8cee2c8c350534b9d0141fc662eaf1f292ea0ae3ed19e5e5271c8fd390d27e492ca2803acd31a1978be2cdc6be0da711403 - languageName: node - linkType: hard - -"@sinonjs/fake-timers@npm:^15.0.0": - version: 15.3.2 - resolution: "@sinonjs/fake-timers@npm:15.3.2" - dependencies: - "@sinonjs/commons": "npm:^3.0.1" - checksum: 10c0/fea39af47e70acf7f6b431b857dc5b50886e1a19d48189bc7f9cf90806a9fdfd4931c04343558724772d429c47fb53df640fc8c8d6ddf6ad66164bd7cbd3220a - languageName: node - linkType: hard - "@smithy/chunked-blob-reader-native@npm:^4.2.3": version: 4.2.3 resolution: "@smithy/chunked-blob-reader-native@npm:4.2.3" @@ -7026,6 +6655,13 @@ __metadata: languageName: node linkType: hard +"@standard-schema/spec@npm:^1.1.0": + version: 1.1.0 + resolution: "@standard-schema/spec@npm:1.1.0" + checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 + languageName: node + linkType: hard + "@surma/rollup-plugin-off-main-thread@npm:^2.2.3": version: 2.2.3 resolution: "@surma/rollup-plugin-off-main-thread@npm:2.2.3" @@ -7038,6 +6674,158 @@ __metadata: languageName: node linkType: hard +"@swc/core-darwin-arm64@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-darwin-arm64@npm:1.15.32" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@swc/core-darwin-x64@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-darwin-x64@npm:1.15.32" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@swc/core-linux-arm-gnueabihf@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.32" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@swc/core-linux-arm64-gnu@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-arm64-gnu@npm:1.15.32" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-arm64-musl@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-arm64-musl@npm:1.15.32" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@swc/core-linux-ppc64-gnu@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-ppc64-gnu@npm:1.15.32" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-s390x-gnu@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-s390x-gnu@npm:1.15.32" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-x64-gnu@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-x64-gnu@npm:1.15.32" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-x64-musl@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-linux-x64-musl@npm:1.15.32" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@swc/core-win32-arm64-msvc@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-win32-arm64-msvc@npm:1.15.32" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@swc/core-win32-ia32-msvc@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-win32-ia32-msvc@npm:1.15.32" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@swc/core-win32-x64-msvc@npm:1.15.32": + version: 1.15.32 + resolution: "@swc/core-win32-x64-msvc@npm:1.15.32" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@swc/core@npm:^1.15.32": + version: 1.15.32 + resolution: "@swc/core@npm:1.15.32" + dependencies: + "@swc/core-darwin-arm64": "npm:1.15.32" + "@swc/core-darwin-x64": "npm:1.15.32" + "@swc/core-linux-arm-gnueabihf": "npm:1.15.32" + "@swc/core-linux-arm64-gnu": "npm:1.15.32" + "@swc/core-linux-arm64-musl": "npm:1.15.32" + "@swc/core-linux-ppc64-gnu": "npm:1.15.32" + "@swc/core-linux-s390x-gnu": "npm:1.15.32" + "@swc/core-linux-x64-gnu": "npm:1.15.32" + "@swc/core-linux-x64-musl": "npm:1.15.32" + "@swc/core-win32-arm64-msvc": "npm:1.15.32" + "@swc/core-win32-ia32-msvc": "npm:1.15.32" + "@swc/core-win32-x64-msvc": "npm:1.15.32" + "@swc/counter": "npm:^0.1.3" + "@swc/types": "npm:^0.1.26" + peerDependencies: + "@swc/helpers": ">=0.5.17" + dependenciesMeta: + "@swc/core-darwin-arm64": + optional: true + "@swc/core-darwin-x64": + optional: true + "@swc/core-linux-arm-gnueabihf": + optional: true + "@swc/core-linux-arm64-gnu": + optional: true + "@swc/core-linux-arm64-musl": + optional: true + "@swc/core-linux-ppc64-gnu": + optional: true + "@swc/core-linux-s390x-gnu": + optional: true + "@swc/core-linux-x64-gnu": + optional: true + "@swc/core-linux-x64-musl": + optional: true + "@swc/core-win32-arm64-msvc": + optional: true + "@swc/core-win32-ia32-msvc": + optional: true + "@swc/core-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@swc/helpers": + optional: true + checksum: 10c0/114e2d08a588de6dc0b01106368461d471464ec1bd0d046f4007cd2af9f52c0ddbf473a6dc251aa7f71828b74fe8488221718019187bb91a5f503a45b91b5fb1 + languageName: node + linkType: hard + +"@swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: 10c0/8424f60f6bf8694cfd2a9bca45845bce29f26105cda8cf19cdb9fd3e78dc6338699e4db77a89ae449260bafa1cc6bec307e81e7fb96dbf7dcfce0eea55151356 + languageName: node + linkType: hard + +"@swc/types@npm:^0.1.26": + version: 0.1.26 + resolution: "@swc/types@npm:0.1.26" + dependencies: + "@swc/counter": "npm:^0.1.3" + checksum: 10c0/8449341e8bbff81c14e9918c25421143cf605dff20f70f048847e1f7cede396f8dd73903cbef331a809b4a8e15d0db374a5f6809003e7b440f93df1dd4934d28 + languageName: node + linkType: hard + "@tanstack/react-table@npm:^8.21.3": version: 8.21.3 resolution: "@tanstack/react-table@npm:8.21.3" @@ -7083,7 +6871,7 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0, @tybys/wasm-util@npm:^0.10.1": +"@tybys/wasm-util@npm:^0.10.1": version: 0.10.1 resolution: "@tybys/wasm-util@npm:0.10.1" dependencies: @@ -7131,47 +6919,6 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.20.5": - version: 7.20.5 - resolution: "@types/babel__core@npm:7.20.5" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff - languageName: node - linkType: hard - -"@types/babel__generator@npm:*": - version: 7.27.0 - resolution: "@types/babel__generator@npm:7.27.0" - dependencies: - "@babel/types": "npm:^7.0.0" - checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd - languageName: node - linkType: hard - -"@types/babel__template@npm:*": - version: 7.4.4 - resolution: "@types/babel__template@npm:7.4.4" - dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" - checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b - languageName: node - linkType: hard - -"@types/babel__traverse@npm:*": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 - languageName: node - linkType: hard - "@types/bluebird@npm:*": version: 3.5.42 resolution: "@types/bluebird@npm:3.5.42" @@ -7196,6 +6943,16 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^5.2.2": + version: 5.2.3 + resolution: "@types/chai@npm:5.2.3" + dependencies: + "@types/deep-eql": "npm:*" + assertion-error: "npm:^2.0.1" + checksum: 10c0/e0ef1de3b6f8045a5e473e867c8565788c444271409d155588504840ad1a53611011f85072188c2833941189400228c1745d78323dac13fcede9c2b28bacfb2f + languageName: node + linkType: hard + "@types/co-body@npm:^6.1.0, @types/co-body@npm:^6.1.3": version: 6.1.3 resolution: "@types/co-body@npm:6.1.3" @@ -7547,6 +7304,13 @@ __metadata: languageName: node linkType: hard +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + "@types/diff@npm:^5.0.9": version: 5.2.3 resolution: "@types/diff@npm:5.2.3" @@ -7741,41 +7505,6 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": - version: 2.0.6 - resolution: "@types/istanbul-lib-coverage@npm:2.0.6" - checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 - languageName: node - linkType: hard - -"@types/istanbul-lib-report@npm:*": - version: 3.0.3 - resolution: "@types/istanbul-lib-report@npm:3.0.3" - dependencies: - "@types/istanbul-lib-coverage": "npm:*" - checksum: 10c0/247e477bbc1a77248f3c6de5dadaae85ff86ac2d76c5fc6ab1776f54512a745ff2a5f791d22b942e3990ddbd40f3ef5289317c4fca5741bedfaa4f01df89051c - languageName: node - linkType: hard - -"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": - version: 3.0.4 - resolution: "@types/istanbul-reports@npm:3.0.4" - dependencies: - "@types/istanbul-lib-report": "npm:*" - checksum: 10c0/1647fd402aced5b6edac87274af14ebd6b3a85447ef9ad11853a70fd92a98d35f81a5d3ea9fcb5dbb5834e800c6e35b64475e33fcae6bfa9acc70d61497c54ee - languageName: node - linkType: hard - -"@types/jest@npm:^29.5.14": - version: 29.5.14 - resolution: "@types/jest@npm:29.5.14" - dependencies: - expect: "npm:^29.0.0" - pretty-format: "npm:^29.0.0" - checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed - languageName: node - linkType: hard - "@types/js-yaml@npm:^4.0.9": version: 4.0.9 resolution: "@types/js-yaml@npm:4.0.9" @@ -7783,14 +7512,15 @@ __metadata: languageName: node linkType: hard -"@types/jsdom@npm:^21.1.7": - version: 21.1.7 - resolution: "@types/jsdom@npm:21.1.7" +"@types/jsdom@npm:^28.0.1": + version: 28.0.1 + resolution: "@types/jsdom@npm:28.0.1" dependencies: "@types/node": "npm:*" "@types/tough-cookie": "npm:*" parse5: "npm:^7.0.0" - checksum: 10c0/c0c0025adc2b193e85453eeeea168bb909f0ebad08d6552be7474a407e9c163db8f696dcf1e3cbe8cb9c9d970ba45f4386171794509c1a0fe5d1fed72c91679d + undici-types: "npm:^7.21.0" + checksum: 10c0/4d0e412b4de5389279544ff227c6bacf6a8cb3e2fcabf8b543026568444c60e770848ba752cd134ef90f6ce3e7bafd3158b2a3dc1947c2961a5824b12d15bfac languageName: node linkType: hard @@ -8340,6 +8070,15 @@ __metadata: languageName: node linkType: hard +"@types/set-cookie-parser@npm:^2.4.10": + version: 2.4.10 + resolution: "@types/set-cookie-parser@npm:2.4.10" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/010b0c582ea70a2088618b4725808e80c30cce296c19ec58e51d94e0fd1038201b7b99238bf3ea74e1894163c8037d10a4f1729de62b2801ce240ff070f43e76 + languageName: node + linkType: hard + "@types/slug@npm:^5.0.9": version: 5.0.9 resolution: "@types/slug@npm:5.0.9" @@ -8347,10 +8086,10 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": - version: 2.0.3 - resolution: "@types/stack-utils@npm:2.0.3" - checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c +"@types/statuses@npm:^2.0.6": + version: 2.0.6 + resolution: "@types/statuses@npm:2.0.6" + checksum: 10c0/dd88c220b0e2c6315686289525fd61472d2204d2e4bef4941acfb76bda01d3066f749ac74782aab5b537a45314fcd7d6261eefa40b6ec872691f5803adaa608d languageName: node linkType: hard @@ -8453,22 +8192,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs-parser@npm:*": - version: 21.0.3 - resolution: "@types/yargs-parser@npm:21.0.3" - checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0 - languageName: node - linkType: hard - -"@types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": - version: 17.0.35 - resolution: "@types/yargs@npm:17.0.35" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: 10c0/609557826a6b85e73ccf587923f6429850d6dc70e420b455bab4601b670bfadf684b09ae288bccedab042c48ba65f1666133cf375814204b544009f57d6eef63 - languageName: node - linkType: hard - "@types/yauzl@npm:^2.10.3": version: 2.10.3 resolution: "@types/yauzl@npm:2.10.3" @@ -8478,148 +8201,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.3.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a - languageName: node - linkType: hard - -"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-android-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-darwin-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" - dependencies: - "@napi-rs/wasm-runtime": "npm:^0.2.11" - conditions: cpu=wasm32 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@upsetjs/venn.js@npm:^2.0.0": version: 2.0.0 resolution: "@upsetjs/venn.js@npm:2.0.0" @@ -8646,6 +8227,105 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/expect@npm:4.1.5" + dependencies: + "@standard-schema/spec": "npm:^1.1.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + chai: "npm:^6.2.2" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/5184682304db471aa20024c1154210ad3d6d590afb61646201ce1a15297259f9a35f92f8fad4435bc8a82135e307ddd27c8495f72417d72d9aa139eb281d9e06 + languageName: node + linkType: hard + +"@vitest/mocker@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/mocker@npm:4.1.5" + dependencies: + "@vitest/spy": "npm:4.1.5" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/bcfe97700476130933c7ea33fa670c8d2768a81de5325ce407f901e55c2f66cabbb88a7b6cffb46ddf33dff7d8fc209d769fb298f568e310fbeead9b36f6fdb9 + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/pretty-format@npm:4.1.5" + dependencies: + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/42b5e9b75e87c0a884d36bee364e2d07ee45e96f413377737a74993e077d90c3a12aa36743855aee5e4e28b78fae20e3e6de5eef8d5344b9aba2bc1e1d5537a1 + languageName: node + linkType: hard + +"@vitest/runner@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/runner@npm:4.1.5" + dependencies: + "@vitest/utils": "npm:4.1.5" + pathe: "npm:^2.0.3" + checksum: 10c0/6a03b313a121155f6dd9e32eeb103c0e12440f586bc4ba1f0d77444e44c6df4652a44443718552037463115635b8378e11f35902d90ce1326f77743219fca056 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/snapshot@npm:4.1.5" + dependencies: + "@vitest/pretty-format": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10c0/e11bf50d06702331290750a40eaef86078c108df3cd9a52bb1be7b84250048790163f36827525be6a383a4bb1994fc35e6d0c24239a41688b0bb68a1d15d172f + languageName: node + linkType: hard + +"@vitest/spy@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/spy@npm:4.1.5" + checksum: 10c0/fda6b1ee0a2fec1a152d8041aba7a79744c3876863b244d1ed406d02b36e8ccc997edb2e3963d1027d728d3dc5a33813e11bef53a0a14fc7de4de5e721d0f591 + languageName: node + linkType: hard + +"@vitest/ui@npm:^4.1.5": + version: 4.1.5 + resolution: "@vitest/ui@npm:4.1.5" + dependencies: + "@vitest/utils": "npm:4.1.5" + fflate: "npm:^0.8.2" + flatted: "npm:^3.4.2" + pathe: "npm:^2.0.3" + sirv: "npm:^3.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.1.0" + peerDependencies: + vitest: 4.1.5 + checksum: 10c0/2109480d08516abe3350994ebfcb9adc8a2eb4bb1839c48a336d6ff3378eb49a520ad6490f177e60034ed4fcf579206d9ab14995e951cbf6d4c7c792c46fe202 + languageName: node + linkType: hard + +"@vitest/utils@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/utils@npm:4.1.5" + dependencies: + "@vitest/pretty-format": "npm:4.1.5" + convert-source-map: "npm:^2.0.0" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/72409717e68018e5fe42fa173cc4eff6def8c35bd52013f86ddb414cd28d73fcc425ac62968e01a52371b3fd5a7a775536283d2f1d64432753f628712a6a4908 + languageName: node + linkType: hard + "@xmldom/xmldom@npm:^0.8.6": version: 0.8.13 resolution: "@xmldom/xmldom@npm:0.8.13" @@ -8801,15 +8481,6 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.3.2": - version: 4.3.2 - resolution: "ansi-escapes@npm:4.3.2" - dependencies: - type-fest: "npm:^0.21.3" - checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 - languageName: node - linkType: hard - "ansi-escapes@npm:^7.0.0": version: 7.3.0 resolution: "ansi-escapes@npm:7.3.0" @@ -8851,13 +8522,6 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": - version: 5.2.0 - resolution: "ansi-styles@npm:5.2.0" - checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df - languageName: node - linkType: hard - "ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1, ansi-styles@npm:^6.2.3": version: 6.2.3 resolution: "ansi-styles@npm:6.2.3" @@ -8950,6 +8614,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + "async-function@npm:^1.0.0": version: 1.0.0 resolution: "async-function@npm:1.0.0" @@ -9053,45 +8724,6 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:30.3.0, babel-jest@npm:^30.3.0": - version: 30.3.0 - resolution: "babel-jest@npm:30.3.0" - dependencies: - "@jest/transform": "npm:30.3.0" - "@types/babel__core": "npm:^7.20.5" - babel-plugin-istanbul: "npm:^7.0.1" - babel-preset-jest: "npm:30.3.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - slash: "npm:^3.0.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-0 - checksum: 10c0/5e41e124a404ddb78aa37a20336d7c883feab5ad9c4f4c72ae26db71be2fcca345874b9a7fef97d9c5f64f144a264b247ebde8acfe493578320f314ca581bac3 - languageName: node - linkType: hard - -"babel-plugin-istanbul@npm:^7.0.1": - version: 7.0.1 - resolution: "babel-plugin-istanbul@npm:7.0.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.0.0" - "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-instrument: "npm:^6.0.2" - test-exclude: "npm:^6.0.0" - checksum: 10c0/92975e3df12503b168695463b451468da0c20e117807221652eb8e33a26c160f3b9d4c5c4e65495657420e871c6a54e5e31f539e2e1da37ef2261d7ddd4b1dfd - languageName: node - linkType: hard - -"babel-plugin-jest-hoist@npm:30.3.0": - version: 30.3.0 - resolution: "babel-plugin-jest-hoist@npm:30.3.0" - dependencies: - "@types/babel__core": "npm:^7.20.5" - checksum: 10c0/5e15900a6487356131e084970f4a9ebe24b702d74930f786e897d4fab90b0987054f66661a3570ea692f429dcd158c2214c97ecf08f7356cbc60029d7b277c74 - languageName: node - linkType: hard - "babel-plugin-module-resolver@npm:^5.0.3": version: 5.0.3 resolution: "babel-plugin-module-resolver@npm:5.0.3" @@ -9189,43 +8821,6 @@ __metadata: languageName: node linkType: hard -"babel-preset-current-node-syntax@npm:^1.2.0": - version: 1.2.0 - resolution: "babel-preset-current-node-syntax@npm:1.2.0" - dependencies: - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/plugin-syntax-bigint": "npm:^7.8.3" - "@babel/plugin-syntax-class-properties": "npm:^7.12.13" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" - "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" - "@babel/plugin-syntax-import-meta": "npm:^7.10.4" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" - "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0 || ^8.0.0-0 - checksum: 10c0/94a4f81cddf9b051045d08489e4fff7336292016301664c138cfa3d9ffe3fe2ba10a24ad6ae589fd95af1ac72ba0216e1653555c187e694d7b17be0c002bea10 - languageName: node - linkType: hard - -"babel-preset-jest@npm:30.3.0": - version: 30.3.0 - resolution: "babel-preset-jest@npm:30.3.0" - dependencies: - babel-plugin-jest-hoist: "npm:30.3.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-beta.1 - checksum: 10c0/a6839a1527d254bf04e82c0cf61a6a2aa283123a74f0a552e6fce462cb990abebab75a13ec3e9c58b09a865d4d2dfbac710c2d3975ae3ce6f2707cb314915c66 - languageName: node - linkType: hard - "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -9496,15 +9091,6 @@ __metadata: languageName: node linkType: hard -"bser@npm:2.1.1": - version: 2.1.1 - resolution: "bser@npm:2.1.1" - dependencies: - node-int64: "npm:^0.4.0" - checksum: 10c0/24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 - languageName: node - linkType: hard - "btoa-lite@npm:^1.0.0": version: 1.0.0 resolution: "btoa-lite@npm:1.0.0" @@ -9636,27 +9222,13 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.0.0, callsites@npm:^3.1.0": +"callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 languageName: node linkType: hard -"camelcase@npm:^5.3.1": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 - languageName: node - linkType: hard - -"camelcase@npm:^6.3.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 - languageName: node - linkType: hard - "camelize@npm:^1.0.0": version: 1.0.1 resolution: "camelize@npm:1.0.1" @@ -9671,6 +9243,13 @@ __metadata: languageName: node linkType: hard +"chai@npm:^6.2.2": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 + languageName: node + linkType: hard + "chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -9682,7 +9261,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.1.2": +"chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -9692,13 +9271,6 @@ __metadata: languageName: node linkType: hard -"char-regex@npm:^1.0.2": - version: 1.0.2 - resolution: "char-regex@npm:1.0.2" - checksum: 10c0/57a09a86371331e0be35d9083ba429e86c4f4648ecbe27455dbfb343037c16ee6fdc7f6b61f433a57cc5ded5561d71c56a150e018f40c2ffb7bc93a26dae341e - languageName: node - linkType: hard - "character-entities-legacy@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-legacy@npm:1.1.4" @@ -9800,21 +9372,14 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^3.2.0, ci-info@npm:^3.7.0": +"ci-info@npm:^3.7.0": version: 3.9.0 resolution: "ci-info@npm:3.9.0" checksum: 10c0/6f0109e36e111684291d46123d491bc4e7b7a1934c3a20dea28cba89f1d4a03acd892f5f6a81ed3855c38647e285a150e3c9ba062e38943bef57fee6c1554c3a languageName: node linkType: hard -"ci-info@npm:^4.2.0": - version: 4.3.1 - resolution: "ci-info@npm:4.3.1" - checksum: 10c0/7dd82000f514d76ddfe7775e4cb0d66e5c638f5fa0e2a3be29557e898da0d32ac04f231217d414d07fb968b1fbc6d980ee17ddde0d2c516f23da9cfff608f6c1 - languageName: node - linkType: hard - -"cjs-module-lexer@npm:^2.1.0, cjs-module-lexer@npm:^2.2.0": +"cjs-module-lexer@npm:^2.2.0": version: 2.2.0 resolution: "cjs-module-lexer@npm:2.2.0" checksum: 10c0/aec4ca58f87145fac221386790ecaae8b012f2e2359a45acb61d8c75ea4fa84f6ea869f17abc1a7e91a808eff0fed581209632f03540de16f72f0a28f5fd35ac @@ -9867,6 +9432,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -9916,13 +9488,6 @@ __metadata: languageName: node linkType: hard -"co@npm:^4.6.0": - version: 4.6.0 - resolution: "co@npm:4.6.0" - checksum: 10c0/c0e85ea0ca8bf0a50cbdca82efc5af0301240ca88ebe3644a6ffb8ffe911f34d40f8fbcf8f1d52c5ddd66706abd4d3bfcd64259f1e8e2371d4f47573b0dc8c28 - languageName: node - linkType: hard - "collapse-white-space@npm:^2.0.0": version: 2.1.0 resolution: "collapse-white-space@npm:2.1.0" @@ -9930,13 +9495,6 @@ __metadata: languageName: node linkType: hard -"collect-v8-coverage@npm:^1.0.2": - version: 1.0.3 - resolution: "collect-v8-coverage@npm:1.0.3" - checksum: 10c0/bc62ba251bcce5e3354a8f88fa6442bee56e3e612fec08d4dfcf66179b41ea0bf544b0f78c4ebc0f8050871220af95bb5c5578a6aef346feea155640582f09dc - languageName: node - linkType: hard - "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -10251,6 +9809,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:^1.1.1": + version: 1.1.1 + resolution: "cookie@npm:1.1.1" + checksum: 10c0/79c4ddc0fcad9c4f045f826f42edf54bcc921a29586a4558b0898277fa89fb47be95bc384c2253f493af7b29500c830da28341274527328f18eba9f58afa112c + languageName: node + linkType: hard + "cookies@npm:~0.9.1": version: 0.9.1 resolution: "cookies@npm:0.9.1" @@ -10370,15 +9935,6 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:^3.0.4": - version: 3.2.0 - resolution: "cross-fetch@npm:3.2.0" - dependencies: - node-fetch: "npm:^2.7.0" - checksum: 10c0/d8596adf0269130098a676f6739a0922f3cc7b71cc89729925411ebe851a87026171c82ea89154c4811c9867c01c44793205a52e618ce2684650218c7fbeeb9f - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -10451,16 +10007,6 @@ __metadata: languageName: node linkType: hard -"cssstyle@npm:^4.2.1": - version: 4.6.0 - resolution: "cssstyle@npm:4.6.0" - dependencies: - "@asamuzakjp/css-color": "npm:^3.2.0" - rrweb-cssom: "npm:^0.8.0" - checksum: 10c0/71add1b0ffafa1bedbef6855db6189b9523d3320e015a0bf3fbd504760efb9a81e1f1a225228d5fa892ee58e56d06994ca372e7f4e461cda7c4c9985fe075f65 - languageName: node - linkType: hard - "csstype@npm:^3.2.2": version: 3.2.3 resolution: "csstype@npm:3.2.3" @@ -10871,16 +10417,6 @@ __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: "npm:^4.0.0" - whatwg-url: "npm:^14.0.0" - checksum: 10c0/1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad - languageName: node - linkType: hard - "data-view-buffer@npm:^1.0.2": version: 1.0.2 resolution: "data-view-buffer@npm:1.0.2" @@ -11004,7 +10540,7 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.3, decimal.js@npm:^10.5.0": +"decimal.js@npm:^10.4.3": version: 10.6.0 resolution: "decimal.js@npm:10.6.0" checksum: 10c0/07d69fbcc54167a340d2d97de95f546f9ff1f69d2b45a02fd7a5292412df3cd9eb7e23065e532a318f5474a2e1bccf8392fdf0443ef467f97f3bf8cb0477e5aa @@ -11018,18 +10554,6 @@ __metadata: languageName: node linkType: hard -"dedent@npm:^1.6.0": - version: 1.7.1 - resolution: "dedent@npm:1.7.1" - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - checksum: 10c0/ae29ec1c5bd5216c698c9f23acaa5b720260fd4cef3c8b5af887eb5f8c9e6fdd5fed8668767437b4efea35e2991bd798987717633411a1734807c28255769b78 - languageName: node - linkType: hard - "deep-equal@npm:~1.0.1": version: 1.0.1 resolution: "deep-equal@npm:1.0.1" @@ -11138,13 +10662,6 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.1.0": - version: 3.1.0 - resolution: "detect-newline@npm:3.1.0" - checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d - languageName: node - linkType: hard - "detect-node-es@npm:^1.1.0": version: 1.1.0 resolution: "detect-node-es@npm:1.1.0" @@ -11162,13 +10679,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": - version: 29.6.3 - resolution: "diff-sequences@npm:29.6.3" - checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 - languageName: node - linkType: hard - "diff@npm:^5.2.2": version: 5.2.2 resolution: "diff@npm:5.2.2" @@ -11415,7 +10925,7 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.13.0, emittery@npm:^0.13.1": +"emittery@npm:^0.13.0": version: 0.13.1 resolution: "emittery@npm:0.13.1" checksum: 10c0/1573d0ae29ab34661b6c63251ff8f5facd24ccf6a823f19417ae8ba8c88ea450325788c67f16c99edec8de4b52ce93a10fe441ece389fd156e88ee7dab9bfa35 @@ -11671,6 +11181,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^2.0.0": + version: 2.1.0 + resolution: "es-module-lexer@npm:2.1.0" + checksum: 10c0/93bcf2454fa72d67fe3ccd0abef8ce7933f5840a319513418a643dd8e9c6aa8f49709cecfae02ded722805dd327232d30723a807cc52e6809d6ac697c62c29fb + languageName: node + linkType: hard + "es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": version: 1.1.1 resolution: "es-object-atoms@npm:1.1.1" @@ -11823,13 +11340,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 - languageName: node - linkType: hard - "estree-walker@npm:^1.0.1": version: 1.0.1 resolution: "estree-walker@npm:1.0.1" @@ -11844,6 +11354,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -11914,37 +11433,10 @@ __metadata: languageName: node linkType: hard -"exit-x@npm:^0.2.2": - version: 0.2.2 - resolution: "exit-x@npm:0.2.2" - checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 - languageName: node - linkType: hard - -"expect@npm:30.3.0": - version: 30.3.0 - resolution: "expect@npm:30.3.0" - dependencies: - "@jest/expect-utils": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - checksum: 10c0/a07a157a0c8b3f1e29bfe5ccbf03a3add2c69fe60d1af8a0980053bb6403d721d5f5e4616f1ea5833b747913f8c880c79ce4d98c23a71a2f0c27cf7273892576 - languageName: node - linkType: hard - -"expect@npm:^29.0.0": - version: 29.7.0 - resolution: "expect@npm:29.7.0" - dependencies: - "@jest/expect-utils": "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - jest-matcher-utils: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - checksum: 10c0/2eddeace66e68b8d8ee5f7be57f3014b19770caaf6815c7a08d131821da527fb8c8cb7b3dcd7c883d2d3d8d184206a4268984618032d1e4b16dc8d6596475d41 +"expect-type@npm:^1.3.0": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd languageName: node linkType: hard @@ -12059,6 +11551,22 @@ __metadata: languageName: node linkType: hard +"fast-string-truncated-width@npm:^3.0.2": + version: 3.0.3 + resolution: "fast-string-truncated-width@npm:3.0.3" + checksum: 10c0/043b8663397d14a3880ce4f3407bcda60b40db9bbeafe62863a35d1f9c69ea17c8da3fcd72de235553e6c9cd053128cde9e24ca0d4a7463208f48db3cd23d981 + languageName: node + linkType: hard + +"fast-string-width@npm:^3.0.2": + version: 3.0.2 + resolution: "fast-string-width@npm:3.0.2" + dependencies: + fast-string-truncated-width: "npm:^3.0.2" + checksum: 10c0/c8822d175315bb353ebe782b65214ac53b13e3bf704e03b132ea7bdfa8de6a636375b3ab7a4097545393d109381c37c4f387c72a462c90b61412dbc4632f39a7 + languageName: node + linkType: hard + "fast-uri@npm:^3.0.1": version: 3.1.0 resolution: "fast-uri@npm:3.1.0" @@ -12066,6 +11574,15 @@ __metadata: languageName: node linkType: hard +"fast-wrap-ansi@npm:^0.2.0": + version: 0.2.0 + resolution: "fast-wrap-ansi@npm:0.2.0" + dependencies: + fast-string-width: "npm:^3.0.2" + checksum: 10c0/c0eb6debee565c5dbb9132dddff5c4d4aba5eb02185ae4dab285acd6186018cffca04264e92f373cbf592a9bcd1c33d65dba036030a8f3baeff1169969a1b59b + languageName: node + linkType: hard + "fast-xml-builder@npm:^1.1.5": version: 1.1.5 resolution: "fast-xml-builder@npm:1.1.5" @@ -12098,15 +11615,6 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.2": - version: 2.0.2 - resolution: "fb-watchman@npm:2.0.2" - dependencies: - bser: "npm:2.1.1" - checksum: 10c0/feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 - languageName: node - linkType: hard - "fdir@npm:^6.2.0, fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -12153,6 +11661,13 @@ __metadata: languageName: node linkType: hard +"fflate@npm:^0.8.2": + version: 0.8.2 + resolution: "fflate@npm:0.8.2" + checksum: 10c0/03448d630c0a583abea594835a9fdb2aaf7d67787055a761515bf4ed862913cfd693b4c4ffd5c3f3b355a70cf1e19033e9ae5aedcca103188aaff91b8bd6e293 + languageName: node + linkType: hard + "file-selector@npm:^0.4.0": version: 0.4.0 resolution: "file-selector@npm:0.4.0" @@ -12226,16 +11741,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^4.0.0, find-up@npm:^4.1.0": - version: 4.1.0 - resolution: "find-up@npm:4.1.0" - dependencies: - locate-path: "npm:^5.0.0" - path-exists: "npm:^4.0.0" - checksum: 10c0/0406ee89ebeefa2d507feb07ec366bebd8a6167ae74aa4e34fb4c4abd06cf782a3ce26ae4194d70706f72182841733f00551c209fe575cb00bd92104056e78c1 - languageName: node - linkType: hard - "find-yarn-workspace-root@npm:^2.0.0": version: 2.0.0 resolution: "find-yarn-workspace-root@npm:2.0.0" @@ -12245,6 +11750,13 @@ __metadata: languageName: node linkType: hard +"flatted@npm:^3.4.2": + version: 3.4.2 + resolution: "flatted@npm:3.4.2" + checksum: 10c0/a65b67aae7172d6cdf63691be7de6c5cd5adbdfdfe2e9da1a09b617c9512ed794037741ee53d93114276bff3f93cd3b0d97d54f9b316e1e4885dde6e9ffdf7ed + languageName: node + linkType: hard + "fn.name@npm:1.x.x": version: 1.1.0 resolution: "fn.name@npm:1.1.0" @@ -12495,7 +12007,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.3, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -12505,7 +12017,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -12619,13 +12131,6 @@ __metadata: languageName: node linkType: hard -"get-package-type@npm:^0.1.0": - version: 0.1.0 - resolution: "get-package-type@npm:0.1.0" - checksum: 10c0/e34cdf447fdf1902a1f6d5af737eaadf606d2ee3518287abde8910e04159368c268568174b2e71102b87b26c2020486f126bfca9c4fb1ceb986ff99b52ecd1be - languageName: node - linkType: hard - "get-paths@npm:0.0.7": version: 0.0.7 resolution: "get-paths@npm:0.0.7" @@ -12718,7 +12223,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.3.7, glob@npm:^10.4.2, glob@npm:^10.5.0": +"glob@npm:^10.3.7, glob@npm:^10.4.2": version: 10.5.0 resolution: "glob@npm:10.5.0" dependencies: @@ -12761,7 +12266,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0": +"glob@npm:^7.1.3, glob@npm:^7.1.6, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -12797,6 +12302,13 @@ __metadata: languageName: node linkType: hard +"globrex@npm:^0.1.2": + version: 0.1.2 + resolution: "globrex@npm:0.1.2" + checksum: 10c0/a54c029520cf58bda1d8884f72bd49b4cd74e977883268d931fd83bcbd1a9eb96d57c7dbd4ad80148fb9247467ebfb9b215630b2ed7563b2a8de02e1ff7f89d1 + languageName: node + linkType: hard + "gopd@npm:^1.0.1, gopd@npm:^1.2.0": version: 1.2.0 resolution: "gopd@npm:1.2.0" @@ -12804,7 +12316,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.8, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.8": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -12818,6 +12330,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^16.13.2": + version: 16.13.2 + resolution: "graphql@npm:16.13.2" + checksum: 10c0/64e822a0a0e4398781e4bc9765b88d370c08261498b517add4b878038ef7be2005b6b394a79a5102b9379d57052f60bc7f23fec8f39808d101984a74772ebd9d + languageName: node + linkType: hard + "gulp-sort@npm:^2.0.0": version: 2.0.0 resolution: "gulp-sort@npm:2.0.0" @@ -12927,6 +12446,16 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^5.0.1": + version: 5.0.1 + resolution: "headers-polyfill@npm:5.0.1" + dependencies: + "@types/set-cookie-parser": "npm:^2.4.10" + set-cookie-parser: "npm:^3.0.1" + checksum: 10c0/c269730a88a12c88718037aa71f178601f2b193ba8a37e276b6ced6b8f7e06fc1ac051f2a7acb0a8b4cc878407066555fdcdbb270e90374baaa472cb26af0c30 + languageName: node + linkType: hard + "heimdalljs-logger@npm:^0.1.10, heimdalljs-logger@npm:^0.1.7": version: 0.1.10 resolution: "heimdalljs-logger@npm:0.1.10" @@ -13021,22 +12550,6 @@ __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: "npm:^3.1.1" - checksum: 10c0/523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 - languageName: node - linkType: hard - -"html-escaper@npm:^2.0.0": - version: 2.0.2 - resolution: "html-escaper@npm:2.0.2" - checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 - languageName: node - linkType: hard - "html-parse-stringify@npm:^3.0.1": version: 3.0.1 resolution: "html-parse-stringify@npm:3.0.1" @@ -13137,7 +12650,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2": +"http-proxy-agent@npm:^7.0.0": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" dependencies: @@ -13343,18 +12856,6 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.2.0": - version: 3.2.0 - resolution: "import-local@npm:3.2.0" - dependencies: - pkg-dir: "npm:^4.2.0" - resolve-cwd: "npm:^3.0.0" - bin: - import-local-fixture: fixtures/cli.js - checksum: 10c0/94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 - languageName: node - linkType: hard - "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -13703,13 +13204,6 @@ __metadata: languageName: node linkType: hard -"is-generator-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "is-generator-fn@npm:2.1.0" - checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d - languageName: node - linkType: hard - "is-generator-function@npm:^1.0.10": version: 1.1.2 resolution: "is-generator-function@npm:1.1.2" @@ -13767,6 +13261,13 @@ __metadata: languageName: node linkType: hard +"is-node-process@npm:^1.2.0": + version: 1.2.0 + resolution: "is-node-process@npm:1.2.0" + checksum: 10c0/5b24fda6776d00e42431d7bcd86bce81cb0b6cabeb944142fe7b077a54ada2e155066ad06dbe790abdb397884bdc3151e04a9707b8cd185099efbc79780573ed + languageName: node + linkType: hard + "is-number-object@npm:^1.1.1": version: 1.1.1 resolution: "is-number-object@npm:1.1.1" @@ -14008,58 +13509,6 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": - version: 3.2.2 - resolution: "istanbul-lib-coverage@npm:3.2.2" - checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b - languageName: node - linkType: hard - -"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": - version: 6.0.3 - resolution: "istanbul-lib-instrument@npm:6.0.3" - dependencies: - "@babel/core": "npm:^7.23.9" - "@babel/parser": "npm:^7.23.9" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-coverage: "npm:^3.2.0" - semver: "npm:^7.5.4" - checksum: 10c0/a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 - languageName: node - linkType: hard - -"istanbul-lib-report@npm:^3.0.0": - version: 3.0.1 - resolution: "istanbul-lib-report@npm:3.0.1" - dependencies: - istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^4.0.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 - languageName: node - linkType: hard - -"istanbul-lib-source-maps@npm:^5.0.0": - version: 5.0.6 - resolution: "istanbul-lib-source-maps@npm:5.0.6" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.23" - debug: "npm:^4.1.1" - istanbul-lib-coverage: "npm:^3.0.0" - checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.1.3": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" - dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc - languageName: node - linkType: hard - "jackspeak@npm:^3.1.2": version: 3.4.3 resolution: "jackspeak@npm:3.4.3" @@ -14102,512 +13551,6 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:30.3.0": - version: 30.3.0 - resolution: "jest-changed-files@npm:30.3.0" - dependencies: - execa: "npm:^5.1.1" - jest-util: "npm:30.3.0" - p-limit: "npm:^3.1.0" - checksum: 10c0/5a2f9790f8ab7f5804ebbf0fcdd908c40286d602d76abbecc6bea72e7f3c60b77dc8a3d3f5acdddd11653b2574f471a5c126ceda0734bc6a7d607cf145843525 - languageName: node - linkType: hard - -"jest-circus@npm:30.3.0": - version: 30.3.0 - resolution: "jest-circus@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/expect": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - co: "npm:^4.6.0" - dedent: "npm:^1.6.0" - is-generator-fn: "npm:^2.1.0" - jest-each: "npm:30.3.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - p-limit: "npm:^3.1.0" - pretty-format: "npm:30.3.0" - pure-rand: "npm:^7.0.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/a3a0eb973699b400fb6de4207a7fbc5b33f51523e5e94f954d0e6e60418ea95099883614495fce54d805a321cb65e883592048b73203a59b8f4e53d1bb975a07 - languageName: node - linkType: hard - -"jest-cli@npm:^30.3.0": - version: 30.3.0 - resolution: "jest-cli@npm:30.3.0" - dependencies: - "@jest/core": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - exit-x: "npm:^0.2.2" - import-local: "npm:^3.2.0" - jest-config: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - yargs: "npm:^17.7.2" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: ./bin/jest.js - checksum: 10c0/764d77551e0fb6d666212e89d01be6f7bb1a2b3adb918bba7c5c37593a11b01cf2af645506c2b6438335cfc79bfcf41bfd4680958d8ca751851752a7c66269d3 - languageName: node - linkType: hard - -"jest-config@npm:30.3.0": - version: 30.3.0 - resolution: "jest-config@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/get-type": "npm:30.1.0" - "@jest/pattern": "npm:30.0.1" - "@jest/test-sequencer": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - babel-jest: "npm:30.3.0" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - deepmerge: "npm:^4.3.1" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-circus: "npm:30.3.0" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-runner: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - parse-json: "npm:^5.2.0" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - strip-json-comments: "npm:^3.1.1" - peerDependencies: - "@types/node": "*" - esbuild-register: ">=3.4.0" - ts-node: ">=9.0.0" - peerDependenciesMeta: - "@types/node": - optional: true - esbuild-register: - optional: true - ts-node: - optional: true - checksum: 10c0/157607e5ac5e83924df97d992fbd40a1540af07c5a7be296fae49455b3729687847304f3b4a9112e7da17593b76cec3453cd55c1ecd4334f7318f2489d7d10a1 - languageName: node - linkType: hard - -"jest-diff@npm:30.3.0": - version: 30.3.0 - resolution: "jest-diff@npm:30.3.0" - dependencies: - "@jest/diff-sequences": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - pretty-format: "npm:30.3.0" - checksum: 10c0/573a2a1a155b95fbde547d8ee33a5375179a8d03d4586025478dac16d695e4614aef075c3afa57e0f3a96cea8f638fa68a55c1e625f6e86b4f5b9e5850311ffb - languageName: node - linkType: hard - -"jest-diff@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-diff@npm:29.7.0" - dependencies: - chalk: "npm:^4.0.0" - diff-sequences: "npm:^29.6.3" - jest-get-type: "npm:^29.6.3" - pretty-format: "npm:^29.7.0" - checksum: 10c0/89a4a7f182590f56f526443dde69acefb1f2f0c9e59253c61d319569856c4931eae66b8a3790c443f529267a0ddba5ba80431c585deed81827032b2b2a1fc999 - languageName: node - linkType: hard - -"jest-docblock@npm:30.2.0": - version: 30.2.0 - resolution: "jest-docblock@npm:30.2.0" - dependencies: - detect-newline: "npm:^3.1.0" - checksum: 10c0/2578366604eef1b36d59ffe1fc52a710995571535d437f83d94ff94756a83f78e699c1ba004c38a34c01859d669fd6c64e865c23c5a7d5bf4837cfca4bef3dda - languageName: node - linkType: hard - -"jest-each@npm:30.3.0": - version: 30.3.0 - resolution: "jest-each@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - jest-util: "npm:30.3.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/d23d2b43b3ea42beaf99648e2cf1c74b8a13c3e45c7c882979171471c225f7d666cb4a0d5f1ff9031b4504866fa3badc7266ffd885d3d8035420c559a31501e1 - languageName: node - linkType: hard - -"jest-environment-jsdom@npm:^30.3.0": - version: 30.3.0 - resolution: "jest-environment-jsdom@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/environment-jsdom-abstract": "npm:30.3.0" - jsdom: "npm:^26.1.0" - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/1d9a288c847dc7d3fe0ac4bd494fa5f78581d5f7f1f28fd1f58073634f139b6e4d13d1ea1bbed8e68693f45b74279fb7ea002dd453faa98ab6ab657c443cc0ce - languageName: node - linkType: hard - -"jest-environment-node@npm:30.3.0": - version: 30.3.0 - resolution: "jest-environment-node@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - checksum: 10c0/2a4be80861e569fa11456d89ff2aaedd71726ae02ade8f2cc6fbc86ba8749e24c37864676c4718fc08a40f6e6d2b2b51bc48d715b09b1e93e15e42e4a10f7b5b - languageName: node - linkType: hard - -"jest-fetch-mock@npm:^3.0.3": - version: 3.0.3 - resolution: "jest-fetch-mock@npm:3.0.3" - dependencies: - cross-fetch: "npm:^3.0.4" - promise-polyfill: "npm:^8.1.3" - checksum: 10c0/21ffe8c902ca5adafa7ed61760e100e4c290e99b0b487645f5bb92938ea64c2d1d9dc8af46e65fb7917d6237586067d53af756583a77330dbb4fbda079a63c29 - languageName: node - linkType: hard - -"jest-get-type@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-get-type@npm:29.6.3" - checksum: 10c0/552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b - languageName: node - linkType: hard - -"jest-haste-map@npm:30.3.0": - version: 30.3.0 - resolution: "jest-haste-map@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - anymatch: "npm:^3.1.3" - fb-watchman: "npm:^2.0.2" - fsevents: "npm:^2.3.3" - graceful-fs: "npm:^4.2.11" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.3.0" - jest-worker: "npm:30.3.0" - picomatch: "npm:^4.0.3" - walker: "npm:^1.0.8" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/b9ef350082b15d4c119d6188f781024d859d6cfb17ae25d15c90c3a373234e16109afbeffdcf1af4baf6a85eb0cbbab00439c981ad43037c0f05d89ff98bd1af - languageName: node - linkType: hard - -"jest-leak-detector@npm:30.3.0": - version: 30.3.0 - resolution: "jest-leak-detector@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/a648c082b74e6c7d0c2e890002094ba97b108398fa3d0316958fc74321aa7b0824507a685d261a463856f219a724b86a6073bac86d351cf0675ecf962c1ee0ca - languageName: node - linkType: hard - -"jest-matcher-utils@npm:30.3.0": - version: 30.3.0 - resolution: "jest-matcher-utils@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - jest-diff: "npm:30.3.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/4c5f4b6435964110e64c4b5b42e3553fffe303ecdd68021147a7bcc72914aec3a899867c50db22b250c72aded53e3f7a9f64d83c9dca2e65ce27f36d23c6ca78 - languageName: node - linkType: hard - -"jest-matcher-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-matcher-utils@npm:29.7.0" - dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - pretty-format: "npm:^29.7.0" - checksum: 10c0/0d0e70b28fa5c7d4dce701dc1f46ae0922102aadc24ed45d594dd9b7ae0a8a6ef8b216718d1ab79e451291217e05d4d49a82666e1a3cc2b428b75cd9c933244e - languageName: node - linkType: hard - -"jest-message-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-message-util@npm:30.3.0" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@jest/types": "npm:30.3.0" - "@types/stack-utils": "npm:^2.0.3" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.3" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/6ce611caef76394872b23a111286b48e56f42655d14a5fbd0629d9b7437ed892e85ad96b15864bc22185c24ef670afb6665c57b9729458a36d50ffe8310f0926 - languageName: node - linkType: hard - -"jest-message-util@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-message-util@npm:29.7.0" - dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.6.3" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.7.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 10c0/850ae35477f59f3e6f27efac5215f706296e2104af39232bb14e5403e067992afb5c015e87a9243ec4d9df38525ef1ca663af9f2f4766aa116f127247008bd22 - languageName: node - linkType: hard - -"jest-mock@npm:30.3.0": - version: 30.3.0 - resolution: "jest-mock@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-util: "npm:30.3.0" - checksum: 10c0/9d95d550c6c998a85887c48ff5ee26de4bca18be91462ea8a8135d6023d591132465756f74981ca39b60f8708dfe38213a55bd4b619798a7b9438ca10d718099 - languageName: node - linkType: hard - -"jest-pnp-resolver@npm:^1.2.3": - version: 1.2.3 - resolution: "jest-pnp-resolver@npm:1.2.3" - peerDependencies: - jest-resolve: "*" - peerDependenciesMeta: - jest-resolve: - optional: true - checksum: 10c0/86eec0c78449a2de733a6d3e316d49461af6a858070e113c97f75fb742a48c2396ea94150cbca44159ffd4a959f743a47a8b37a792ef6fdad2cf0a5cba973fac - languageName: node - linkType: hard - -"jest-regex-util@npm:30.0.1": - version: 30.0.1 - resolution: "jest-regex-util@npm:30.0.1" - checksum: 10c0/f30c70524ebde2d1012afe5ffa5691d5d00f7d5ba9e43d588f6460ac6fe96f9e620f2f9b36a02d0d3e7e77bc8efb8b3450ae3b80ac53c8be5099e01bf54f6728 - languageName: node - linkType: hard - -"jest-resolve-dependencies@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve-dependencies@npm:30.3.0" - dependencies: - jest-regex-util: "npm:30.0.1" - jest-snapshot: "npm:30.3.0" - checksum: 10c0/25dde0c8c050bc3437332f37ab87484f597596b80ece77a93e4da2b466b42e45cc5ad748270c1477587536de15eea1ffe83a32638e824b120830c3a87c9a5b71 - languageName: node - linkType: hard - -"jest-resolve@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve@npm:30.3.0" - dependencies: - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-pnp-resolver: "npm:^1.2.3" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - slash: "npm:^3.0.0" - unrs-resolver: "npm:^1.7.11" - checksum: 10c0/540f59f160c232c1b922b111a93f24ef5202d75e00f2e994de976badf6e88879893b474320ff363a6b97259a7a208b6a4f5eeabede787eea9b7912a12ac64b1b - languageName: node - linkType: hard - -"jest-runner@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runner@npm:30.3.0" - dependencies: - "@jest/console": "npm:30.3.0" - "@jest/environment": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.3.0" - jest-haste-map: "npm:30.3.0" - jest-leak-detector: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-resolve: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-watcher: "npm:30.3.0" - jest-worker: "npm:30.3.0" - p-limit: "npm:^3.1.0" - source-map-support: "npm:0.5.13" - checksum: 10c0/6fb205f48541658f0b23b6c9a6730f0133f07c994a22ef506ebfcded5bbb444b655ac828074157e6579e664609a46f6a5bf3d366b694c6c8b523b5207a70499c - languageName: node - linkType: hard - -"jest-runtime@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runtime@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/globals": "npm:30.3.0" - "@jest/source-map": "npm:30.0.1" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - cjs-module-lexer: "npm:^2.1.0" - collect-v8-coverage: "npm:^1.0.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - slash: "npm:^3.0.0" - strip-bom: "npm:^4.0.0" - checksum: 10c0/79c486157a926d5be5c66356ad26cc3792cca1afb1490e255a550f52784b6c92eea42f1cb3b2c7565650ea777cf17ffc3f8e305d6b97888e7d273f6d7f282686 - languageName: node - linkType: hard - -"jest-snapshot@npm:30.3.0": - version: 30.3.0 - resolution: "jest-snapshot@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@babel/generator": "npm:^7.27.5" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - "@babel/types": "npm:^7.27.3" - "@jest/expect-utils": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - "@jest/snapshot-utils": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - chalk: "npm:^4.1.2" - expect: "npm:30.3.0" - graceful-fs: "npm:^4.2.11" - jest-diff: "npm:30.3.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - pretty-format: "npm:30.3.0" - semver: "npm:^7.7.2" - synckit: "npm:^0.11.8" - checksum: 10c0/c1dd295d9d4962f2504c965575212fc62a358a849c66ab96b2f6e608ebdf6a6029ca505bb0693664a54a534e581883665d404a59976a5b46b1a1f88b537e96c5 - languageName: node - linkType: hard - -"jest-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-util@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.3" - checksum: 10c0/eea6f39e52a8cb2b1a28bb315a90dc6a8e450fffed73bb5ef4489d02d86f7d91be600d83f1dcba22956b8ac5fefa8f1b250e636c8402d3e8b50a5eec8b5963b2 - languageName: node - linkType: hard - -"jest-util@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-util@npm:29.7.0" - dependencies: - "@jest/types": "npm:^29.6.3" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 10c0/bc55a8f49fdbb8f51baf31d2a4f312fb66c9db1483b82f602c9c990e659cdd7ec529c8e916d5a89452ecbcfae4949b21b40a7a59d4ffc0cd813a973ab08c8150 - languageName: node - linkType: hard - -"jest-validate@npm:30.3.0": - version: 30.3.0 - resolution: "jest-validate@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.3.0" - camelcase: "npm:^6.3.0" - chalk: "npm:^4.1.2" - leven: "npm:^3.1.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/645629e9ae0926252dee26b0ad71b9f0392daa896328393479c63b1b13d2a70df4dac8b5053227c64e0120e930db1242897898c40706f135f20f73ef77fcf4f5 - languageName: node - linkType: hard - -"jest-watcher@npm:30.3.0": - version: 30.3.0 - resolution: "jest-watcher@npm:30.3.0" - dependencies: - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - jest-util: "npm:30.3.0" - string-length: "npm:^4.0.2" - checksum: 10c0/2631be5cc122fbf14cb0bb7566cdea6d6c432b984d8ef3c6385254bb6c378342e0754cbd2dfe094d80762d44bd1c7015de2ec2100eb6f192906619d8b229e1a5 - languageName: node - linkType: hard - -"jest-worker@npm:30.3.0": - version: 30.3.0 - resolution: "jest-worker@npm:30.3.0" - dependencies: - "@types/node": "npm:*" - "@ungap/structured-clone": "npm:^1.3.0" - jest-util: "npm:30.3.0" - merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.1.1" - checksum: 10c0/25dfb1bc43d389e1daf8baad0ef7964249f001a7da7d92c61e398840424ca13fb1fb6242f6e021f0cbb37952f90371fb8be1ef0183b5d04ef161fdb8f09ee78e - languageName: node - linkType: hard - "jju@npm:~1.4.0": version: 1.4.0 resolution: "jju@npm:1.4.0" @@ -14707,39 +13650,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^26.1.0": - version: 26.1.0 - resolution: "jsdom@npm:26.1.0" - dependencies: - cssstyle: "npm:^4.2.1" - data-urls: "npm:^5.0.0" - decimal.js: "npm:^10.5.0" - html-encoding-sniffer: "npm:^4.0.0" - http-proxy-agent: "npm:^7.0.2" - https-proxy-agent: "npm:^7.0.6" - is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.16" - parse5: "npm:^7.2.1" - rrweb-cssom: "npm:^0.8.0" - saxes: "npm:^6.0.0" - symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^5.1.1" - w3c-xmlserializer: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^3.1.1" - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.1.1" - ws: "npm:^8.18.0" - xml-name-validator: "npm:^5.0.0" - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/5b14a5bc32ce077a06fb42d1ab95b1191afa5cbbce8859e3b96831c5143becbbcbf0511d4d4934e922d2901443ced2cdc3b734c1cf30b5f73b3e067ce457d0f4 - languageName: node - linkType: hard - "jsesc@npm:^3.0.2, jsesc@npm:~3.1.0": version: 3.1.0 resolution: "jsesc@npm:3.1.0" @@ -15252,99 +14162,99 @@ __metadata: languageName: node linkType: hard -"lightningcss-android-arm64@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-android-arm64@npm:1.30.2" +"lightningcss-android-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-android-arm64@npm:1.32.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-darwin-arm64@npm:1.30.2" +"lightningcss-darwin-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-arm64@npm:1.32.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-darwin-x64@npm:1.30.2" +"lightningcss-darwin-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-x64@npm:1.32.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-freebsd-x64@npm:1.30.2" +"lightningcss-freebsd-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-freebsd-x64@npm:1.32.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.2" +"lightningcss-linux-arm-gnueabihf@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.32.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-linux-arm64-gnu@npm:1.30.2" +"lightningcss-linux-arm64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.32.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-linux-arm64-musl@npm:1.30.2" +"lightningcss-linux-arm64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.32.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-linux-x64-gnu@npm:1.30.2" +"lightningcss-linux-x64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.32.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-linux-x64-musl@npm:1.30.2" +"lightningcss-linux-x64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-musl@npm:1.32.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-arm64-msvc@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-win32-arm64-msvc@npm:1.30.2" +"lightningcss-win32-arm64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-arm64-msvc@npm:1.32.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.30.2": - version: 1.30.2 - resolution: "lightningcss-win32-x64-msvc@npm:1.30.2" +"lightningcss-win32-x64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.32.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"lightningcss@npm:^1.30.2": - version: 1.30.2 - resolution: "lightningcss@npm:1.30.2" +"lightningcss@npm:^1.30.2, lightningcss@npm:^1.32.0": + version: 1.32.0 + resolution: "lightningcss@npm:1.32.0" dependencies: detect-libc: "npm:^2.0.3" - lightningcss-android-arm64: "npm:1.30.2" - lightningcss-darwin-arm64: "npm:1.30.2" - lightningcss-darwin-x64: "npm:1.30.2" - lightningcss-freebsd-x64: "npm:1.30.2" - lightningcss-linux-arm-gnueabihf: "npm:1.30.2" - lightningcss-linux-arm64-gnu: "npm:1.30.2" - lightningcss-linux-arm64-musl: "npm:1.30.2" - lightningcss-linux-x64-gnu: "npm:1.30.2" - lightningcss-linux-x64-musl: "npm:1.30.2" - lightningcss-win32-arm64-msvc: "npm:1.30.2" - lightningcss-win32-x64-msvc: "npm:1.30.2" + lightningcss-android-arm64: "npm:1.32.0" + lightningcss-darwin-arm64: "npm:1.32.0" + lightningcss-darwin-x64: "npm:1.32.0" + lightningcss-freebsd-x64: "npm:1.32.0" + lightningcss-linux-arm-gnueabihf: "npm:1.32.0" + lightningcss-linux-arm64-gnu: "npm:1.32.0" + lightningcss-linux-arm64-musl: "npm:1.32.0" + lightningcss-linux-x64-gnu: "npm:1.32.0" + lightningcss-linux-x64-musl: "npm:1.32.0" + lightningcss-win32-arm64-msvc: "npm:1.32.0" + lightningcss-win32-x64-msvc: "npm:1.32.0" dependenciesMeta: lightningcss-android-arm64: optional: true @@ -15368,7 +14278,7 @@ __metadata: optional: true lightningcss-win32-x64-msvc: optional: true - checksum: 10c0/5c0c73a33946dab65908d5cd1325df4efa290efb77f940b60f40448b5ab9a87d3ea665ef9bcf00df4209705050ecf2f7ecc649f44d6dfa5905bb50f15717e78d + checksum: 10c0/70945bd55097af46fc9fab7f5ed09cd5869d85940a2acab7ee06d0117004a1d68155708a2d462531cea2fc3c67aefc9333a7068c80b0b78dd404c16838809e03 languageName: node linkType: hard @@ -15425,6 +14335,13 @@ __metadata: languageName: node linkType: hard +"load-tsconfig@npm:^0.2.5": + version: 0.2.5 + resolution: "load-tsconfig@npm:0.2.5" + checksum: 10c0/bf2823dd26389d3497b6567f07435c5a7a58d9df82e879b0b3892f87d8db26900f84c85bc329ef41c0540c0d6a448d1c23ddc64a80f3ff6838b940f3915a3fcb + languageName: node + linkType: hard + "localforage@npm:^1.8.1": version: 1.10.0 resolution: "localforage@npm:1.10.0" @@ -15444,15 +14361,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^5.0.0": - version: 5.0.0 - resolution: "locate-path@npm:5.0.0" - dependencies: - p-locate: "npm:^4.1.0" - checksum: 10c0/33a1c5247e87e022f9713e6213a744557a3e9ec32c5d0b5efb10aa3a38177615bf90221a5592674857039c1a0fd2063b82f285702d37b792d973e9e72ace6c59 - languageName: node - linkType: hard - "lodash-es@npm:^4.18.1": version: 4.18.1 resolution: "lodash-es@npm:4.18.1" @@ -15656,7 +14564,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.2.0, lru-cache@npm:^10.4.3": +"lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb @@ -15711,6 +14619,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "mailparser@npm:^3.7.5": version: 3.9.8 resolution: "mailparser@npm:3.9.8" @@ -15739,15 +14656,6 @@ __metadata: languageName: node linkType: hard -"make-dir@npm:^4.0.0": - version: 4.0.0 - resolution: "make-dir@npm:4.0.0" - dependencies: - semver: "npm:^7.5.3" - checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 - languageName: node - linkType: hard - "make-fetch-happen@npm:^15.0.0": version: 15.0.3 resolution: "make-fetch-happen@npm:15.0.3" @@ -15767,15 +14675,6 @@ __metadata: languageName: node linkType: hard -"makeerror@npm:1.0.12": - version: 1.0.12 - resolution: "makeerror@npm:1.0.12" - dependencies: - tmpl: "npm:1.0.5" - checksum: 10c0/b0e6e599780ce6bab49cc413eba822f7d1f0dfebd1c103eaa3785c59e43e22c59018323cf9e1708f0ef5329e94a745d163fcbb6bff8e4c6742f9be9e86f3500c - languageName: node - linkType: hard - "mammoth@npm:^1.11.0": version: 1.11.0 resolution: "mammoth@npm:1.11.0" @@ -15937,7 +14836,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -16253,6 +15152,13 @@ __metadata: languageName: node linkType: hard +"mrmime@npm:^2.0.0": + version: 2.0.1 + resolution: "mrmime@npm:2.0.1" + checksum: 10c0/af05afd95af202fdd620422f976ad67dc18e6ee29beb03dd1ce950ea6ef664de378e44197246df4c7cdd73d47f2e7143a6e26e473084b9e4aa2095c0ad1e1761 + languageName: node + linkType: hard + "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -16310,6 +15216,46 @@ __metadata: languageName: node linkType: hard +"msw@npm:^2.14.2": + version: 2.14.2 + resolution: "msw@npm:2.14.2" + dependencies: + "@inquirer/confirm": "npm:^6.0.11" + "@mswjs/interceptors": "npm:^0.41.3" + "@open-draft/deferred-promise": "npm:^3.0.0" + "@types/statuses": "npm:^2.0.6" + cookie: "npm:^1.1.1" + graphql: "npm:^16.13.2" + headers-polyfill: "npm:^5.0.1" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + path-to-regexp: "npm:^6.3.0" + picocolors: "npm:^1.1.1" + rettime: "npm:^0.11.7" + statuses: "npm:^2.0.2" + strict-event-emitter: "npm:^0.5.1" + tough-cookie: "npm:^6.0.1" + type-fest: "npm:^5.5.0" + until-async: "npm:^3.0.2" + yargs: "npm:^17.7.2" + peerDependencies: + typescript: ">= 4.8.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: 10c0/85dcf819047167b925fcb55b19a38533697e2ea27f341f637a21d311482478ee568d87ccf4a65c388fb7e90c238976b6ae06db3271f53dbc99add2cbc6719b44 + languageName: node + linkType: hard + +"mute-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "mute-stream@npm:3.0.0" + checksum: 10c0/12cdb36a101694c7a6b296632e6d93a30b74401873cf7507c88861441a090c71c77a58f213acadad03bc0c8fa186639dec99d68a14497773a8744320c136e701 + languageName: node + linkType: hard + "mz@npm:^2.7.0": version: 2.7.0 resolution: "mz@npm:2.7.0" @@ -16346,22 +15292,6 @@ __metadata: languageName: node linkType: hard -"napi-postinstall@npm:^0.3.0": - version: 0.3.4 - resolution: "napi-postinstall@npm:0.3.4" - bin: - napi-postinstall: lib/cli.js - checksum: 10c0/b33d64150828bdade3a5d07368a8b30da22ee393f8dd8432f1b9e5486867be21c84ec443dd875dd3ef3c7401a079a7ab7e2aa9d3538a889abbcd96495d5104fe - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 10c0/f5f9a7974bfb28a91afafa254b197f0f22c684d4a1731763dda960d2c8e375b36c7d690e0d9dc8fba774c537af14a7e979129bca23d88d052fbeb9466955e447 - languageName: node - linkType: hard - "natural-sort@npm:^1.0.0": version: 1.0.0 resolution: "natural-sort@npm:1.0.0" @@ -16468,13 +15398,6 @@ __metadata: languageName: node linkType: hard -"node-int64@npm:^0.4.0": - version: 0.4.0 - resolution: "node-int64@npm:0.4.0" - checksum: 10c0/a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a - languageName: node - linkType: hard - "node-releases@npm:^2.0.36": version: 2.0.37 resolution: "node-releases@npm:2.0.37" @@ -16589,7 +15512,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.16, nwsapi@npm:^2.2.4": +"nwsapi@npm:^2.2.4": version: 2.2.23 resolution: "nwsapi@npm:2.2.23" checksum: 10c0/e44bfc9246baf659581206ed716d291a1905185247795fb8a302cb09315c943a31023b4ac4d026a5eaf32b2def51d77b3d0f9ebf4f3d35f70e105fcb6447c76e @@ -16652,6 +15575,13 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 + languageName: node + linkType: hard + "octokit@npm:^3.2.2": version: 3.2.2 resolution: "octokit@npm:3.2.2" @@ -16813,6 +15743,7 @@ __metadata: "@sentry/react": "npm:^7.120.4" "@simplewebauthn/browser": "npm:^13.3.0" "@simplewebauthn/server": "npm:^13.2.3" + "@swc/core": "npm:^1.15.32" "@tanstack/react-table": "npm:^8.21.3" "@tanstack/react-virtual": "npm:^3.13.24" "@types/addressparser": "npm:^1.0.3" @@ -16831,8 +15762,8 @@ __metadata: "@types/google.analytics": "npm:^0.0.46" "@types/invariant": "npm:^2.2.37" "@types/ioredis-mock": "npm:^8.2.7" - "@types/jest": "npm:^29.5.14" "@types/js-yaml": "npm:^4.0.9" + "@types/jsdom": "npm:^28.0.1" "@types/jsonwebtoken": "npm:^8.5.9" "@types/katex": "npm:^0.16.8" "@types/koa": "npm:^2.15.0" @@ -16883,9 +15814,9 @@ __metadata: "@types/validator": "npm:^13.15.10" "@types/yauzl": "npm:^2.10.3" "@vitejs/plugin-react-oxc": "npm:^0.2.3" + "@vitest/ui": "npm:^4.1.5" addressparser: "npm:^1.0.1" async-sema: "npm:^3.1.1" - babel-jest: "npm:^30.3.0" babel-plugin-module-resolver: "npm:^5.0.3" babel-plugin-styled-components: "npm:^2.1.4" babel-plugin-transform-inline-environment-variables: "npm:^0.4.4" @@ -16933,9 +15864,6 @@ __metadata: ipaddr.js: "npm:^2.3.0" is-printable-key-event: "npm:^1.0.0" iso-639-3: "npm:^3.0.1" - jest-cli: "npm:^30.3.0" - jest-environment-jsdom: "npm:^30.3.0" - jest-fetch-mock: "npm:^3.0.3" js-yaml: "npm:^4.1.1" jsdom: "npm:^22.1.0" jsonwebtoken: "npm:^9.0.3" @@ -16963,6 +15891,7 @@ __metadata: mobx: "npm:^4.15.7" mobx-react: "npm:^6.3.1" mobx-utils: "npm:^4.0.1" + msw: "npm:^2.14.2" natural-sort: "npm:^1.0.0" node-fetch: "npm:2.7.0" nodemailer: "npm:^7.0.13" @@ -17056,12 +15985,16 @@ __metadata: typescript: "npm:^5.9.3" ukkonen: "npm:^2.2.0" umzug: "npm:^3.8.2" + unplugin-swc: "npm:^1.5.9" utility-types: "npm:^3.11.0" uuid: "npm:^11.1.0" validator: "npm:13.15.35" vaul: "npm:^1.1.2" vite: "npm:rolldown-vite@7.3.1" + vite-plugin-babel: "npm:^1.6.0" vite-plugin-pwa: "npm:1.2.0" + vite-tsconfig-paths: "npm:^6.1.1" + vitest: "npm:^4.1.5" web-haptics: "npm:^0.0.6" winston: "npm:^3.17.0" ws: "npm:^7.5.10" @@ -17074,6 +16007,13 @@ __metadata: languageName: unknown linkType: soft +"outvariant@npm:^1.4.0, outvariant@npm:^1.4.3": + version: 1.4.3 + resolution: "outvariant@npm:1.4.3" + checksum: 10c0/5976ca7740349cb8c71bd3382e2a762b1aeca6f33dc984d9d896acdf3c61f78c3afcf1bfe9cc633a7b3c4b295ec94d292048f83ea2b2594fae4496656eba992c + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -17271,7 +16211,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": +"p-limit@npm:^2.0.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" dependencies: @@ -17280,15 +16220,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^3.1.0": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: "npm:^0.1.0" - checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -17298,15 +16229,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^4.1.0": - version: 4.1.0 - resolution: "p-locate@npm:4.1.0" - dependencies: - p-limit: "npm:^2.2.0" - checksum: 10c0/1b476ad69ad7f6059744f343b26d51ce091508935c1dbb80c4e0a2f397ffce0ca3a1f9f5cd3c7ce19d7929a09719d5c65fe70d8ee289c3f267cd36f2881813e9 - languageName: node - linkType: hard - "p-map@npm:^2.1.0": version: 2.1.0 resolution: "p-map@npm:2.1.0" @@ -17401,7 +16323,7 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0, parse5@npm:^7.1.2, parse5@npm:^7.2.1": +"parse5@npm:^7.0.0, parse5@npm:^7.1.2": version: 7.3.0 resolution: "parse5@npm:7.3.0" dependencies: @@ -17553,13 +16475,6 @@ __metadata: languageName: node linkType: hard -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b - languageName: node - linkType: hard - "path-expression-matcher@npm:^1.1.3, path-expression-matcher@npm:^1.5.0": version: 1.5.0 resolution: "path-expression-matcher@npm:1.5.0" @@ -17624,6 +16539,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^6.3.0": + version: 6.3.0 + resolution: "path-to-regexp@npm:6.3.0" + checksum: 10c0/73b67f4638b41cde56254e6354e46ae3a2ebc08279583f6af3d96fe4664fc75788f74ed0d18ca44fa4a98491b69434f9eee73b97bb5314bd1b5adb700f5c18d6 + languageName: node + linkType: hard + "path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.3.0": version: 8.4.2 resolution: "path-to-regexp@npm:8.4.2" @@ -17782,13 +16704,6 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.7": - version: 4.0.7 - resolution: "pirates@npm:4.0.7" - checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a - languageName: node - linkType: hard - "pkce-challenge@npm:^5.0.0": version: 5.0.1 resolution: "pkce-challenge@npm:5.0.1" @@ -17796,15 +16711,6 @@ __metadata: languageName: node linkType: hard -"pkg-dir@npm:^4.2.0": - version: 4.2.0 - resolution: "pkg-dir@npm:4.2.0" - dependencies: - find-up: "npm:^4.0.0" - checksum: 10c0/c56bda7769e04907a88423feb320babaed0711af8c436ce3e56763ab1021ba107c7b0cafb11cde7529f669cfc22bffcaebffb573645cbd63842ea9fb17cd7728 - languageName: node - linkType: hard - "pkg-types@npm:^1.3.1": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" @@ -17900,14 +16806,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.5.6": - version: 8.5.10 - resolution: "postcss@npm:8.5.10" +"postcss@npm:^8.5.10, postcss@npm:^8.5.6": + version: 8.5.13 + resolution: "postcss@npm:8.5.13" dependencies: nanoid: "npm:^3.3.11" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10c0/c592dffa0c4873b401f01955b265538d9942f425040df5e2b8f0ad34c83773a792ea0fa5859ccc99cfb5b955b4ebff118ab7056315388dc83b107b0fa8313576 + checksum: 10c0/3aa7c8cbdfbfd99b34406a433cef56d164dd135fc9cb9e63d487cc363291f877a55ec7b8ff6ec15348c17c2d98a43be46bfad671e6340403041a3e79f70c2f2f languageName: node linkType: hard @@ -17978,28 +16884,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:30.3.0": - version: 30.3.0 - resolution: "pretty-format@npm:30.3.0" - dependencies: - "@jest/schemas": "npm:30.0.5" - ansi-styles: "npm:^5.2.0" - react-is: "npm:^18.3.1" - checksum: 10c0/719b27d70cd8b01013485054c5d094e1fe85e093b09ee73553e3b19302da3cf54fbd6a7ea9577d6471aeff8d372200e56979ffc4c831e2133520bd18060895fb - languageName: node - linkType: hard - -"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": - version: 29.7.0 - resolution: "pretty-format@npm:29.7.0" - dependencies: - "@jest/schemas": "npm:^29.6.3" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f - languageName: node - linkType: hard - "pretty@npm:^2.0.0": version: 2.0.0 resolution: "pretty@npm:2.0.0" @@ -18046,13 +16930,6 @@ __metadata: languageName: node linkType: hard -"promise-polyfill@npm:^8.1.3": - version: 8.3.0 - resolution: "promise-polyfill@npm:8.3.0" - checksum: 10c0/97141f07a31a6be135ec9ed53700a3423a771cabec0ba5e08fcb2bf8cfda855479ff70e444fceb938f560be42b450cd032c14f4a940ed2ad1e5b4dcb78368dce - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -18316,13 +17193,6 @@ __metadata: languageName: node linkType: hard -"pure-rand@npm:^7.0.0": - version: 7.0.1 - resolution: "pure-rand@npm:7.0.1" - checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e - languageName: node - linkType: hard - "pvtsutils@npm:^1.3.6": version: 1.3.6 resolution: "pvtsutils@npm:1.3.6" @@ -18587,7 +17457,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.1 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.3.1": +"react-is@npm:^17.0.1 || ^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 @@ -19046,15 +17916,6 @@ __metadata: languageName: node linkType: hard -"resolve-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "resolve-cwd@npm:3.0.0" - dependencies: - resolve-from: "npm:^5.0.0" - checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 - languageName: node - linkType: hard - "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -19062,13 +17923,6 @@ __metadata: languageName: node linkType: hard -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2 - languageName: node - linkType: hard - "resolve-options@npm:^2.0.0": version: 2.0.0 resolution: "resolve-options@npm:2.0.0" @@ -19147,6 +18001,13 @@ __metadata: languageName: node linkType: hard +"rettime@npm:^0.11.7": + version: 0.11.8 + resolution: "rettime@npm:0.11.8" + checksum: 10c0/a0e53133e5d3345a60ca4a86f29e5b67715ce6de61427eb5bdd223c41e80789f62a926f9efd9524dee38d3ab968444096564e29263a9abd61f1695fdd1114867 + languageName: node + linkType: hard + "reusify@npm:^1.0.4": version: 1.1.0 resolution: "reusify@npm:1.1.0" @@ -19254,6 +18115,64 @@ __metadata: languageName: node linkType: hard +"rolldown@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "rolldown@npm:1.0.0-rc.17" + dependencies: + "@oxc-project/types": "npm:=0.127.0" + "@rolldown/binding-android-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-darwin-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-darwin-x64": "npm:1.0.0-rc.17" + "@rolldown/binding-freebsd-x64": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm64-musl": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-ppc64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-s390x-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-x64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-x64-musl": "npm:1.0.0-rc.17" + "@rolldown/binding-openharmony-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-wasm32-wasi": "npm:1.0.0-rc.17" + "@rolldown/binding-win32-arm64-msvc": "npm:1.0.0-rc.17" + "@rolldown/binding-win32-x64-msvc": "npm:1.0.0-rc.17" + "@rolldown/pluginutils": "npm:1.0.0-rc.17" + dependenciesMeta: + "@rolldown/binding-android-arm64": + optional: true + "@rolldown/binding-darwin-arm64": + optional: true + "@rolldown/binding-darwin-x64": + optional: true + "@rolldown/binding-freebsd-x64": + optional: true + "@rolldown/binding-linux-arm-gnueabihf": + optional: true + "@rolldown/binding-linux-arm64-gnu": + optional: true + "@rolldown/binding-linux-arm64-musl": + optional: true + "@rolldown/binding-linux-ppc64-gnu": + optional: true + "@rolldown/binding-linux-s390x-gnu": + optional: true + "@rolldown/binding-linux-x64-gnu": + optional: true + "@rolldown/binding-linux-x64-musl": + optional: true + "@rolldown/binding-openharmony-arm64": + optional: true + "@rolldown/binding-wasm32-wasi": + optional: true + "@rolldown/binding-win32-arm64-msvc": + optional: true + "@rolldown/binding-win32-x64-msvc": + optional: true + bin: + rolldown: bin/cli.mjs + checksum: 10c0/bb99abc62ece4e34edd06d2b8eb9ffb7194dc2f0465a4329bb106cbde3006a10f1575e3580b198b793341109a2109581aed623c537c12b0c3a4ba0d72169b2fb + languageName: node + linkType: hard + "rollup-plugin-stats@npm:1.5.6": version: 1.5.6 resolution: "rollup-plugin-stats@npm:1.5.6" @@ -19345,13 +18264,6 @@ __metadata: languageName: node linkType: hard -"rrweb-cssom@npm:^0.8.0": - version: 0.8.0 - resolution: "rrweb-cssom@npm:0.8.0" - checksum: 10c0/56f2bfd56733adb92c0b56e274c43f864b8dd48784d6fe946ef5ff8d438234015e59ad837fc2ad54714b6421384141c1add4eb569e72054e350d1f8a50b8ac7b - languageName: node - linkType: hard - "rsvp@npm:^4.8.2": version: 4.8.5 resolution: "rsvp@npm:4.8.5" @@ -19682,6 +18594,13 @@ __metadata: languageName: node linkType: hard +"set-cookie-parser@npm:^3.0.1": + version: 3.1.0 + resolution: "set-cookie-parser@npm:3.1.0" + checksum: 10c0/7465e389ff9fb7ff243fd55f0f48b5648d53a560903db170a7f766c2b82f22f4242c4d366fcdf12afdd376496f84058025d889e718459256ecbfc9a5fe7755f5 + languageName: node + linkType: hard + "set-function-length@npm:^1.2.2": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -19818,6 +18737,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.3": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -19841,6 +18767,17 @@ __metadata: languageName: node linkType: hard +"sirv@npm:^3.0.2": + version: 3.0.2 + resolution: "sirv@npm:3.0.2" + dependencies: + "@polka/url": "npm:^1.0.0-next.24" + mrmime: "npm:^2.0.0" + totalist: "npm:^3.0.0" + checksum: 10c0/5930e4397afdb14fbae13751c3be983af4bda5c9aadec832607dc2af15a7162f7d518c71b30e83ae3644b9a24cea041543cc969e5fe2b80af6ce8ea3174b2d04 + languageName: node + linkType: hard + "slash@npm:^2.0.0": version: 2.0.0 resolution: "slash@npm:2.0.0" @@ -19848,13 +18785,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 10c0/e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b - languageName: node - linkType: hard - "slice-ansi@npm:^7.1.0": version: 7.1.2 resolution: "slice-ansi@npm:7.1.2" @@ -20017,16 +18947,6 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:0.5.13": - version: 0.5.13 - resolution: "source-map-support@npm:0.5.13" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/137539f8c453fa0f496ea42049ab5da4569f96781f6ac8e5bfda26937be9494f4e8891f523c5f98f0e85f71b35d74127a00c46f83f6a4f54672b58d53202565e - languageName: node - linkType: hard - "source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" @@ -20141,12 +19061,10 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: "npm:^2.0.0" - checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 languageName: node linkType: hard @@ -20171,6 +19089,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^4.0.0-rc.1": + version: 4.1.0 + resolution: "std-env@npm:4.1.0" + checksum: 10c0/2e14b6b490db34cb969a48d9cf7c35bca4a47653914aac2814221baae7b867a5b15940d133625c391621971f98cd2266a5dc7036669960e883f1081db2a56558 + languageName: node + linkType: hard + "stop-iteration-iterator@npm:^1.1.0": version: 1.1.0 resolution: "stop-iteration-iterator@npm:1.1.0" @@ -20225,6 +19150,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 10c0/f5228a6e6b6393c57f52f62e673cfe3be3294b35d6f7842fc24b172ae0a6e6c209fa83241d0e433fc267c503bc2f4ffdbe41a9990ff8ffd5ac425ec0489417f7 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -20239,16 +19171,6 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.2": - version: 4.0.2 - resolution: "string-length@npm:4.0.2" - dependencies: - char-regex: "npm:^1.0.2" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/1cd77409c3d7db7bc59406f6bcc9ef0783671dcbabb23597a1177c166906ef2ee7c8290f78cae73a8aec858768f189d2cb417797df5e15ec4eb5e16b3346340c - languageName: node - linkType: hard - "string-replace-to-array@npm:^2.1.1": version: 2.1.1 resolution: "string-replace-to-array@npm:2.1.1" @@ -20405,13 +19327,6 @@ __metadata: languageName: node linkType: hard -"strip-bom@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-bom@npm:4.0.0" - checksum: 10c0/26abad1172d6bc48985ab9a5f96c21e440f6e7e476686de49be813b5a59b3566dccb5c525b831ec54fe348283b47f3ffb8e080bc3f965fde12e84df23f6bb7ef - languageName: node - linkType: hard - "strip-comments@npm:^2.0.1": version: 2.0.1 resolution: "strip-comments@npm:2.0.1" @@ -20426,13 +19341,6 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd - languageName: node - linkType: hard - "strnum@npm:^2.2.3": version: 2.2.3 resolution: "strnum@npm:2.2.3" @@ -20552,12 +19460,10 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.8": - version: 0.11.11 - resolution: "synckit@npm:0.11.11" - dependencies: - "@pkgr/core": "npm:^0.2.9" - checksum: 10c0/f0761495953d12d94a86edf6326b3a565496c72f9b94c02549b6961fb4d999f4ca316ce6b3eb8ed2e4bfc5056a8de65cda0bd03a233333a35221cd2fdc0e196b +"tagged-tag@npm:^1.0.0": + version: 1.0.0 + resolution: "tagged-tag@npm:1.0.0" + checksum: 10c0/91d25c9ffb86a91f20522cefb2cbec9b64caa1febe27ad0df52f08993ff60888022d771e868e6416cf2e72dab68449d2139e8709ba009b74c6c7ecd4000048d1 languageName: node linkType: hard @@ -20616,17 +19522,6 @@ __metadata: languageName: node linkType: hard -"test-exclude@npm:^6.0.0": - version: 6.0.0 - resolution: "test-exclude@npm:6.0.0" - dependencies: - "@istanbuljs/schema": "npm:^0.1.2" - glob: "npm:^7.1.4" - minimatch: "npm:^3.0.4" - checksum: 10c0/019d33d81adff3f9f1bfcff18125fb2d3c65564f437d9be539270ee74b994986abb8260c7c2ce90e8f30162178b09dbbce33c6389273afac4f36069c48521f57 - languageName: node - linkType: hard - "text-decoder@npm:^1.1.0": version: 1.2.3 resolution: "text-decoder@npm:1.2.3" @@ -20701,20 +19596,34 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^1.0.1, tinyexec@npm:^1.0.4": - version: 1.1.1 - resolution: "tinyexec@npm:1.1.1" - checksum: 10c0/48433cb32573a767e2b63bb92343cbbae4240d05a19a63f7869f9447491305e7bd82d11daccb79b2628b596ad703a25798226c50bfd1d8e63477fb42af6a5b35 +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c languageName: node linkType: hard -"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": - version: 0.2.15 - resolution: "tinyglobby@npm:0.2.15" +"tinyexec@npm:^1.0.1, tinyexec@npm:^1.0.2, tinyexec@npm:^1.0.4": + version: 1.1.2 + resolution: "tinyexec@npm:1.1.2" + checksum: 10c0/9e0ef6c001ce54688cf16833a02f70a339276219ca947b88930b124267de2cffc764ff44e87e7369384b1d75ab63491465412cbbdf06f2437956b9ab66ab4491 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.16": + version: 0.2.16 + resolution: "tinyglobby@npm:0.2.16" dependencies: fdir: "npm:^6.5.0" - picomatch: "npm:^4.0.3" - checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 + picomatch: "npm:^4.0.4" + checksum: 10c0/f2e09fd93dd95c41e522113b686ff6f7c13020962f8698a864a257f3d7737599afc47722b7ab726e12f8a813f779906187911ff8ee6701ede65072671a7e934b + languageName: node + linkType: hard + +"tinyrainbow@npm:^3.1.0": + version: 3.1.0 + resolution: "tinyrainbow@npm:3.1.0" + checksum: 10c0/f11cf387a26c5c9255bec141a90ac511b26172981b10c3e50053bc6700ea7d2336edcc4a3a21dbb8412fe7c013477d2ba4d7e4877800f3f8107be5105aad6511 languageName: node linkType: hard @@ -20727,21 +19636,21 @@ __metadata: languageName: node linkType: hard -"tldts-core@npm:^6.1.86": - version: 6.1.86 - resolution: "tldts-core@npm:6.1.86" - checksum: 10c0/8133c29375f3f99f88fce5f4d62f6ecb9532b106f31e5423b27c1eb1b6e711bd41875184a456819ceaed5c8b94f43911b1ad57e25c6eb86e1fc201228ff7e2af +"tldts-core@npm:^7.0.30": + version: 7.0.30 + resolution: "tldts-core@npm:7.0.30" + checksum: 10c0/e3cd730e96b0e9c0332fcaab44d0257b668f9089644508e4f6f870d37bbf5c218243b7e83aa39690c87b386d1b0ad577772a5994969c4c81cc25a476f783ccd7 languageName: node linkType: hard -"tldts@npm:^6.1.32": - version: 6.1.86 - resolution: "tldts@npm:6.1.86" +"tldts@npm:^7.0.5": + version: 7.0.30 + resolution: "tldts@npm:7.0.30" dependencies: - tldts-core: "npm:^6.1.86" + tldts-core: "npm:^7.0.30" bin: tldts: bin/cli.js - checksum: 10c0/27ae7526d9d78cb97b2de3f4d102e0b4321d1ccff0648a7bb0e039ed54acbce86bacdcd9cd3c14310e519b457854e7bafbef1f529f58a1e217a737ced63f0940 + checksum: 10c0/c36f7b480f09128303158e4738a82426c33e8da9f77d4fb57a2d5ef5896c803d7a3c1d53ade965712f9cb4946935139b6d192a18698665556ca504493c7c265e languageName: node linkType: hard @@ -20752,13 +19661,6 @@ __metadata: languageName: node linkType: hard -"tmpl@npm:1.0.5": - version: 1.0.5 - resolution: "tmpl@npm:1.0.5" - checksum: 10c0/f935537799c2d1922cb5d6d3805f594388f75338fe7a4a9dac41504dd539704ca4db45b883b52e7b0aa5b2fd5ddadb1452bf95cd23a69da2f793a843f9451cc9 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -20798,6 +19700,13 @@ __metadata: languageName: node linkType: hard +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 10c0/4bb1fadb69c3edbef91c73ebef9d25b33bbf69afe1e37ce544d5f7d13854cda15e47132f3e0dc4cafe300ddb8578c77c50a65004d8b6e97e77934a69aa924863 + languageName: node + linkType: hard + "touch@npm:^3.1.0": version: 3.1.1 resolution: "touch@npm:3.1.1" @@ -20819,12 +19728,12 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^5.1.1": - version: 5.1.2 - resolution: "tough-cookie@npm:5.1.2" +"tough-cookie@npm:^6.0.1": + version: 6.0.1 + resolution: "tough-cookie@npm:6.0.1" dependencies: - tldts: "npm:^6.1.32" - checksum: 10c0/5f95023a47de0f30a902bba951664b359725597d8adeabc66a0b93a931c3af801e1e697dae4b8c21a012056c0ea88bd2bf4dfe66b2adcf8e2f42cd9796fe0626 + tldts: "npm:^7.0.5" + checksum: 10c0/ec70bd6b1215efe4ed31a158f0be3e4c9088fcbd8620edc23a5860d4f3d85c757b77e274baaa700f7b25e409f4181552ed189603c2b2e1a9f88104da3a61a37d languageName: node linkType: hard @@ -20846,15 +19755,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^5.1.0": - version: 5.1.1 - resolution: "tr46@npm:5.1.1" - dependencies: - punycode: "npm:^2.3.1" - checksum: 10c0/ae270e194d52ec67ebd695c1a42876e0f19b96e4aca2ab464ab1d9d17dc3acd3e18764f5034c93897db73421563be27c70c98359c4501136a497e46deda5d5ec - languageName: node - linkType: hard - "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -20904,6 +19804,20 @@ __metadata: languageName: node linkType: hard +"tsconfck@npm:^3.0.3": + version: 3.1.6 + resolution: "tsconfck@npm:3.1.6" + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + bin: + tsconfck: bin/tsconfck.js + checksum: 10c0/269c3c513540be44844117bb9b9258fe6f8aeab026d32aeebf458d5299125f330711429dbb556dbf125a0bc25f4a81e6c24ac96de2740badd295c3fb400f66c4 + languageName: node + linkType: hard + "tslib@npm:2.8.1, tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -20943,13 +19857,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd - languageName: node - linkType: hard - "type-fest@npm:^0.16.0": version: 0.16.0 resolution: "type-fest@npm:0.16.0" @@ -20957,13 +19864,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.21.3": - version: 0.21.3 - resolution: "type-fest@npm:0.21.3" - checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 - languageName: node - linkType: hard - "type-fest@npm:^4.0.0": version: 4.41.0 resolution: "type-fest@npm:4.41.0" @@ -20971,6 +19871,15 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^5.5.0": + version: 5.6.0 + resolution: "type-fest@npm:5.6.0" + dependencies: + tagged-tag: "npm:^1.0.0" + checksum: 10c0/5468a8ffda7f3904e6f7bbd8069eb8b6dd4bd9156e206df7a01d09a73e28cd1afedf74ead9d0fc12841c8c90074194859feca240511c50800962fde1bd9ddcbc + languageName: node + linkType: hard + "type-is@npm:2.0.1, type-is@npm:^2.0.1": version: 2.0.1 resolution: "type-is@npm:2.0.1" @@ -21165,6 +20074,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:^7.21.0": + version: 7.25.0 + resolution: "undici-types@npm:7.25.0" + checksum: 10c0/b30edc6d3a0aa0f1f4e0f4f56dc08b81ffbecc27e3b142b1363555104b076f9eebaa61dfd835d91a8341ad6c5e6f789ed2161f75b80855378828cd93ad7c9d26 + languageName: node + linkType: hard + "undici-types@npm:~6.21.0": version: 6.21.0 resolution: "undici-types@npm:6.21.0" @@ -21300,70 +20216,35 @@ __metadata: languageName: node linkType: hard -"unrs-resolver@npm:^1.7.11": - version: 1.11.1 - resolution: "unrs-resolver@npm:1.11.1" +"unplugin-swc@npm:^1.5.9": + version: 1.5.9 + resolution: "unplugin-swc@npm:1.5.9" dependencies: - "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" - "@unrs/resolver-binding-android-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" - "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" - "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" - "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" - napi-postinstall: "npm:^0.3.0" - dependenciesMeta: - "@unrs/resolver-binding-android-arm-eabi": - optional: true - "@unrs/resolver-binding-android-arm64": - optional: true - "@unrs/resolver-binding-darwin-arm64": - optional: true - "@unrs/resolver-binding-darwin-x64": - optional: true - "@unrs/resolver-binding-freebsd-x64": - optional: true - "@unrs/resolver-binding-linux-arm-gnueabihf": - optional: true - "@unrs/resolver-binding-linux-arm-musleabihf": - optional: true - "@unrs/resolver-binding-linux-arm64-gnu": - optional: true - "@unrs/resolver-binding-linux-arm64-musl": - optional: true - "@unrs/resolver-binding-linux-ppc64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-musl": - optional: true - "@unrs/resolver-binding-linux-s390x-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-musl": - optional: true - "@unrs/resolver-binding-wasm32-wasi": - optional: true - "@unrs/resolver-binding-win32-arm64-msvc": - optional: true - "@unrs/resolver-binding-win32-ia32-msvc": - optional: true - "@unrs/resolver-binding-win32-x64-msvc": - optional: true - checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 + "@rollup/pluginutils": "npm:^5.3.0" + load-tsconfig: "npm:^0.2.5" + unplugin: "npm:^2.3.11" + peerDependencies: + "@swc/core": ^1.2.108 + checksum: 10c0/c5e945d1476ee0d3f1932dc6b3a94d876885f7f1b4496697aa678214e45cb022344d459a297dbf31e9af6de1a3fb078a4946081539da04b30b63c4f9d8475886 + languageName: node + linkType: hard + +"unplugin@npm:^2.3.11": + version: 2.3.11 + resolution: "unplugin@npm:2.3.11" + dependencies: + "@jridgewell/remapping": "npm:^2.3.5" + acorn: "npm:^8.15.0" + picomatch: "npm:^4.0.3" + webpack-virtual-modules: "npm:^0.6.2" + checksum: 10c0/273c1eab0eca4470c7317428689295c31dbe8ab0b306504de9f03cd20c156debb4131bef24b27ac615862958c5dd950a3951d26c0723ea774652ab3624149cff + languageName: node + linkType: hard + +"until-async@npm:^3.0.2": + version: 3.0.2 + resolution: "until-async@npm:3.0.2" + checksum: 10c0/61c8b03895dbe18fe3d90316d0a1894e0c131ea4b1673f6ce78eed993d0bb81bbf4b7adf8477e9ff7725782a76767eed9d077561cfc9f89b4a1ebe61f7c9828e languageName: node linkType: hard @@ -21500,17 +20381,6 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^9.0.1": - version: 9.3.0 - resolution: "v8-to-istanbul@npm:9.3.0" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.12" - "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^2.0.0" - checksum: 10c0/968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 - languageName: node - linkType: hard - "validator@npm:13.15.35, validator@npm:^13.15.22, validator@npm:^13.9.0": version: 13.15.35 resolution: "validator@npm:13.15.35" @@ -21609,6 +20479,16 @@ __metadata: languageName: node linkType: hard +"vite-plugin-babel@npm:^1.6.0": + version: 1.6.0 + resolution: "vite-plugin-babel@npm:1.6.0" + peerDependencies: + "@babel/core": ^7.0.0 + vite: ^2.7.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10c0/7484bff317cdb988a65613a1c788cd6b9682df66f5cf5226831898678f2811c4d14a8a14519b15c9896b8e8483e9b4b4d5fb519dab3bb497e0952ebc1911fd99 + languageName: node + linkType: hard + "vite-plugin-pwa@npm:1.2.0": version: 1.2.0 resolution: "vite-plugin-pwa@npm:1.2.0" @@ -21630,6 +20510,76 @@ __metadata: languageName: node linkType: hard +"vite-tsconfig-paths@npm:^6.1.1": + version: 6.1.1 + resolution: "vite-tsconfig-paths@npm:6.1.1" + dependencies: + debug: "npm:^4.1.1" + globrex: "npm:^0.1.2" + tsconfck: "npm:^3.0.3" + peerDependencies: + vite: "*" + checksum: 10c0/5e61080991418fefa08c5b98995cdcada4931ae01ac97ef9e2ee941051f61b76890a6e7ba48bed3b2a229ec06fef33a06621bba4ce457b3f4233ad31dc0c1d1b + languageName: node + linkType: hard + +"vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.0.10 + resolution: "vite@npm:8.0.10" + dependencies: + fsevents: "npm:~2.3.3" + lightningcss: "npm:^1.32.0" + picomatch: "npm:^4.0.4" + postcss: "npm:^8.5.10" + rolldown: "npm:1.0.0-rc.17" + tinyglobby: "npm:^0.2.16" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + "@vitejs/devtools": ^0.1.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: ">=1.21.0" + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + "@vitejs/devtools": + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/92188b82654f856dbe562a1b679de695bb6ca18c0f43c4c276f84a869fb78e22dedb7c2df83b5617d6afdca979c059d654b5f61a0936a45f49917f352b9325ca + languageName: node + linkType: hard + "vite@npm:rolldown-vite@7.3.1": version: 7.3.1 resolution: "rolldown-vite@npm:7.3.1" @@ -21686,6 +20636,74 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^4.1.5": + version: 4.1.5 + resolution: "vitest@npm:4.1.5" + dependencies: + "@vitest/expect": "npm:4.1.5" + "@vitest/mocker": "npm:4.1.5" + "@vitest/pretty-format": "npm:4.1.5" + "@vitest/runner": "npm:4.1.5" + "@vitest/snapshot": "npm:4.1.5" + "@vitest/spy": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + es-module-lexer: "npm:^2.0.0" + expect-type: "npm:^1.3.0" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^4.0.0-rc.1" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.1.0" + vite: "npm:^6.0.0 || ^7.0.0 || ^8.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.1.5 + "@vitest/browser-preview": 4.1.5 + "@vitest/browser-webdriverio": 4.1.5 + "@vitest/coverage-istanbul": 4.1.5 + "@vitest/coverage-v8": 4.1.5 + "@vitest/ui": 4.1.5 + happy-dom: "*" + jsdom: "*" + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/coverage-istanbul": + optional: true + "@vitest/coverage-v8": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vite: + optional: false + bin: + vitest: vitest.mjs + checksum: 10c0/196eaf5e95b45a3f6d3001a2408d7dc6f146c29c873ed4e42e1ad4c9327122934fb3793a12b6ce3b7c25d355e738b20123acc0894ce30358c3370b15f4bd0865 + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -21768,15 +20786,6 @@ __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: "npm:^5.0.0" - checksum: 10c0/8712774c1aeb62dec22928bf1cdfd11426c2c9383a1a63f2bcae18db87ca574165a0fbe96b312b73652149167ac6c7f4cf5409f2eb101d9c805efe0e4bae798b - languageName: node - linkType: hard - "walk-sync@npm:^2.2.0": version: 2.2.0 resolution: "walk-sync@npm:2.2.0" @@ -21789,15 +20798,6 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.8": - version: 1.0.8 - resolution: "walker@npm:1.0.8" - dependencies: - makeerror: "npm:1.0.12" - checksum: 10c0/a17e037bccd3ca8a25a80cb850903facdfed0de4864bd8728f1782370715d679fa72e0a0f5da7c1c1379365159901e5935f35be531229da53bbfc0efdabdb48e - languageName: node - linkType: hard - "warning@npm:^4.0.3": version: 4.0.3 resolution: "warning@npm:4.0.3" @@ -21849,6 +20849,13 @@ __metadata: languageName: node linkType: hard +"webpack-virtual-modules@npm:^0.6.2": + version: 0.6.2 + resolution: "webpack-virtual-modules@npm:0.6.2" + checksum: 10c0/5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add + languageName: node + linkType: hard + "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -21858,15 +20865,6 @@ __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: "npm:0.6.3" - checksum: 10c0/273b5f441c2f7fda3368a496c3009edbaa5e43b71b09728f90425e7f487e5cef9eb2b846a31bd760dd8077739c26faf6b5ca43a5f24033172b003b72cf61a93e - languageName: node - linkType: hard - "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0" @@ -21874,13 +20872,6 @@ __metadata: languageName: node linkType: hard -"whatwg-mimetype@npm:^4.0.0": - version: 4.0.0 - resolution: "whatwg-mimetype@npm:4.0.0" - checksum: 10c0/a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df - 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" @@ -21891,16 +20882,6 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^14.0.0, whatwg-url@npm:^14.1.1": - version: 14.2.0 - resolution: "whatwg-url@npm:14.2.0" - dependencies: - tr46: "npm:^5.1.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10c0/f746fc2f4c906607d09537de1227b13f9494c171141e5427ed7d2c0dd0b6a48b43d8e71abaae57d368d0c06b673fd8ec63550b32ad5ed64990c7b0266c2b4272 - languageName: node - linkType: hard - "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -22016,6 +20997,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + languageName: node + linkType: hard + "winston-transport@npm:^4.9.0": version: 4.9.0 resolution: "winston-transport@npm:4.9.0" @@ -22285,17 +21278,7 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: "npm:^0.1.4" - signal-exit: "npm:^4.0.1" - checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d - languageName: node - linkType: hard - -"ws@npm:*, ws@npm:^8.13.0, ws@npm:^8.18.0, ws@npm:^8.5.0": +"ws@npm:*, ws@npm:^8.13.0, ws@npm:^8.5.0": version: 8.20.0 resolution: "ws@npm:8.20.0" peerDependencies: @@ -22354,13 +21337,6 @@ __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: 10c0/3fcf44e7b73fb18be917fdd4ccffff3639373c7cb83f8fc35df6001fecba7942f1dbead29d91ebb8315e2f2ff786b508f0c9dc0215b6353f9983c6b7d62cb1f5 - languageName: node - linkType: hard - "xmlbuilder@npm:^10.0.0": version: 10.1.1 resolution: "xmlbuilder@npm:10.1.1" @@ -22526,13 +21502,6 @@ __metadata: languageName: node linkType: hard -"yocto-queue@npm:^0.1.0": - version: 0.1.0 - resolution: "yocto-queue@npm:0.1.0" - checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f - languageName: node - linkType: hard - "yocto-spinner@npm:^1.1.0": version: 1.1.0 resolution: "yocto-spinner@npm:1.1.0"