From 4bd51d74047cb5d35fe5a8218b0c36a23d62c645 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:37:12 +0100 Subject: [PATCH 1/9] fix: self-reference parent page --- apps/server/src/core/page/services/page.service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/server/src/core/page/services/page.service.ts b/apps/server/src/core/page/services/page.service.ts index aad9b1cf3..387abc5cc 100644 --- a/apps/server/src/core/page/services/page.service.ts +++ b/apps/server/src/core/page/services/page.service.ts @@ -810,6 +810,10 @@ export class PageService { throw new BadRequestException('Invalid move position'); } + if (dto.parentPageId && dto.parentPageId === dto.pageId) { + throw new BadRequestException('A page cannot be its own parent'); + } + let parentPageId = null; if (movedPage.parentPageId === dto.parentPageId) { parentPageId = undefined; From 305fd40686fc73a032ef2859539114ce99af5e39 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:38:03 +0100 Subject: [PATCH 2/9] fix: browser tab showing url instead of page title (#2382) --- .../src/components/ui/document-title.test.tsx | 45 +++++++++++++++++++ .../src/components/ui/document-title.tsx | 29 ++++++++++++ apps/client/src/components/ui/error-404.tsx | 6 +-- apps/client/src/ee/ai/pages/ai-settings.tsx | 7 +-- .../src/ee/api-key/pages/user-api-keys.tsx | 10 ++--- .../ee/api-key/pages/workspace-api-keys.tsx | 9 +--- apps/client/src/ee/audit/pages/audit-logs.tsx | 9 +--- apps/client/src/ee/billing/pages/billing.tsx | 7 +-- apps/client/src/ee/licence/pages/license.tsx | 7 +-- .../pages/verified-pages.tsx | 9 +--- apps/client/src/ee/pages/cloud-login.tsx | 9 +--- apps/client/src/ee/pages/create-workspace.tsx | 7 +-- .../client/src/ee/security/pages/security.tsx | 8 ++-- .../src/ee/template/pages/template-editor.tsx | 9 +--- .../src/ee/template/pages/template-list.tsx | 9 +--- .../client/src/pages/auth/forgot-password.tsx | 7 +-- apps/client/src/pages/auth/invite-signup.tsx | 7 +-- apps/client/src/pages/auth/login.tsx | 9 +--- apps/client/src/pages/auth/password-reset.tsx | 15 ++----- .../client/src/pages/auth/setup-workspace.tsx | 9 +--- apps/client/src/pages/dashboard/home.tsx | 9 +--- apps/client/src/pages/label/label-page.tsx | 9 +--- apps/client/src/pages/page/page.tsx | 16 ++++--- .../settings/account/account-preferences.tsx | 9 +--- .../settings/account/account-settings.tsx | 9 +--- .../src/pages/settings/group/group-info.tsx | 9 +--- .../src/pages/settings/group/groups.tsx | 7 +-- .../src/pages/settings/shares/shares.tsx | 9 +--- .../src/pages/settings/space/spaces.tsx | 9 +--- .../settings/workspace/workspace-members.tsx | 9 +--- .../settings/workspace/workspace-settings.tsx | 8 ++-- apps/client/src/pages/share/shared-page.tsx | 10 +++-- apps/client/src/pages/space/space-home.tsx | 7 +-- apps/client/src/pages/spaces/spaces.tsx | 9 +--- 34 files changed, 153 insertions(+), 203 deletions(-) create mode 100644 apps/client/src/components/ui/document-title.test.tsx create mode 100644 apps/client/src/components/ui/document-title.tsx diff --git a/apps/client/src/components/ui/document-title.test.tsx b/apps/client/src/components/ui/document-title.test.tsx new file mode 100644 index 000000000..1376bc3a6 --- /dev/null +++ b/apps/client/src/components/ui/document-title.test.tsx @@ -0,0 +1,45 @@ +import { describe, expect, it, beforeEach } from "vitest"; +import { render } from "@testing-library/react"; +import { HelmetProvider } from "react-helmet-async"; +import { DocumentTitle } from "./document-title.tsx"; + +const renderTitle = (ui: React.ReactNode) => + render({ui}); + +describe("DocumentTitle", () => { + beforeEach(() => { + document.head.innerHTML = "Docmost"; + }); + + it("appends the app name", () => { + renderTitle(); + expect(document.title).toBe("Home - Docmost"); + }); + + it("omits the app name when asked", () => { + renderTitle(); + expect(document.title).toBe("My page"); + }); + + it("falls back to the app name without a title", () => { + renderTitle(); + expect(document.title).toBe("Docmost"); + }); + + it("never renders an empty title", () => { + renderTitle(); + const titles = Array.from(document.querySelectorAll("head > title")); + expect(titles.every((node) => node.textContent !== "")).toBe(true); + }); + + it("renders extra head children", () => { + renderTitle( + + + , + ); + expect( + document.querySelector('head > meta[name="robots"]')?.getAttribute("content"), + ).toBe("noindex"); + }); +}); diff --git a/apps/client/src/components/ui/document-title.tsx b/apps/client/src/components/ui/document-title.tsx new file mode 100644 index 000000000..fe878fd5a --- /dev/null +++ b/apps/client/src/components/ui/document-title.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { Helmet } from "react-helmet-async"; +import { getAppName } from "@/lib/config.ts"; + +type DocumentTitleProps = { + title?: string; + withAppName?: boolean; + children?: React.ReactNode; +}; + +export function DocumentTitle({ + title, + withAppName = true, + children, +}: DocumentTitleProps) { + const appName = getAppName(); + + let documentTitle = appName; + if (title) { + documentTitle = withAppName ? `${title} - ${appName}` : title; + } + + return ( + + {documentTitle} + {children} + + ); +} diff --git a/apps/client/src/components/ui/error-404.tsx b/apps/client/src/components/ui/error-404.tsx index 8c8846aeb..3065b7ecc 100644 --- a/apps/client/src/components/ui/error-404.tsx +++ b/apps/client/src/components/ui/error-404.tsx @@ -1,17 +1,15 @@ import { Title, Text, Button, Container, Group } from "@mantine/core"; import classes from "./error-404.module.css"; import { Link } from "react-router-dom"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export function Error404() { const { t } = useTranslation(); return ( <> - - {t("404 page not found")} - Docmost - + {t("404 page not found")} diff --git a/apps/client/src/ee/ai/pages/ai-settings.tsx b/apps/client/src/ee/ai/pages/ai-settings.tsx index 3a5a281ef..ad678bbcb 100644 --- a/apps/client/src/ee/ai/pages/ai-settings.tsx +++ b/apps/client/src/ee/ai/pages/ai-settings.tsx @@ -1,5 +1,3 @@ -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import SettingsTitle from "@/components/settings/settings-title.tsx"; import React from "react"; import useUserRole from "@/hooks/use-user-role.tsx"; @@ -15,6 +13,7 @@ import { Feature } from "@/ee/features"; import { useUpgradeLabel } from "@/ee/hooks/use-upgrade-label"; import { isCloud } from "@/lib/config.ts"; import { useLocation, useNavigate } from "react-router-dom"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function AiSettings() { const { t } = useTranslation(); @@ -40,9 +39,7 @@ export default function AiSettings() { return ( <> - - AI settings - {getAppName()} - + diff --git a/apps/client/src/ee/api-key/pages/user-api-keys.tsx b/apps/client/src/ee/api-key/pages/user-api-keys.tsx index c305f4afb..2b2572200 100644 --- a/apps/client/src/ee/api-key/pages/user-api-keys.tsx +++ b/apps/client/src/ee/api-key/pages/user-api-keys.tsx @@ -1,10 +1,9 @@ import React, { useState } from "react"; import { Anchor, Alert, Button, Group, Space, Text } from "@mantine/core"; import { IconInfoCircle } from "@tabler/icons-react"; -import { Helmet } from "react-helmet-async"; import { Trans, useTranslation } from "react-i18next"; import SettingsTitle from "@/components/settings/settings-title"; -import { getAppName, getAppUrl } from "@/lib/config"; +import { getAppUrl } from "@/lib/config"; import { ApiKeyTable } from "@/ee/api-key/components/api-key-table"; import { CreateApiKeyModal } from "@/ee/api-key/components/create-api-key-modal"; import { ApiKeyCreatedModal } from "@/ee/api-key/components/api-key-created-modal"; @@ -17,6 +16,7 @@ import { IApiKey } from "@/ee/api-key"; import { useAtom } from "jotai"; import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; import useUserRole from "@/hooks/use-user-role.tsx"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function UserApiKeys() { const { t } = useTranslation(); @@ -49,11 +49,7 @@ export default function UserApiKeys() { return ( <> - - - {t("API keys")} - {getAppName()} - - + diff --git a/apps/client/src/ee/api-key/pages/workspace-api-keys.tsx b/apps/client/src/ee/api-key/pages/workspace-api-keys.tsx index 8476f4457..6a819bbcb 100644 --- a/apps/client/src/ee/api-key/pages/workspace-api-keys.tsx +++ b/apps/client/src/ee/api-key/pages/workspace-api-keys.tsx @@ -1,9 +1,7 @@ import React, { useState } from "react"; import { Anchor, Button, Divider, Group, Space, Text } from "@mantine/core"; -import { Helmet } from "react-helmet-async"; import { Trans, useTranslation } from "react-i18next"; import SettingsTitle from "@/components/settings/settings-title"; -import { getAppName } from "@/lib/config"; import { ApiKeyTable } from "@/ee/api-key/components/api-key-table"; import { CreateApiKeyModal } from "@/ee/api-key/components/create-api-key-modal"; import { ApiKeyCreatedModal } from "@/ee/api-key/components/api-key-created-modal"; @@ -15,6 +13,7 @@ import { useGetApiKeysQuery } from "@/ee/api-key/queries/api-key-query.ts"; import { IApiKey } from "@/ee/api-key"; import useUserRole from '@/hooks/use-user-role.tsx'; import RestrictApiToAdmins from "@/ee/api-key/components/restrict-api-to-admins"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function WorkspaceApiKeys() { const { t } = useTranslation(); @@ -47,11 +46,7 @@ export default function WorkspaceApiKeys() { return ( <> - - - {t("API management")} - {getAppName()} - - + diff --git a/apps/client/src/ee/audit/pages/audit-logs.tsx b/apps/client/src/ee/audit/pages/audit-logs.tsx index 05f7881ad..811e094e8 100644 --- a/apps/client/src/ee/audit/pages/audit-logs.tsx +++ b/apps/client/src/ee/audit/pages/audit-logs.tsx @@ -10,11 +10,9 @@ import { Text, Tooltip, } from "@mantine/core"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { IconSettings } from "@tabler/icons-react"; import SettingsTitle from "@/components/settings/settings-title"; -import { getAppName } from "@/lib/config"; import Paginate from "@/components/common/paginate"; import { useCursorPaginate } from "@/hooks/use-cursor-paginate"; import { @@ -26,6 +24,7 @@ import { IAuditLogParams } from "@/ee/audit/types/audit.types"; import { eventFilterOptions } from "@/ee/audit/lib/audit-event-labels"; import AuditLogsTable from "@/ee/audit/components/audit-logs-table"; import useUserRole from "@/hooks/use-user-role"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; type RetentionUnit = "days" | "months" | "years"; @@ -97,11 +96,7 @@ export default function AuditLogs() { return ( <> - - - {t("Audit log")} - {getAppName()} - - + diff --git a/apps/client/src/ee/billing/pages/billing.tsx b/apps/client/src/ee/billing/pages/billing.tsx index a389a1e58..9f47b9a58 100644 --- a/apps/client/src/ee/billing/pages/billing.tsx +++ b/apps/client/src/ee/billing/pages/billing.tsx @@ -1,5 +1,3 @@ -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import SettingsTitle from "@/components/settings/settings-title.tsx"; import BillingPlans from "@/ee/billing/components/billing-plans.tsx"; import BillingTrial from "@/ee/billing/components/billing-trial.tsx"; @@ -9,6 +7,7 @@ import React from "react"; import BillingDetails from "@/ee/billing/components/billing-details.tsx"; import { useBillingQuery } from "@/ee/billing/queries/billing-query.ts"; import useUserRole from "@/hooks/use-user-role.tsx"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Billing() { const { data: billing, isError: isBillingError } = useBillingQuery(); @@ -20,9 +19,7 @@ export default function Billing() { return ( <> - - Billing - {getAppName()} - + diff --git a/apps/client/src/ee/licence/pages/license.tsx b/apps/client/src/ee/licence/pages/license.tsx index 0aa9d2f58..1e9727d23 100644 --- a/apps/client/src/ee/licence/pages/license.tsx +++ b/apps/client/src/ee/licence/pages/license.tsx @@ -1,5 +1,3 @@ -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import SettingsTitle from "@/components/settings/settings-title.tsx"; import React from "react"; import useUserRole from "@/hooks/use-user-role.tsx"; @@ -9,6 +7,7 @@ import InstallationDetails from "@/ee/licence/components/installation-details.ts import OssDetails from "@/ee/licence/components/oss-details.tsx"; import { useAtom } from "jotai/index"; import { entitlementAtom } from "@/ee/entitlement/entitlement-atom"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function License() { const [entitlements] = useAtom(entitlementAtom); @@ -21,9 +20,7 @@ export default function License() { return ( <> - - License - {getAppName()} - + diff --git a/apps/client/src/ee/page-verification/pages/verified-pages.tsx b/apps/client/src/ee/page-verification/pages/verified-pages.tsx index 51786e5a1..15b7badad 100644 --- a/apps/client/src/ee/page-verification/pages/verified-pages.tsx +++ b/apps/client/src/ee/page-verification/pages/verified-pages.tsx @@ -1,17 +1,16 @@ import { useState, useMemo } from "react"; import { Group, MultiSelect, Select, Space, TextInput } from "@mantine/core"; import { useDebouncedValue } from "@mantine/hooks"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { IconSearch } from "@tabler/icons-react"; import SettingsTitle from "@/components/settings/settings-title"; -import { getAppName } from "@/lib/config"; import Paginate from "@/components/common/paginate"; import { useCursorPaginate } from "@/hooks/use-cursor-paginate"; import { useVerificationListQuery } from "@/ee/page-verification/queries/page-verification-query"; import { IVerificationListParams } from "@/ee/page-verification/types/page-verification.types"; import VerificationListTable from "@/ee/page-verification/components/verification-list-table"; import { useGetSpacesQuery } from "@/features/space/queries/space-query"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function VerifiedPages() { const { t } = useTranslation(); @@ -68,11 +67,7 @@ export default function VerifiedPages() { return ( <> - - - {t("Verified pages")} - {getAppName()} - - + diff --git a/apps/client/src/ee/pages/cloud-login.tsx b/apps/client/src/ee/pages/cloud-login.tsx index c0a40a0d4..14de528b8 100644 --- a/apps/client/src/ee/pages/cloud-login.tsx +++ b/apps/client/src/ee/pages/cloud-login.tsx @@ -1,18 +1,13 @@ -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import { CloudLoginForm } from "@/ee/components/cloud-login-form.tsx"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function CloudLogin() { const { t } = useTranslation(); return ( <> - - - {t("Login")} - {getAppName()} - - + diff --git a/apps/client/src/ee/pages/create-workspace.tsx b/apps/client/src/ee/pages/create-workspace.tsx index fb335d662..f681e65e9 100644 --- a/apps/client/src/ee/pages/create-workspace.tsx +++ b/apps/client/src/ee/pages/create-workspace.tsx @@ -1,14 +1,11 @@ import { SetupWorkspaceForm } from "@/features/auth/components/setup-workspace-form.tsx"; -import { Helmet } from "react-helmet-async"; import React from "react"; -import { getAppName } from "@/lib/config.ts"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function CreateWorkspace() { return ( <> - - Create Workspace - {getAppName()} - + ); diff --git a/apps/client/src/ee/security/pages/security.tsx b/apps/client/src/ee/security/pages/security.tsx index 2ff3670be..de3a7073b 100644 --- a/apps/client/src/ee/security/pages/security.tsx +++ b/apps/client/src/ee/security/pages/security.tsx @@ -1,5 +1,4 @@ -import { Helmet } from "react-helmet-async"; -import { getAppName, isCloud } from "@/lib/config.ts"; +import { isCloud } from "@/lib/config.ts"; import SettingsTitle from "@/components/settings/settings-title.tsx"; import { Alert, @@ -37,6 +36,7 @@ import EnableScim from "@/ee/scim/components/enable-scim"; import { useCursorPaginate } from "@/hooks/use-cursor-paginate"; import Paginate from "@/components/common/paginate"; import { IScimToken } from "@/ee/scim/types/scim-token.types"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; const SCIM_TOKEN_LIMIT = 5; @@ -64,9 +64,7 @@ export default function Security() { return ( <> - - Security - {getAppName()} - + diff --git a/apps/client/src/ee/template/pages/template-editor.tsx b/apps/client/src/ee/template/pages/template-editor.tsx index 2b4069978..7fadf05c8 100644 --- a/apps/client/src/ee/template/pages/template-editor.tsx +++ b/apps/client/src/ee/template/pages/template-editor.tsx @@ -22,8 +22,6 @@ import { useTranslation } from "react-i18next"; import { useDisclosure, useWindowEvent } from "@mantine/hooks"; import { notifications } from "@mantine/notifications"; import { Link, useParams } from "react-router-dom"; -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config"; import { useEditor, EditorContent } from "@tiptap/react"; import { templateExtensions } from "@/features/editor/extensions/extensions"; import { @@ -44,6 +42,7 @@ import CalloutMenu from "@/features/editor/components/callout/callout-menu.tsx"; import ColumnsMenu from "@/features/editor/components/columns/columns-menu.tsx"; import classes from "./template-editor.module.css"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function TemplateEditor() { const { t } = useTranslation(); @@ -247,11 +246,7 @@ export default function TemplateEditor() { return ( <> - - - {t("Edit template")} - {getAppName()} - - + {editorToolbarEnabled && editor && ( diff --git a/apps/client/src/ee/template/pages/template-list.tsx b/apps/client/src/ee/template/pages/template-list.tsx index fafd4c117..7fc740304 100644 --- a/apps/client/src/ee/template/pages/template-list.tsx +++ b/apps/client/src/ee/template/pages/template-list.tsx @@ -13,11 +13,9 @@ import { } from "@mantine/core"; import { modals } from "@mantine/modals"; import { IconPlus } from "@tabler/icons-react"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { useDisclosure } from "@mantine/hooks"; -import { getAppName } from "@/lib/config"; import { useGetTemplatesQuery, useDeleteTemplateMutation, @@ -31,6 +29,7 @@ import useUserRole from "@/hooks/use-user-role"; import CreateTemplateModal from "@/ee/template/components/create-template-modal"; import { useAtomValue } from "jotai"; import { workspaceAtom } from "@/features/user/atoms/current-user-atom"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function TemplateList() { const { t } = useTranslation(); @@ -102,11 +101,7 @@ export default function TemplateList() { return ( <> - - - {t("Templates")} - {getAppName()} - - + diff --git a/apps/client/src/pages/auth/forgot-password.tsx b/apps/client/src/pages/auth/forgot-password.tsx index 94826c1c8..dc5f10826 100644 --- a/apps/client/src/pages/auth/forgot-password.tsx +++ b/apps/client/src/pages/auth/forgot-password.tsx @@ -1,13 +1,10 @@ import { ForgotPasswordForm } from "@/features/auth/components/forgot-password-form"; -import { getAppName } from "@/lib/config"; -import { Helmet } from "react-helmet-async"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function ForgotPassword() { return ( <> - - Forgot Password - {getAppName()} - + ); diff --git a/apps/client/src/pages/auth/invite-signup.tsx b/apps/client/src/pages/auth/invite-signup.tsx index b9c9340ce..0ed064bf6 100644 --- a/apps/client/src/pages/auth/invite-signup.tsx +++ b/apps/client/src/pages/auth/invite-signup.tsx @@ -1,16 +1,13 @@ -import { Helmet } from "react-helmet-async"; import { InviteSignUpForm } from "@/features/auth/components/invite-sign-up-form.tsx"; -import {getAppName} from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function InviteSignup() { const { t } = useTranslation(); return ( <> - - {t("Invitation Signup")} - {getAppName()} - + ); diff --git a/apps/client/src/pages/auth/login.tsx b/apps/client/src/pages/auth/login.tsx index 4b062c190..5cd710baf 100644 --- a/apps/client/src/pages/auth/login.tsx +++ b/apps/client/src/pages/auth/login.tsx @@ -1,18 +1,13 @@ import { LoginForm } from "@/features/auth/components/login-form"; -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function LoginPage() { const { t } = useTranslation(); return ( <> - - - {t("Login")} - {getAppName()} - - + ); diff --git a/apps/client/src/pages/auth/password-reset.tsx b/apps/client/src/pages/auth/password-reset.tsx index ae7d391b3..d785761ee 100644 --- a/apps/client/src/pages/auth/password-reset.tsx +++ b/apps/client/src/pages/auth/password-reset.tsx @@ -1,11 +1,10 @@ -import { Helmet } from "react-helmet-async"; import { PasswordResetForm } from "@/features/auth/components/password-reset-form"; import { Link, useSearchParams } from "react-router-dom"; import { useVerifyUserTokenQuery } from "@/features/auth/queries/auth-query"; import { Button, Container, Group, Text } from "@mantine/core"; import APP_ROUTE from "@/lib/app-route"; -import { getAppName } from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function PasswordReset() { const { t } = useTranslation(); @@ -23,11 +22,7 @@ export default function PasswordReset() { if (isError || !resetToken) { return ( <> - - - {t("Password Reset")} - {getAppName()} - - + {t("Invalid or expired password reset link")} @@ -49,11 +44,7 @@ export default function PasswordReset() { return ( <> - - - {t("Password Reset")} - {getAppName()} - - + ); diff --git a/apps/client/src/pages/auth/setup-workspace.tsx b/apps/client/src/pages/auth/setup-workspace.tsx index 7fb75e2db..0e85525a9 100644 --- a/apps/client/src/pages/auth/setup-workspace.tsx +++ b/apps/client/src/pages/auth/setup-workspace.tsx @@ -1,11 +1,10 @@ import { useWorkspacePublicDataQuery } from "@/features/workspace/queries/workspace-query.ts"; import { SetupWorkspaceForm } from "@/features/auth/components/setup-workspace-form.tsx"; -import { Helmet } from "react-helmet-async"; import React, { useEffect } from "react"; import { useNavigate } from "react-router-dom"; import APP_ROUTE from "@/lib/app-route.ts"; -import { getAppName } from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function SetupWorkspace() { const { t } = useTranslation(); @@ -35,11 +34,7 @@ export default function SetupWorkspace() { ) { return ( <> - - - {t("Setup Workspace")} - {getAppName()} - - + ); diff --git a/apps/client/src/pages/dashboard/home.tsx b/apps/client/src/pages/dashboard/home.tsx index 83d553038..20d127bef 100644 --- a/apps/client/src/pages/dashboard/home.tsx +++ b/apps/client/src/pages/dashboard/home.tsx @@ -2,20 +2,15 @@ import { Container, Space } from "@mantine/core"; import HomeTabs from "@/features/home/components/home-tabs"; import HomeAiPrompt from "@/features/home/components/home-ai-prompt"; import SpaceCarousel from "@/features/space/components/space-carousel.tsx"; -import { getAppName } from "@/lib/config.ts"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Home() { const { t } = useTranslation(); return ( <> - - - {t("Home")} - {getAppName()} - - + diff --git a/apps/client/src/pages/label/label-page.tsx b/apps/client/src/pages/label/label-page.tsx index 8a5a53532..c272d7778 100644 --- a/apps/client/src/pages/label/label-page.tsx +++ b/apps/client/src/pages/label/label-page.tsx @@ -17,9 +17,7 @@ import { } from "@tabler/icons-react"; import { Link, useParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; -import { Helmet } from "react-helmet-async"; import { useDebouncedValue } from "@mantine/hooks"; -import { getAppName } from "@/lib/config"; import { useLabelPagesQuery } from "@/features/label/queries/label-query.ts"; import { useGetSpacesQuery } from "@/features/space/queries/space-query.ts"; import { getLabelColor } from "@/features/label/utils/label-colors.ts"; @@ -29,6 +27,7 @@ import { normalizeLabelName } from "@/features/label/utils/normalize-label.ts"; import { SpaceFilterMenu } from "@/features/space/components/space-filter-menu.tsx"; import { EmptyState } from "@/components/ui/empty-state"; import classes from "@/features/label/label.module.css"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function LabelPage() { const { t } = useTranslation(); @@ -82,11 +81,7 @@ export default function LabelPage() { return ( <> - - - {labelName} - {getAppName()} - - + diff --git a/apps/client/src/pages/page/page.tsx b/apps/client/src/pages/page/page.tsx index 5ca737d02..ea109488f 100644 --- a/apps/client/src/pages/page/page.tsx +++ b/apps/client/src/pages/page/page.tsx @@ -3,7 +3,6 @@ import { usePageQuery } from "@/features/page/queries/page-query"; import { FullEditor } from "@/features/editor/full-editor"; import { TitleEditor } from "@/features/editor/title-editor"; import HistoryModal from "@/features/page-history/components/history-modal"; -import { Helmet } from "react-helmet-async"; import PageHeader from "@/features/page/components/header/page-header.tsx"; import { extractPageSlugId } from "@/lib"; import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts"; @@ -18,6 +17,7 @@ import { BaseView } from "@/ee/base/components/base-view"; import { useHasFeature } from "@/ee/hooks/use-feature"; import { Feature } from "@/ee/features"; import { getPageTitle } from "@/features/page/page.utils"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; const MemoizedFullEditor = React.memo(FullEditor); const MemoizedTitleEditor = React.memo(TitleEditor); const MemoizedPageHeader = React.memo(PageHeader); @@ -110,9 +110,10 @@ function PageContent({ pageSlug }: { pageSlug: string | undefined }) { paddingTop: "calc(var(--page-header-height) + 6px)", }} > - - {`${page?.icon || ""} ${getPageTitle(page?.title, page?.isBase, t)}`} - +
- - {`${page?.icon || ""} ${getPageTitle(page?.title, page?.isBase, t)}`} - + diff --git a/apps/client/src/pages/settings/account/account-preferences.tsx b/apps/client/src/pages/settings/account/account-preferences.tsx index bead4bfbc..6f9a0c1b4 100644 --- a/apps/client/src/pages/settings/account/account-preferences.tsx +++ b/apps/client/src/pages/settings/account/account-preferences.tsx @@ -5,21 +5,16 @@ import PageWidthPref from "@/features/user/components/page-width-pref.tsx"; import PageEditPref from "@/features/user/components/page-state-pref"; import FixedToolbarPref from "@/features/user/components/fixed-toolbar-pref"; import NotificationPref from "@/features/user/components/notification-pref"; -import { getAppName } from "@/lib/config.ts"; import { Divider } from "@mantine/core"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function AccountPreferences() { const { t } = useTranslation(); return ( <> - - - {t("Preferences")} - {getAppName()} - - + diff --git a/apps/client/src/pages/settings/account/account-settings.tsx b/apps/client/src/pages/settings/account/account-settings.tsx index 6f87d31af..f39a0e877 100644 --- a/apps/client/src/pages/settings/account/account-settings.tsx +++ b/apps/client/src/pages/settings/account/account-settings.tsx @@ -4,22 +4,17 @@ import ChangePassword from "@/features/user/components/change-password"; import { Divider } from "@mantine/core"; import AccountAvatar from "@/features/user/components/account-avatar"; import SettingsTitle from "@/components/settings/settings-title.tsx"; -import { getAppName } from "@/lib/config.ts"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { AccountMfaSection } from "@/features/user/components/account-mfa-section"; import SessionList from "@/features/session/components/session-list"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function AccountSettings() { const { t } = useTranslation(); return ( <> - - - {t("My Profile")} - {getAppName()} - - + diff --git a/apps/client/src/pages/settings/group/group-info.tsx b/apps/client/src/pages/settings/group/group-info.tsx index 5a1c9bb71..70c596c5b 100644 --- a/apps/client/src/pages/settings/group/group-info.tsx +++ b/apps/client/src/pages/settings/group/group-info.tsx @@ -1,20 +1,15 @@ import SettingsTitle from "@/components/settings/settings-title.tsx"; import GroupMembersList from "@/features/group/components/group-members"; import GroupDetails from "@/features/group/components/group-details"; -import { getAppName } from "@/lib/config.ts"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function GroupInfo() { const { t } = useTranslation(); return ( <> - - - {t("Manage Group")} - {getAppName()} - - + diff --git a/apps/client/src/pages/settings/group/groups.tsx b/apps/client/src/pages/settings/group/groups.tsx index cae553f15..0b75b9bfd 100644 --- a/apps/client/src/pages/settings/group/groups.tsx +++ b/apps/client/src/pages/settings/group/groups.tsx @@ -3,9 +3,8 @@ import SettingsTitle from "@/components/settings/settings-title.tsx"; import { Group } from "@mantine/core"; import CreateGroupModal from "@/features/group/components/create-group-modal"; import useUserRole from "@/hooks/use-user-role.tsx"; -import {getAppName} from "@/lib/config.ts"; -import {Helmet} from "react-helmet-async"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Groups() { const { t } = useTranslation(); @@ -13,9 +12,7 @@ export default function Groups() { return ( <> - - {t("Groups")} - {getAppName()} - + diff --git a/apps/client/src/pages/settings/shares/shares.tsx b/apps/client/src/pages/settings/shares/shares.tsx index 1a5a118e4..d327681af 100644 --- a/apps/client/src/pages/settings/shares/shares.tsx +++ b/apps/client/src/pages/settings/shares/shares.tsx @@ -1,22 +1,17 @@ import SettingsTitle from "@/components/settings/settings-title.tsx"; -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; import ShareList from "@/features/share/components/share-list.tsx"; import { Alert, Text } from "@mantine/core"; import { IconInfoCircle } from "@tabler/icons-react"; import React from "react"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Shares() { const { t } = useTranslation(); return ( <> - - - {t("Public sharing")} - {getAppName()} - - + }> diff --git a/apps/client/src/pages/settings/space/spaces.tsx b/apps/client/src/pages/settings/space/spaces.tsx index 329eab25f..e098f3570 100644 --- a/apps/client/src/pages/settings/space/spaces.tsx +++ b/apps/client/src/pages/settings/space/spaces.tsx @@ -3,9 +3,8 @@ import SpaceList from "@/features/space/components/space-list.tsx"; import useUserRole from "@/hooks/use-user-role.tsx"; import { Group } from "@mantine/core"; import CreateSpaceModal from "@/features/space/components/create-space-modal.tsx"; -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config.ts"; import { useTranslation } from "react-i18next"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Spaces() { const { t } = useTranslation(); @@ -13,11 +12,7 @@ export default function Spaces() { return ( <> - - - {t("Spaces")} - {getAppName()} - - + diff --git a/apps/client/src/pages/settings/workspace/workspace-members.tsx b/apps/client/src/pages/settings/workspace/workspace-members.tsx index dba853a47..d12bed760 100644 --- a/apps/client/src/pages/settings/workspace/workspace-members.tsx +++ b/apps/client/src/pages/settings/workspace/workspace-members.tsx @@ -6,11 +6,10 @@ import { useEffect, useState } from "react"; import { useNavigate, useSearchParams } from "react-router-dom"; import WorkspaceInvitesTable from "@/features/workspace/components/members/components/workspace-invites-table.tsx"; import useUserRole from "@/hooks/use-user-role.tsx"; -import { getAppName } from "@/lib/config.ts"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { useAtom } from "jotai"; import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function WorkspaceMembers() { const { t } = useTranslation(); @@ -38,11 +37,7 @@ export default function WorkspaceMembers() { return ( <> - - - {t("Members")} - {getAppName()} - - + {/* */} diff --git a/apps/client/src/pages/settings/workspace/workspace-settings.tsx b/apps/client/src/pages/settings/workspace/workspace-settings.tsx index 1dc55485f..dc9e7c5fc 100644 --- a/apps/client/src/pages/settings/workspace/workspace-settings.tsx +++ b/apps/client/src/pages/settings/workspace/workspace-settings.tsx @@ -2,21 +2,19 @@ import SettingsTitle from "@/components/settings/settings-title.tsx"; import WorkspaceNameForm from "@/features/workspace/components/settings/components/workspace-name-form"; import WorkspaceIcon from "@/features/workspace/components/settings/components/workspace-icon.tsx"; import { useTranslation } from "react-i18next"; -import { getAppName, isCloud } from "@/lib/config.ts"; -import { Helmet } from "react-helmet-async"; +import { isCloud } from "@/lib/config.ts"; import ManageHostname from "@/ee/components/manage-hostname.tsx"; import { Divider } from "@mantine/core"; import AllowMemberTemplates from "@/ee/security/components/allow-member-templates.tsx"; import WorkspaceDefaultPageEditMode from "@/features/workspace/components/settings/components/workspace-default-page-edit-mode.tsx"; import PersonalSpacesSetting from "@/ee/personal-space/components/personal-spaces-setting.tsx"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function WorkspaceSettings() { const { t } = useTranslation(); return ( <> - - Workspace Settings - {getAppName()} - + diff --git a/apps/client/src/pages/share/shared-page.tsx b/apps/client/src/pages/share/shared-page.tsx index f156208e5..b7028b2fb 100644 --- a/apps/client/src/pages/share/shared-page.tsx +++ b/apps/client/src/pages/share/shared-page.tsx @@ -1,5 +1,4 @@ import { useNavigate, useParams } from "react-router-dom"; -import { Helmet } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { useSharePageQuery } from "@/features/share/queries/share-query.ts"; import { Container } from "@mantine/core"; @@ -14,6 +13,7 @@ import { sharedTreeDataAtom, } from "@/features/share/atoms/shared-page-atom.ts"; import { isPageInTree } from "@/features/share/utils.ts"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function SharedPage() { const { t } = useTranslation(); @@ -56,12 +56,14 @@ export default function SharedPage() { return (
- - {`${data?.page?.title || t("untitled")}`} + {!data?.share.searchIndexing && ( )} - + - - {space?.name || 'Overview'} - {getAppName()} - + {space && } diff --git a/apps/client/src/pages/spaces/spaces.tsx b/apps/client/src/pages/spaces/spaces.tsx index 1eadcee79..0f67c8c63 100644 --- a/apps/client/src/pages/spaces/spaces.tsx +++ b/apps/client/src/pages/spaces/spaces.tsx @@ -1,13 +1,12 @@ import { Container, Title, Text, Group, Box } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { Helmet } from "react-helmet-async"; -import { getAppName } from "@/lib/config"; import { useGetSpacesQuery } from "@/features/space/queries/space-query"; import CreateSpaceModal from "@/features/space/components/create-space-modal"; import { AllSpacesList } from "@/features/space/components/spaces-page"; import FavoriteSpacesGrid from "@/features/space/components/spaces-page/favorite-spaces-grid"; import { usePaginateAndSearch } from "@/hooks/use-paginate-and-search"; import useUserRole from "@/hooks/use-user-role"; +import { DocumentTitle } from "@/components/ui/document-title.tsx"; export default function Spaces() { const { t } = useTranslation(); @@ -22,11 +21,7 @@ export default function Spaces() { return ( <> - - - {t("Spaces")} - {getAppName()} - - + From 7439da2f6ec1e7ee71b2d3b053eae20831ba7cc5 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:56:12 +0100 Subject: [PATCH 3/9] chore: package updates (#2383) * update * update versions * package updates --- apps/client/package.json | 4 +- apps/server/package.json | 14 +- package.json | 16 +- pnpm-lock.yaml | 1481 ++++++++++++++++++++++---------------- pnpm-workspace.yaml | 10 +- 5 files changed, 873 insertions(+), 652 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 4e00721eb..e5bb5ad5a 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -50,9 +50,9 @@ "katex": "0.16.40", "lowlight": "3.3.0", "mantine-form-zod-resolver": "1.3.0", - "mermaid": "11.15.0", + "mermaid": "11.16.1", "mitt": "3.0.1", - "nanoid": "3.3.8", + "nanoid": "3.3.17", "posthog-js": "1.391.2", "react": "19.2.7", "react-clear-modal": "^2.0.18", diff --git a/apps/server/package.json b/apps/server/package.json index 6f68db45d..cb32657a7 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -51,19 +51,19 @@ "@nestjs-labs/nestjs-ioredis": "11.0.4", "@nestjs/bullmq": "11.0.4", "@nestjs/cache-manager": "3.1.3", - "@nestjs/common": "11.1.27", + "@nestjs/common": "11.1.28", "@nestjs/config": "4.0.4", "@nestjs/core": "11.1.27", "@nestjs/event-emitter": "3.1.0", "@nestjs/jwt": "11.0.2", "@nestjs/mapped-types": "2.1.1", "@nestjs/passport": "11.0.5", - "@nestjs/platform-fastify": "11.1.27", - "@nestjs/platform-socket.io": "11.1.27", + "@nestjs/platform-fastify": "11.1.28", + "@nestjs/platform-socket.io": "11.1.28", "@nestjs/schedule": "6.1.3", "@nestjs/terminus": "11.1.1", "@nestjs/throttler": "6.5.0", - "@nestjs/websockets": "11.1.27", + "@nestjs/websockets": "11.1.28", "@node-saml/passport-saml": "5.1.0", "@socket.io/redis-adapter": "8.3.0", "ai": "6.0.134", @@ -90,8 +90,8 @@ "ldapts": "8.1.7", "mammoth": "1.12.0", "mime-types": "3.0.2", - "msgpackr": "^1.11.9", - "nanoid": "5.1.7", + "msgpackr": "1.11.9", + "nanoid": "5.1.16", "nestjs-cls": "6.2.0", "nestjs-kysely": "3.1.2", "nestjs-pino": "4.6.1", @@ -102,7 +102,7 @@ "passport-google-oauth20": "2.0.0", "passport-jwt": "4.0.1", "pg-tsquery": "8.4.2", - "pgvector": "^0.2.1", + "pgvector": "0.2.1", "pino-http": "11.0.0", "pino-pretty": "13.1.3", "postgres": "3.4.8", diff --git a/package.json b/package.json index a3736788c..f51701448 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,11 @@ "@casl/ability": "6.8.0", "@docmost/editor-ext": "workspace:*", "@floating-ui/dom": "1.7.3", - "@hocuspocus/common": "4.4.0", - "@hocuspocus/provider": "4.4.0", - "@hocuspocus/provider-react": "4.4.0", - "@hocuspocus/server": "4.4.0", - "@hocuspocus/transformer": "4.4.0", + "@hocuspocus/common": "4.5.0", + "@hocuspocus/provider": "4.5.0", + "@hocuspocus/provider-react": "4.5.0", + "@hocuspocus/server": "4.5.0", + "@hocuspocus/transformer": "4.5.0", "@joplin/turndown": "4.0.82", "@joplin/turndown-plugin-gfm": "1.0.64", "@sindresorhus/slugify": "3.0.0", @@ -65,7 +65,7 @@ "date-fns": "4.1.0", "diff": "8.0.3", "docx": "9.7.1", - "dompurify": "3.4.12", + "dompurify": "3.4.13", "fractional-indexing-jittered": "1.0.0", "highlight.js": "11.11.1", "image-dimensions": "2.5.0", @@ -81,12 +81,12 @@ "yjs": "^13.6.30" }, "devDependencies": { - "@nx/js": "22.7.2", + "@nx/js": "23.1.1", "@types/bytes": "3.1.5", "@types/qrcode": "1.5.6", "@types/turndown": "5.0.6", "concurrently": "10.0.4", - "nx": "22.7.2", + "nx": "23.1.1", "tsx": "^4.21.0" }, "workspaces": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f9b32547..e26d0a45d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,11 +8,11 @@ overrides: prosemirror-changeset: 2.4.0 glob: 13.0.6 ws: 8.21.0 - dompurify: 3.4.12 - mermaid: 11.15.0 + dompurify: 3.4.13 + mermaid: 11.16.1 undici: 7.29.0 tmp: 0.2.7 - nanoid@^3: 3.3.8 + nanoid@^3: 3.3.17 lodash-es: 4.18.1 express-rate-limit: 8.2.2 flatted: 3.4.2 @@ -23,9 +23,11 @@ overrides: ip-address: 10.3.1 fast-uri: 3.1.5 form-data@>=4.0.0 <4.0.6: 4.0.6 - nanoid@>=4.0.0 <5.0.9: 5.1.16 + nanoid@>=4.0.0 <5.1.16: 5.1.16 esbuild@>=0.27.3 <0.28.1: 0.28.1 '@opentelemetry/core@>=2.0.0 <2.8.0': 2.9.0 + js-yaml@>=3.0.0 <3.15.1: 3.15.1 + js-yaml@>=4.0.0 <4.3.1: 4.3.1 patchedDependencies: scimmy@1.3.5: 775d80f86830b2c5dd1a250c9802c10f8fc3da3c7898373de5aa0c23993d1673 @@ -47,23 +49,23 @@ importers: specifier: 1.7.3 version: 1.7.3 '@hocuspocus/common': - specifier: 4.4.0 - version: 4.4.0 + specifier: 4.5.0 + version: 4.5.0 '@hocuspocus/provider': - specifier: 4.4.0 - version: 4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) + specifier: 4.5.0 + version: 4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) '@hocuspocus/provider-react': - specifier: 4.4.0 - version: 4.4.0(@hocuspocus/provider@4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(react@19.2.7)(yjs@13.6.30) + specifier: 4.5.0 + version: 4.5.0(@hocuspocus/provider@4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(react@19.2.7)(yjs@13.6.30) '@hocuspocus/server': - specifier: 4.4.0 - version: 4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) + specifier: 4.5.0 + version: 4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) '@hocuspocus/transformer': - specifier: 4.4.0 - version: 4.4.0(@tiptap/core@3.29.2(@tiptap/pm@3.29.2))(@tiptap/pm@3.29.2)(y-prosemirror@1.3.7(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.41.9)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(yjs@13.6.30) + specifier: 4.5.0 + version: 4.5.0(@tiptap/core@3.29.2(@tiptap/pm@3.29.2))(@tiptap/pm@3.29.2)(y-prosemirror@1.3.7(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.41.9)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(yjs@13.6.30) '@joplin/turndown': specifier: 4.0.82 - version: 4.0.82(supports-color@10.2.2) + version: 4.0.82(supports-color@7.2.0) '@joplin/turndown-plugin-gfm': specifier: 1.0.64 version: 1.0.64 @@ -173,8 +175,8 @@ importers: specifier: 9.7.1 version: 9.7.1 dompurify: - specifier: 3.4.12 - version: 3.4.12 + specifier: 3.4.13 + version: 3.4.13 fractional-indexing-jittered: specifier: 1.0.0 version: 1.0.0 @@ -216,8 +218,8 @@ importers: version: 13.6.30 devDependencies: '@nx/js': - specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7(supports-color@10.2.2))(debug@4.4.3(supports-color@10.2.2))(nx@22.7.2(debug@4.4.3(supports-color@10.2.2)))(supports-color@10.2.2) + specifier: 23.1.1 + version: 23.1.1(@babel/traverse@7.29.7(supports-color@7.2.0))(nx@23.1.1)(supports-color@7.2.0) '@types/bytes': specifier: 3.1.5 version: 3.1.5 @@ -231,8 +233,8 @@ importers: specifier: 10.0.4 version: 10.0.4 nx: - specifier: 22.7.2 - version: 22.7.2(debug@4.4.3(supports-color@10.2.2)) + specifier: 23.1.1 + version: 23.1.1 tsx: specifier: ^4.21.0 version: 4.21.0 @@ -271,7 +273,7 @@ importers: version: 9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mantine/dates': specifier: 9.3.2 - version: 9.3.2(@mantine/core@9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.3.2(react@19.2.7))(dayjs@1.11.19)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 9.3.2(@mantine/core@9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.3.2(react@19.2.7))(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mantine/form': specifier: 9.3.2 version: 9.3.2(react@19.2.7) @@ -354,14 +356,14 @@ importers: specifier: 1.3.0 version: 1.3.0(@mantine/form@9.3.2(react@19.2.7))(zod@4.3.6) mermaid: - specifier: 11.15.0 - version: 11.15.0 + specifier: 11.16.1 + version: 11.16.1 mitt: specifier: 3.0.1 version: 3.0.1 nanoid: - specifier: 3.3.8 - version: 3.3.8 + specifier: 3.3.17 + version: 3.3.17 posthog-js: specifier: 1.391.2 version: 1.391.2 @@ -536,55 +538,55 @@ importers: version: 1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.3.6) '@nest-lab/throttler-storage-redis': specifier: 1.2.0 - version: 1.2.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2))(ioredis@5.10.1(supports-color@10.2.2))(reflect-metadata@0.2.2) + version: 1.2.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2))(ioredis@5.10.1(supports-color@10.2.2))(reflect-metadata@0.2.2) '@nestjs-labs/nestjs-ioredis': specifier: 11.0.4 - version: 11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(ioredis@5.10.1(supports-color@10.2.2)) + version: 11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(ioredis@5.10.1(supports-color@10.2.2)) '@nestjs/bullmq': specifier: 11.0.4 - version: 11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(bullmq@5.79.0(supports-color@10.2.2)) + version: 11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(bullmq@5.79.0(supports-color@10.2.2)) '@nestjs/cache-manager': specifier: 3.1.3 - version: 3.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2) + version: 3.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2) '@nestjs/common': - specifier: 11.1.27 - version: 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + specifier: 11.1.28 + version: 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) '@nestjs/config': specifier: 4.0.4 - version: 4.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(rxjs@7.8.2) + version: 4.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(rxjs@7.8.2) '@nestjs/core': specifier: 11.1.27 - version: 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/event-emitter': specifier: 3.1.0 - version: 3.1.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) + version: 3.1.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) '@nestjs/jwt': specifier: 11.0.2 - version: 11.0.2(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2)) + version: 11.0.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2)) '@nestjs/mapped-types': specifier: 2.1.1 - version: 2.1.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) + version: 2.1.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) '@nestjs/passport': specifier: 11.0.5 - version: 11.0.5(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(passport@0.7.0) + version: 11.0.5(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(passport@0.7.0) '@nestjs/platform-fastify': - specifier: 11.1.27 - version: 11.1.27(@fastify/static@10.1.2)(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) + specifier: 11.1.28 + version: 11.1.28(@fastify/static@10.1.2)(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) '@nestjs/platform-socket.io': - specifier: 11.1.27 - version: 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(rxjs@7.8.2)(supports-color@10.2.2) + specifier: 11.1.28 + version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(rxjs@7.8.2)(supports-color@10.2.2) '@nestjs/schedule': specifier: 6.1.3 - version: 6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) + version: 6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) '@nestjs/terminus': specifier: 11.1.1 - version: 11.1.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 11.1.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/throttler': specifier: 6.5.0 - version: 6.5.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2) + version: 6.5.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2) '@nestjs/websockets': - specifier: 11.1.27 - version: 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: 11.1.28 + version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@node-saml/passport-saml': specifier: 5.1.0 version: 5.1.0(supports-color@10.2.2) @@ -664,20 +666,20 @@ importers: specifier: 3.0.2 version: 3.0.2 msgpackr: - specifier: ^1.11.9 + specifier: 1.11.9 version: 1.11.9 nanoid: - specifier: 5.1.7 - version: 5.1.7 + specifier: 5.1.16 + version: 5.1.16 nestjs-cls: specifier: 6.2.0 - version: 6.2.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 6.2.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) nestjs-kysely: specifier: 3.1.2 - version: 3.1.2(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(kysely@0.28.17)(reflect-metadata@0.2.2) + version: 3.1.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(kysely@0.28.17)(reflect-metadata@0.2.2) nestjs-pino: specifier: 4.6.1 - version: 4.6.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2) + version: 4.6.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2) nodemailer: specifier: 9.0.1 version: 9.0.1 @@ -700,7 +702,7 @@ importers: specifier: 8.4.2 version: 8.4.2 pgvector: - specifier: ^0.2.1 + specifier: 0.2.1 version: 0.2.1 pino-http: specifier: 11.0.0 @@ -713,7 +715,7 @@ importers: version: 3.4.8 postmark: specifier: 4.0.7 - version: 4.0.7(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) + version: 4.0.7(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2) react: specifier: 19.2.7 version: 19.2.7 @@ -746,7 +748,7 @@ importers: version: 3.0.3 typesense: specifier: 3.0.5 - version: 3.0.5(@babel/runtime@7.29.2)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) + version: 3.0.5(@babel/runtime@7.29.2)(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2) undici: specifier: 7.29.0 version: 7.29.0 @@ -771,7 +773,7 @@ importers: version: 11.0.10(chokidar@4.0.3)(typescript@5.9.3) '@nestjs/testing': specifier: ^11.1.19 - version: 11.1.19(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) + version: 11.1.19(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) '@types/bcrypt': specifier: ^6.0.0 version: 6.0.0 @@ -2214,31 +2216,31 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@hocuspocus/common@4.4.0': - resolution: {integrity: sha512-cPSlPu/ws2JzBHW6OzctyaQMyDCq/YUS4nhXSbyMdkQwJzhjCkvfmmRnVtcmgLR3TBLaNwToNDwR/mNaJFOYsg==} + '@hocuspocus/common@4.5.0': + resolution: {integrity: sha512-hz6IBLLNKOWrWf+8r236CFFhpkcjEVXtZH1XRrkY0b5dYoQgR5gmuV5/5dJm1Vvyc8I70D+SHCvOch2AsRXonA==} - '@hocuspocus/provider-react@4.4.0': - resolution: {integrity: sha512-8rbhIYQUl8ZvE5q4SHFo9+oYjFCkVoWssQJV6q5CMNuV7D/v1lJoQZLpznw7vzWWj9ijVrqNiI8UFnc2X8AGZg==} + '@hocuspocus/provider-react@4.5.0': + resolution: {integrity: sha512-zvYILUBdDEQg+A/i3goheEGDl3WIX+sD+YcRD61odfudLFEUCFsnZ7B7Ilq45k71cTvX9XSjawxgz7uv//mlpw==} peerDependencies: - '@hocuspocus/provider': ^4.4.0 + '@hocuspocus/provider': ^4.5.0 react: ^18.0.0 || ^19.0.0 yjs: ^13.6.8 - '@hocuspocus/provider@4.4.0': - resolution: {integrity: sha512-A83ROMFqU2bgjTTQ1YMteY9v2cIhDHj4S6XgzjPaqYEgOFr2XvBYGnK+NXzZ6DgldKTnlN7qqvWvZplPvltgyw==} + '@hocuspocus/provider@4.5.0': + resolution: {integrity: sha512-zpu68EIVZCzem1aCRjXeeeRVgaJHZa+p2rpherneUpwTnrb3WInL4IJ7cgMk0yP1/I2KPzve6meGODl1JPNTZQ==} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 - '@hocuspocus/server@4.4.0': - resolution: {integrity: sha512-eVSnx+76CN81vaRol+OlT8FyyGFOBF9Z+kdJQhjVXRpj3kIAI1TzuRHKiZN1vkUogdHfmOAN5Bhs5v7V/qhMkQ==} + '@hocuspocus/server@4.5.0': + resolution: {integrity: sha512-obRjLJmBi+EsQgP/Q7nZHC4ZvuBSROQCiLBLmIvib0IG3mu4vJfWiMiAmmrfMKM05denjbfK2BVKMmDVj9AGig==} engines: {node: '>=22'} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 - '@hocuspocus/transformer@4.4.0': - resolution: {integrity: sha512-wvHgbiWfU1QERIMd37aImtb4xbHRGwek+66VPgFaSx3POgxCKmkZH5iVY25j/T0PBmloofPoV1XYbwLwJZMtJw==} + '@hocuspocus/transformer@4.5.0': + resolution: {integrity: sha512-y5G1a9az4sLhXE8X2koHN6kKAGrgyj0Z9E+orSUvIGmurXGjD/OHPRWIKdOYBls1IzLZ78gkTdwzDN2H9ko0MA==} peerDependencies: '@tiptap/core': ^3.0.1 '@tiptap/pm': ^3.0.1 @@ -2564,8 +2566,8 @@ packages: peerDependencies: '@langchain/core': ^1.0.0 - '@lifeomic/attempt@3.0.3': - resolution: {integrity: sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==} + '@lifeomic/attempt@3.1.0': + resolution: {integrity: sha512-QZqem4QuAnAyzfz+Gj5/+SLxqwCAw2qmt7732ZXodr6VDWGeYLG6w1i/vYLa55JQM9wRuBKLmXmiZ2P0LtE5rw==} '@lukeed/csprng@1.1.0': resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} @@ -2633,8 +2635,8 @@ packages: '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} - '@mermaid-js/parser@1.1.1': - resolution: {integrity: sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw==} + '@mermaid-js/parser@1.2.0': + resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==} '@modelcontextprotocol/sdk@1.30.0': resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} @@ -2740,8 +2742,8 @@ packages: '@swc/core': optional: true - '@nestjs/common@11.1.27': - resolution: {integrity: sha512-kEGSzqM2lWr4whh4Ubflw+oPZSEzxvRMu9WL+LveZploJWTjec5bBlCiRVlVzTPg2kIwBiLwWSvCCW7Wnin1gg==} + '@nestjs/common@11.1.28': + resolution: {integrity: sha512-bRImsxibie+AM7xjdwcrm/gr5YeacI65kSBNzTufa1Ib5iwziaY/lqMtRh9THq6pbV4e1HP9aI2ZxGUumnmaoQ==} peerDependencies: class-transformer: '>=0.4.1' class-validator: '>=0.13.2' @@ -2807,8 +2809,8 @@ packages: '@nestjs/common': ^10.0.0 || ^11.0.0 passport: ^0.5.0 || ^0.6.0 || ^0.7.0 - '@nestjs/platform-fastify@11.1.27': - resolution: {integrity: sha512-rZMPS0RMP9P2O7Y/shAP0kKwrHElGO9cPTlgtdWpQ6JEX58uhYEJLGsU/X9a9l18DNSxxb3YjrEiVVuI2Iv6MA==} + '@nestjs/platform-fastify@11.1.28': + resolution: {integrity: sha512-utUfyxRzZsoFxz1GU3Z0OthHpijB605iqtxwFnk9yKowLrU1t1ZkxMUuad/csemImY6AsuaTpTjCecKbmfl+pQ==} peerDependencies: '@fastify/static': ^8.0.0 || ^9.0.0 '@fastify/view': ^10.0.0 || ^11.0.0 || ^12.0.0 @@ -2820,8 +2822,8 @@ packages: '@fastify/view': optional: true - '@nestjs/platform-socket.io@11.1.27': - resolution: {integrity: sha512-xgpLzaIDGOCC6xOAtHnRAz8sqieFgGxxu3MN5ID026Jt6oeL3efp29N5QHhPr7UlqBfy/Jd02uj0POkZq6Au3Q==} + '@nestjs/platform-socket.io@11.1.28': + resolution: {integrity: sha512-vY+GmU2jBcymvgm5rEnftUx4qNxK8cDJmXjl1/1NcpITTNJo0vg07xYR43MwXHcMqe7b0jwqt5+UCTzxqQFIqA==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/websockets': ^11.0.0 @@ -2906,8 +2908,8 @@ packages: '@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 reflect-metadata: ^0.1.13 || ^0.2.0 - '@nestjs/websockets@11.1.27': - resolution: {integrity: sha512-X3OgJt9KgYTvt9D7sNz9SOj3A1daAHy7DZrYhM1pky8Fh+erlKQH5IQ/tKm+GaJKA5M0srBUr1CMqjak/qNxOw==} + '@nestjs/websockets@11.1.28': + resolution: {integrity: sha512-jeyclAURCJTN8S8lctDhfLdiJeDKjZmYWWLav653Fb9hl9c+zx5jPhavI8Xk5++R8u+lX9qzaRxtsjEoxTtjyw==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/core': ^11.0.0 @@ -2937,75 +2939,78 @@ packages: resolution: {integrity: sha512-pBm+iFjv9eihcgeJuSUs4c0AuX1QEFdHwP8w1iaWCfDzXdeWZxUBU5HT2bY2S4dvNutcy+A9hYsH7ZLBGtgwDg==} engines: {node: '>= 18'} - '@nx/devkit@22.7.2': - resolution: {integrity: sha512-oE2SFUxQeZm/EmFABHpWQ4Pi0fBKbJbXKGPvdFaHoMumRxhqBhuBVf/ap5kYFg8Y9bK/zHJkpsEbGyiyRrhvog==} + '@nx/devkit@23.1.1': + resolution: {integrity: sha512-FmBfS1xUkWYvDYH/ysO7gAqGlaRzugLac8SIC+X/p76WBmhM6tJhfRW/BQ8mxOFZoVLmwhIiR8X0dRPKdasFxw==} peerDependencies: - nx: '>= 21 <= 23 || ^22.0.0-0' + nx: '>= 22 <= 24 || ^23.0.0-0' - '@nx/js@22.7.2': - resolution: {integrity: sha512-d1Hb/2n3QKE9rs8gRtfa/b1/GCGm1rnBFiqePivWbD/9iqerhgkbs6cg4MliLGRnD8gZgXSENLm4IW8ISOi69w==} + '@nx/js@23.1.1': + resolution: {integrity: sha512-8YnhKAnSE7lTiiUEoUyO5LBmZiRIqsc/v2qFMAUfbJKr2bAKAB4h+6Lz9ZfbMvRzJH3fcDZVVWVcvU5GXmQhzg==} peerDependencies: + '@swc/cli': '>=0.6.0 <0.9.0' verdaccio: ^6.0.5 peerDependenciesMeta: + '@swc/cli': + optional: true verdaccio: optional: true - '@nx/nx-darwin-arm64@22.7.2': - resolution: {integrity: sha512-hu+x/IOzx+18imkFwSdtXnvB6d21qcXvc4bCqcbA9BQcUnvTnw0/11SLoasvDqy/9KLKHDWJAIPttcBkbArWVA==} + '@nx/nx-darwin-arm64@23.1.1': + resolution: {integrity: sha512-Rq/RXLX5uIvJQfb6kuUgEirquT5ARaAgQyNaMZVnOPAL5wuxaDvQag8WX/WUCIgbUKZuGkclJwM7Vlnvtn3bdg==} cpu: [arm64] os: [darwin] - '@nx/nx-darwin-x64@22.7.2': - resolution: {integrity: sha512-M4QPs4rjzZN51V7qiKUjJU7hLYtv/h0I/aGUedCQQZibbbDTl45sQlgBQlV/viw2dOw3K5+RxDxtMNFxAbhxQA==} + '@nx/nx-darwin-x64@23.1.1': + resolution: {integrity: sha512-doWaPLPd6yUas3FhQJqMAScupCsToeTedK4RRWm700VhHoVdBTN4ejIBRBfoiT/SPAwY6EOHb8uFDJhGo7geMg==} cpu: [x64] os: [darwin] - '@nx/nx-freebsd-x64@22.7.2': - resolution: {integrity: sha512-tdC2mBQ/ON9qvTs72aL3XVN7B5wd7UsiRJ/qwC2bk/PIpD0vo5c3EwxFyYXfTD60jnlV+CTFxhSVmu8S1pVsfw==} + '@nx/nx-freebsd-x64@23.1.1': + resolution: {integrity: sha512-9rDZKBPGuX8mid11RimJ2ENqDYZpPZhrqTlI9q/VnqcPLq0Bw/8AhqCKhBVlfNqJjbi4OsRQYDK7UkqIlcfThg==} cpu: [x64] os: [freebsd] - '@nx/nx-linux-arm-gnueabihf@22.7.2': - resolution: {integrity: sha512-bBHIC9xZ8L12BWkwMKbRi7+oV4UH1v1Yy8PsIvRfjS7GzYNlOAUMkJxywjF2msnkp8M8Rn29MEvzllZjdyaR7Q==} + '@nx/nx-linux-arm-gnueabihf@23.1.1': + resolution: {integrity: sha512-NDR5X2HiD6WU3JEaDJmOLteIGIFqjrjkzoFWrQke2Y1oCRYu+UyFdPeaMVUyAs5OyUx4U+SD+eBQPTCNbWmazA==} cpu: [arm] os: [linux] - '@nx/nx-linux-arm64-gnu@22.7.2': - resolution: {integrity: sha512-MBYG58VUTmLW4S2RlYmXJiV6P0P1lkiZXtiaulZOXmP5uCSXiqMgK47k56hq9GTbtW1SpyGgh02lkNdCYTbmLw==} + '@nx/nx-linux-arm64-gnu@23.1.1': + resolution: {integrity: sha512-tWDHJII8+aHweTzHelf5dGM6qGNmHbAPhCc3jrtrM0uE+UD/wt2Dpq7H3086Iyia9M9jGM9sYpuD/6W6WAFAMA==} cpu: [arm64] os: [linux] libc: [glibc] - '@nx/nx-linux-arm64-musl@22.7.2': - resolution: {integrity: sha512-Wf4VBSJt5gEGdzX6uzZoITEYB/Y3TxjvPNT11NKfRU/m63b8/D8jCeRmr7cBTaMUlNmdH3Lf3G1PuPNGoEZ0Mg==} + '@nx/nx-linux-arm64-musl@23.1.1': + resolution: {integrity: sha512-t7iVMZ7Cj3LmPcfaYt9KOkojpuC5XRmtZ/0G+NBMA2GuRhCVbzpOgUCob0nQMV2TrTwn5oAWJeDc4xLni+oteg==} cpu: [arm64] os: [linux] libc: [musl] - '@nx/nx-linux-x64-gnu@22.7.2': - resolution: {integrity: sha512-v3AQyfCkv9k+AWT2hy8hAGaCmFYf+G/bt4KAqnWhmXPWNhxrv9FhvTUcjpY+MY+6v7sKdhJv/3eDvtlLd9FOLg==} + '@nx/nx-linux-x64-gnu@23.1.1': + resolution: {integrity: sha512-stuCayctOt/4AFvxKYgGTPluUc0HW7DcyTz9yeTMl/zj0+FENEr8RCTjInD0Q5qVGzYphma6SssVSh432w5agw==} cpu: [x64] os: [linux] libc: [glibc] - '@nx/nx-linux-x64-musl@22.7.2': - resolution: {integrity: sha512-3SMfMB7ynr8wGGTZP+/ZV7FqkCsOg1Raoka+4EtIPX66bEcBycg8FVg81DbyV+IzuKk3N+8Hl2IeY1W2btPypw==} + '@nx/nx-linux-x64-musl@23.1.1': + resolution: {integrity: sha512-cZSUqGV+iHda39W91BNKSysSu6OFfR6M4ViQBcMtbwq3ce19gDr2f23MqGZEQZtaD/eSQ9UNEhx09nhrdYxWDg==} cpu: [x64] os: [linux] libc: [musl] - '@nx/nx-win32-arm64-msvc@22.7.2': - resolution: {integrity: sha512-eTFTTF1JUKXu+PNOGd7KAdqyWyfvFKO/wpqHoq9fjnbjXgCdCg1PaRxHIxA1WT5HFj1iHS6Or+GC1zA1KNt0Sw==} + '@nx/nx-win32-arm64-msvc@23.1.1': + resolution: {integrity: sha512-iDlYbFHgTYV5lg1ypEt+LAj86o/uyy6vR0ha5pcUs4FqXzQgy14lOeyRod/EZs9Er3DIyJlEi/rpEvaP99/Hag==} cpu: [arm64] os: [win32] - '@nx/nx-win32-x64-msvc@22.7.2': - resolution: {integrity: sha512-fbVAiJ7RKSanUXrL67Z6as7BY1akznRqo71ACmrxLvLicG3UsmATbHKGp0zULoe3jBm+rNrIrLk+quZn5q0wUg==} + '@nx/nx-win32-x64-msvc@23.1.1': + resolution: {integrity: sha512-UD21AHWJ2PEA+PuANPCt+lj3kYpAzYNq+bm4VCbrt3KZd7zDPas0ns85UIhfrhsNiSmYzjWz2/JDk2S3cA6lGw==} cpu: [x64] os: [win32] - '@nx/workspace@22.7.2': - resolution: {integrity: sha512-xTEQMkeltIS6V5Qb6QRA7O+HIJQjIZSxLm6SvBNczJqAxckuYwMdbrb2IkDSE0XnQqR3gYg7Isz6UuBUHjz66Q==} + '@nx/workspace@23.1.1': + resolution: {integrity: sha512-woBDOW9bNcp+I2UEKhV62zc+1/gPCKPkTHZgwCdgoXSlXC3N9soGpnLG5QFy8NLodFC1f+5TSQJqN1tBW5rfIA==} '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} @@ -5369,6 +5374,10 @@ packages: redis: optional: true + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -5758,8 +5767,8 @@ packages: peerDependencies: cytoscape: ^3.2.0 - cytoscape@3.33.1: - resolution: {integrity: sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==} + cytoscape@3.34.0: + resolution: {integrity: sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==} engines: {node: '>=0.10'} d3-array@2.12.1: @@ -5926,8 +5935,8 @@ packages: dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} - dayjs@1.11.19: - resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} debounce-fn@6.0.0: resolution: {integrity: sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==} @@ -5977,6 +5986,14 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -5984,9 +6001,9 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} @@ -6074,8 +6091,8 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.4.12: - resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==} + dompurify@3.4.13: + resolution: {integrity: sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==} domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -6410,6 +6427,9 @@ packages: fast-json-stringify@6.0.1: resolution: {integrity: sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==} + fast-json-stringify@7.0.1: + resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==} + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} @@ -6439,8 +6459,8 @@ packages: fastify-plugin@6.0.0: resolution: {integrity: sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==} - fastify@5.8.5: - resolution: {integrity: sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==} + fastify@5.10.0: + resolution: {integrity: sha512-A9L0ziuWGQHgEEVgF3davQ9vbD93IuX+lo2IsxapQmu5b/Y/ynn9m9K5JHt9dvyJXOFc5iN0Zk5GHEOqnzhWjg==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -6707,10 +6727,6 @@ packages: resolution: {integrity: sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==} engines: {node: '>=20'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} @@ -6918,9 +6934,9 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true is-extglob@2.1.1: @@ -6947,6 +6963,11 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -7024,9 +7045,9 @@ packages: is-what@3.14.1: resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -7263,12 +7284,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.15.0: - resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} + js-yaml@3.15.1: + resolution: {integrity: sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==} hasBin: true - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + js-yaml@4.3.1: + resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true jsdom@25.0.0: @@ -7307,6 +7328,9 @@ packages: json-schema-ref-resolver@2.0.1: resolution: {integrity: sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==} + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -7327,9 +7351,6 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} @@ -7365,6 +7386,10 @@ packages: resolution: {integrity: sha512-1DJcK/L05k1Y9Gf7wMcyuqFOL6BiY3vY0CFcAM/LPRN04NALxcl6u7lOWNsp3f/bCHWxigzQl6FbR95XJ4R84Q==} hasBin: true + katex@0.16.47: + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + hasBin: true + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -7760,8 +7785,8 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - mermaid@11.15.0: - resolution: {integrity: sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw==} + mermaid@11.16.1: + resolution: {integrity: sha512-TQsq6u22fAn3rek5VOubrhKPo1g5hwC3FXUN9hiyupTckcYiGuuKGkNQrKYwGJkXUxZdojwRG46gsSCFZMDp4g==} methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -7865,8 +7890,8 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -7875,11 +7900,6 @@ packages: engines: {node: ^18 || >=20} hasBin: true - nanoid@5.1.7: - resolution: {integrity: sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==} - engines: {node: ^18 || >=20} - hasBin: true - napi-postinstall@0.3.4: resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -7984,8 +8004,8 @@ packages: nwsapi@2.2.16: resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} - nx@22.7.2: - resolution: {integrity: sha512-Gh7gGO1t/TvgbKuVJMYWbxUwZC+E+PuRRVUeoOeVe82yEvBNl40EKiVHIbbi6GID0s9Zwzflo07UrKGLoDSVGw==} + nx@23.1.1: + resolution: {integrity: sha512-oDdW2JgVllgfyyN6OqlRzeABw0QrlXdxyl9rtOUMMXQzlkpYA1RTs8jinJCe6QSo7aEn0dZ+Ar7dd09hMudBsg==} hasBin: true peerDependencies: '@swc-node/register': ^1.11.1 @@ -8060,9 +8080,9 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} openai@6.2.0: resolution: {integrity: sha512-qqjzHls7F5xkXNGy9P1Ei1rorI5LWupUUFWP66zPU8FlZbiITX8SFcHMKNZg/NATJ0LpIZcMUFxSwQmdeQPwSw==} @@ -8089,10 +8109,6 @@ packages: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} - ora@5.3.0: - resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} - engines: {node: '>=10'} - ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -8225,9 +8241,6 @@ packages: resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} engines: {node: 18 || 20 || >=22} - path-to-regexp@8.4.0: - resolution: {integrity: sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==} - path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} @@ -8868,6 +8881,10 @@ packages: rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} @@ -8960,6 +8977,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.4: + resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==} + engines: {node: '>=10'} + hasBin: true + send@1.2.1: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} @@ -9863,6 +9885,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -10008,6 +10035,11 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -10721,6 +10753,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@7.2.0) + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@7.2.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.29.7': dependencies: '@babel/parser': 7.29.7 @@ -10745,32 +10797,32 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-function-name': 7.24.6 '@babel/helper-member-expression-to-functions': 7.23.0 '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/helper-split-export-declaration': 7.24.6 semver: 6.3.1 - '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.4.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/helper-define-polyfill-provider@0.4.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@7.2.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -10796,6 +10848,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-imports@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/traverse': 7.29.7(supports-color@7.2.0) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) @@ -10805,22 +10864,31 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.22.5': dependencies: '@babel/types': 7.29.7 '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-wrap-function': 7.22.20 - '@babel/helper-replace-supers@7.22.20(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/helper-replace-supers@7.22.20(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-member-expression-to-functions': 7.23.0 '@babel/helper-optimise-call-expression': 7.22.5 @@ -10862,40 +10930,45 @@ snapshots: dependencies: '@babel/types': 7.29.7 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.7(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-proposal-decorators@7.23.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-proposal-decorators@7.23.7(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-decorators': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-decorators': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) @@ -10906,29 +10979,39 @@ snapshots: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-decorators@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-decorators@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.7(supports-color@10.2.2))': @@ -10936,495 +11019,560 @@ snapshots: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.7(supports-color@10.2.2))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-async-generator-functions@7.23.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-async-generator-functions@7.23.7(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.29.7(supports-color@7.2.0)) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-classes@7.23.8(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-classes@7.23.8(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-environment-visitor': 7.24.6 '@babel/helper-function-name': 7.24.6 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-split-export-declaration': 7.24.6 globals: 11.12.0 - '@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/template': 7.29.7 - '@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-for-of@7.23.6(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-for-of@7.23.6(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-function-name@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-function-name@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-function-name': 7.24.6 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-literals@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-literals@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-simple-access': 7.24.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-modules-systemjs@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@10.2.2) + '@babel/traverse': 7.29.7(supports-color@7.2.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-new-target@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-new-target@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-object-super@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-object-super@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-parameters@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-parameters@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-runtime@7.23.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/plugin-transform-runtime@7.23.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - babel-plugin-polyfill-corejs2: 0.4.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - babel-plugin-polyfill-regenerator: 0.5.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + babel-plugin-polyfill-corejs2: 0.4.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + babel-plugin-polyfill-regenerator: 0.5.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-spread@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-spread@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-typescript@7.23.6(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-typescript@7.23.6(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.29.7(supports-color@7.2.0)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/preset-env@7.23.8(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/preset-env@7.23.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.29.7 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-async-generator-functions': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-classes': 7.23.8(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-for-of': 7.23.6(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-modules-systemjs': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@10.2.2)) - babel-plugin-polyfill-corejs2: 0.4.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - babel-plugin-polyfill-regenerator: 0.5.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-async-generator-functions': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-classes': 7.23.8(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-for-of': 7.23.6(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-modules-systemjs': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@7.2.0)) + babel-plugin-polyfill-corejs2: 0.4.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + babel-plugin-polyfill-regenerator: 0.5.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) core-js-compat: 3.35.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/types': 7.29.7 esutils: 2.0.3 - '@babel/preset-typescript@7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/preset-typescript@7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.29.7 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.29.7(supports-color@7.2.0)) transitivePeerDependencies: - supports-color @@ -11462,6 +11610,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + '@babel/types@7.29.7': dependencies: '@babel/helper-string-parser': 7.29.7 @@ -11693,7 +11853,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 - js-yaml: 4.3.0 + js-yaml: 4.3.1 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -11738,7 +11898,7 @@ snapshots: jotai-scope: 0.7.2(jotai@2.11.0(@types/react@19.2.17)(react@19.2.7))(react@19.2.7) lodash.debounce: 4.0.8 lodash.throttle: 4.1.1 - nanoid: 3.3.8 + nanoid: 3.3.17 pako: 2.0.3 perfect-freehand: 1.2.0 pica: 7.1.1 @@ -11770,7 +11930,7 @@ snapshots: dependencies: '@excalidraw/markdown-to-text': 0.1.2 '@mermaid-js/parser': 0.6.3 - mermaid: 11.15.0 + mermaid: 11.16.1 nanoid: 5.1.16 '@excalidraw/random-username@1.1.0': {} @@ -11875,27 +12035,27 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@hocuspocus/common@4.4.0': + '@hocuspocus/common@4.5.0': dependencies: lib0: 0.2.117 - '@hocuspocus/provider-react@4.4.0(@hocuspocus/provider@4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(react@19.2.7)(yjs@13.6.30)': + '@hocuspocus/provider-react@4.5.0(@hocuspocus/provider@4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(react@19.2.7)(yjs@13.6.30)': dependencies: - '@hocuspocus/provider': 4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) + '@hocuspocus/provider': 4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) react: 19.2.7 yjs: 13.6.30 - '@hocuspocus/provider@4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30)': + '@hocuspocus/provider@4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30)': dependencies: - '@hocuspocus/common': 4.4.0 - '@lifeomic/attempt': 3.0.3 + '@hocuspocus/common': 4.5.0 + '@lifeomic/attempt': 3.1.0 lib0: 0.2.117 y-protocols: 1.0.6(yjs@13.6.30) yjs: 13.6.30 - '@hocuspocus/server@4.4.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30)': + '@hocuspocus/server@4.5.0(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30)': dependencies: - '@hocuspocus/common': 4.4.0 + '@hocuspocus/common': 4.5.0 async-mutex: 0.5.0 crossws: 0.4.10 kleur: 4.1.5 @@ -11905,7 +12065,7 @@ snapshots: transitivePeerDependencies: - srvx - '@hocuspocus/transformer@4.4.0(@tiptap/core@3.29.2(@tiptap/pm@3.29.2))(@tiptap/pm@3.29.2)(y-prosemirror@1.3.7(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.41.9)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(yjs@13.6.30)': + '@hocuspocus/transformer@4.5.0(@tiptap/core@3.29.2(@tiptap/pm@3.29.2))(@tiptap/pm@3.29.2)(y-prosemirror@1.3.7(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.41.9)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30))(yjs@13.6.30)': dependencies: '@tiptap/core': 3.29.2(@tiptap/pm@3.29.2) '@tiptap/pm': 3.29.2 @@ -12085,7 +12245,7 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.15.0 + js-yaml: 3.15.1 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.3': {} @@ -12271,11 +12431,11 @@ snapshots: '@joplin/turndown-plugin-gfm@1.0.64': {} - '@joplin/turndown@4.0.82(supports-color@10.2.2)': + '@joplin/turndown@4.0.82(supports-color@7.2.0)': dependencies: '@adobe/css-tools': 4.4.3 html-entities: 1.4.0 - jsdom: 26.1.0(supports-color@10.2.2) + jsdom: 26.1.0(supports-color@7.2.0) transitivePeerDependencies: - bufferutil - canvas @@ -12343,7 +12503,7 @@ snapshots: '@langchain/core': 1.1.46(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.21.0)(zod@4.3.6))(ws@8.21.0) js-tiktoken: 1.0.21 - '@lifeomic/attempt@3.0.3': {} + '@lifeomic/attempt@3.1.0': {} '@lukeed/csprng@1.1.0': {} @@ -12362,12 +12522,12 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mantine/dates@9.3.2(@mantine/core@9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.3.2(react@19.2.7))(dayjs@1.11.19)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@mantine/dates@9.3.2(@mantine/core@9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.3.2(react@19.2.7))(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@mantine/core': 9.3.2(@mantine/hooks@9.3.2(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mantine/hooks': 9.3.2(react@19.2.7) clsx: 2.1.1 - dayjs: 1.11.19 + dayjs: 1.11.21 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -12414,7 +12574,7 @@ snapshots: dependencies: langium: 3.3.1 - '@mermaid-js/parser@1.1.1': + '@mermaid-js/parser@1.2.0': dependencies: '@chevrotain/types': 11.1.2 @@ -12480,40 +12640,40 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true - '@nest-lab/throttler-storage-redis@1.2.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2))(ioredis@5.10.1(supports-color@10.2.2))(reflect-metadata@0.2.2)': + '@nest-lab/throttler-storage-redis@1.2.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2))(ioredis@5.10.1(supports-color@10.2.2))(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2) ioredis: 5.10.1(supports-color@10.2.2) reflect-metadata: 0.2.2 tslib: 2.8.1 - '@nestjs-labs/nestjs-ioredis@11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(ioredis@5.10.1(supports-color@10.2.2))': + '@nestjs-labs/nestjs-ioredis@11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(ioredis@5.10.1(supports-color@10.2.2))': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) ioredis: 5.10.1(supports-color@10.2.2) tslib: 2.8.1 - '@nestjs/bull-shared@11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': + '@nestjs/bull-shared@11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(bullmq@5.79.0(supports-color@10.2.2))': + '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(bullmq@5.79.0(supports-color@10.2.2))': dependencies: - '@nestjs/bull-shared': 11.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/bull-shared': 11.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) bullmq: 5.79.0(supports-color@10.2.2) tslib: 2.8.1 - '@nestjs/cache-manager@3.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2)': + '@nestjs/cache-manager@3.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) cache-manager: 7.2.8 keyv: 5.6.0 rxjs: 7.8.2 @@ -12546,7 +12706,7 @@ snapshots: - uglify-js - webpack-cli - '@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2)': + '@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2)': dependencies: file-type: 21.3.4(supports-color@10.2.2) iterare: 1.2.1 @@ -12561,17 +12721,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@nestjs/config@4.0.4(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(rxjs@7.8.2)': + '@nestjs/config@4.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) dotenv: 17.4.1 dotenv-expand: 12.0.3 lodash: 4.18.1 rxjs: 7.8.2 - '@nestjs/core@11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) fast-safe-stringify: 2.1.1 iterare: 1.2.1 path-to-regexp: 8.4.2 @@ -12580,41 +12740,41 @@ snapshots: tslib: 2.8.1 uid: 2.0.2 optionalDependencies: - '@nestjs/websockets': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/websockets': 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/event-emitter@3.1.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': + '@nestjs/event-emitter@3.1.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) eventemitter2: 6.4.9 - '@nestjs/jwt@11.0.2(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))': + '@nestjs/jwt@11.0.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) '@types/jsonwebtoken': 9.0.10 jsonwebtoken: 9.0.3 - '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': + '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) reflect-metadata: 0.2.2 optionalDependencies: class-transformer: 0.5.1 class-validator: 0.15.1 - '@nestjs/passport@11.0.5(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(passport@0.7.0)': + '@nestjs/passport@11.0.5(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(passport@0.7.0)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) passport: 0.7.0 - '@nestjs/platform-fastify@11.1.27(@fastify/static@10.1.2)(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': + '@nestjs/platform-fastify@11.1.28(@fastify/static@10.1.2)(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': dependencies: '@fastify/cors': 11.2.0 '@fastify/formbody': 8.0.2 - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) fast-querystring: 1.1.2 - fastify: 5.8.5 + fastify: 5.10.0 fastify-plugin: 6.0.0 find-my-way: 9.7.0 light-my-request: 6.6.0 @@ -12624,10 +12784,10 @@ snapshots: optionalDependencies: '@fastify/static': 10.1.2 - '@nestjs/platform-socket.io@11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(rxjs@7.8.2)(supports-color@10.2.2)': + '@nestjs/platform-socket.io@11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(rxjs@7.8.2)(supports-color@10.2.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/websockets': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/websockets': 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) rxjs: 7.8.2 socket.io: 4.8.3(supports-color@10.2.2) tslib: 2.8.1 @@ -12636,10 +12796,10 @@ snapshots: - supports-color - utf-8-validate - '@nestjs/schedule@6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': + '@nestjs/schedule@6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) cron: 4.4.0 '@nestjs/schematics@11.0.10(chokidar@4.0.3)(typescript@5.9.3)': @@ -12653,38 +12813,38 @@ snapshots: transitivePeerDependencies: - chokidar - '@nestjs/terminus@11.1.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/terminus@11.1.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) boxen: 5.1.2 check-disk-space: 3.4.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 - '@nestjs/testing@11.1.19(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': + '@nestjs/testing@11.1.19(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/throttler@6.5.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)': + '@nestjs/throttler@6.5.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 - '@nestjs/websockets@11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/websockets@11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) iterare: 1.2.1 object-hash: 3.0.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@nestjs/platform-socket.io': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/platform-socket.io': 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(rxjs@7.8.2)(supports-color@10.2.2) '@noble/hashes@1.8.0': {} @@ -12720,38 +12880,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@nx/devkit@22.7.2(nx@22.7.2(debug@4.4.3(supports-color@10.2.2)))': + '@nx/devkit@23.1.1(nx@23.1.1)': dependencies: - '@zkochan/js-yaml': 0.0.7 ejs: 5.0.1 enquirer: 2.3.6 minimatch: 10.2.5 - nx: 22.7.2(debug@4.4.3(supports-color@10.2.2)) + nx: 23.1.1 semver: 7.7.4 tslib: 2.8.1 yargs-parser: 21.1.1 - '@nx/js@22.7.2(@babel/traverse@7.29.7(supports-color@10.2.2))(debug@4.4.3(supports-color@10.2.2))(nx@22.7.2(debug@4.4.3(supports-color@10.2.2)))(supports-color@10.2.2)': + '@nx/js@23.1.1(@babel/traverse@7.29.7(supports-color@7.2.0))(nx@23.1.1)(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/plugin-proposal-decorators': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-transform-runtime': 7.23.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/preset-env': 7.23.8(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@babel/preset-typescript': 7.23.3(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/plugin-proposal-decorators': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-runtime': 7.23.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/preset-env': 7.23.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/preset-typescript': 7.23.3(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) '@babel/runtime': 7.29.2 - '@nx/devkit': 22.7.2(nx@22.7.2(debug@4.4.3(supports-color@10.2.2))) - '@nx/workspace': 22.7.2(debug@4.4.3(supports-color@10.2.2)) + '@nx/devkit': 23.1.1(nx@23.1.1) + '@nx/workspace': 23.1.1 '@zkochan/js-yaml': 0.0.7 - babel-plugin-const-enum: 1.2.0(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + babel-plugin-const-enum: 1.2.0(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) babel-plugin-macros: 3.1.0 - babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.29.7(supports-color@10.2.2))(@babel/traverse@7.29.7(supports-color@10.2.2)) + babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.29.7(supports-color@7.2.0))(@babel/traverse@7.29.7(supports-color@7.2.0)) chalk: 4.1.2 columnify: 1.6.0 detect-port: 2.1.0 ignore: 7.0.5 js-tokens: 4.0.0 - jsonc-parser: 3.2.0 + jsonc-parser: 3.3.1 npm-run-path: 4.0.1 picocolors: 1.1.1 picomatch: 4.0.4 @@ -12763,47 +12925,46 @@ snapshots: - '@babel/traverse' - '@swc-node/register' - '@swc/core' - - debug - nx - supports-color - '@nx/nx-darwin-arm64@22.7.2': + '@nx/nx-darwin-arm64@23.1.1': optional: true - '@nx/nx-darwin-x64@22.7.2': + '@nx/nx-darwin-x64@23.1.1': optional: true - '@nx/nx-freebsd-x64@22.7.2': + '@nx/nx-freebsd-x64@23.1.1': optional: true - '@nx/nx-linux-arm-gnueabihf@22.7.2': + '@nx/nx-linux-arm-gnueabihf@23.1.1': optional: true - '@nx/nx-linux-arm64-gnu@22.7.2': + '@nx/nx-linux-arm64-gnu@23.1.1': optional: true - '@nx/nx-linux-arm64-musl@22.7.2': + '@nx/nx-linux-arm64-musl@23.1.1': optional: true - '@nx/nx-linux-x64-gnu@22.7.2': + '@nx/nx-linux-x64-gnu@23.1.1': optional: true - '@nx/nx-linux-x64-musl@22.7.2': + '@nx/nx-linux-x64-musl@23.1.1': optional: true - '@nx/nx-win32-arm64-msvc@22.7.2': + '@nx/nx-win32-arm64-msvc@23.1.1': optional: true - '@nx/nx-win32-x64-msvc@22.7.2': + '@nx/nx-win32-x64-msvc@23.1.1': optional: true - '@nx/workspace@22.7.2(debug@4.4.3(supports-color@10.2.2))': + '@nx/workspace@23.1.1': dependencies: - '@nx/devkit': 22.7.2(nx@22.7.2(debug@4.4.3(supports-color@10.2.2))) + '@nx/devkit': 23.1.1(nx@23.1.1) '@zkochan/js-yaml': 0.0.7 chalk: 4.1.2 enquirer: 2.3.6 - nx: 22.7.2(debug@4.4.3(supports-color@10.2.2)) + nx: 23.1.1 picomatch: 4.0.4 semver: 7.7.4 tslib: 2.8.1 @@ -12811,7 +12972,6 @@ snapshots: transitivePeerDependencies: - '@swc-node/register' - '@swc/core' - - debug '@opentelemetry/api@1.9.0': {} @@ -15118,9 +15278,19 @@ snapshots: - debug - supports-color - axios@1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@7.2.0): + axios@1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2): dependencies: - follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2)) + follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) + form-data: 4.0.6 + https-proxy-agent: 5.0.1(supports-color@10.2.2) + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + axios@1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0): + dependencies: + follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) form-data: 4.0.6 https-proxy-agent: 5.0.1(supports-color@7.2.0) proxy-from-env: 2.1.0 @@ -15141,12 +15311,12 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-const-enum@1.2.0(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2): + babel-plugin-const-enum@1.2.0(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/traverse': 7.29.7(supports-color@10.2.2) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/traverse': 7.29.7(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -15170,36 +15340,36 @@ snapshots: cosmiconfig: 7.1.0 resolve: 1.22.8 - babel-plugin-polyfill-corejs2@0.4.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2): + babel-plugin-polyfill-corejs2@0.4.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): dependencies: '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.8.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2): + babel-plugin-polyfill-corejs3@0.8.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) core-js-compat: 3.35.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.5.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2): + babel-plugin-polyfill-regenerator@0.5.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - supports-color - babel-plugin-transform-typescript-metadata@0.3.2(@babel/core@7.29.7(supports-color@10.2.2))(@babel/traverse@7.29.7(supports-color@10.2.2)): + babel-plugin-transform-typescript-metadata@0.3.2(@babel/core@7.29.7(supports-color@7.2.0))(@babel/traverse@7.29.7(supports-color@7.2.0)): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 optionalDependencies: - '@babel/traverse': 7.29.7(supports-color@10.2.2) + '@babel/traverse': 7.29.7(supports-color@7.2.0) babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7(supports-color@10.2.2)): dependencies: @@ -15344,6 +15514,10 @@ snapshots: transitivePeerDependencies: - supports-color + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + bytes@3.1.2: {} cache-manager@7.2.8: @@ -15633,7 +15807,7 @@ snapshots: cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.0 - js-yaml: 4.3.0 + js-yaml: 4.3.1 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: @@ -15643,7 +15817,7 @@ snapshots: dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 - js-yaml: 4.3.0 + js-yaml: 4.3.1 parse-json: 5.2.0 optionalDependencies: typescript: 5.9.3 @@ -15712,17 +15886,17 @@ snapshots: csv-stringify@6.8.0: {} - cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1): + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.0): dependencies: cose-base: 1.0.3 - cytoscape: 3.33.1 + cytoscape: 3.34.0 - cytoscape-fcose@2.2.0(cytoscape@3.33.1): + cytoscape-fcose@2.2.0(cytoscape@3.34.0): dependencies: cose-base: 2.2.0 - cytoscape: 3.33.1 + cytoscape: 3.34.0 - cytoscape@3.33.1: {} + cytoscape@3.34.0: {} d3-array@2.12.1: dependencies: @@ -15923,7 +16097,7 @@ snapshots: dateformat@4.6.3: {} - dayjs@1.11.19: {} + dayjs@1.11.21: {} debounce-fn@6.0.0: dependencies: @@ -15961,6 +16135,13 @@ snapshots: deepmerge@4.3.1: {} + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + defaults@1.0.4: dependencies: clone: 1.0.4 @@ -15971,7 +16152,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - define-lazy-prop@2.0.0: {} + define-lazy-prop@3.0.0: {} define-properties@1.2.1: dependencies: @@ -16027,7 +16208,7 @@ snapshots: '@types/node': 25.5.0 hash.js: 1.1.7 jszip: 3.10.1 - nanoid: 5.1.7 + nanoid: 5.1.16 xml: 1.0.1 xml-js: 1.6.11 @@ -16052,7 +16233,7 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.4.12: + dompurify@3.4.13: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -16545,6 +16726,15 @@ snapshots: json-schema-ref-resolver: 2.0.1 rfdc: 1.3.1 + fast-json-stringify@7.0.1: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + fast-uri: 3.1.5 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.3.1 + fast-levenshtein@2.0.6: {} fast-querystring@1.1.2: @@ -16575,7 +16765,7 @@ snapshots: fastify-plugin@6.0.0: {} - fastify@5.8.5: + fastify@5.10.0: dependencies: '@fastify/ajv-compiler': 4.0.5 '@fastify/error': 4.0.0 @@ -16583,7 +16773,7 @@ snapshots: '@fastify/proxy-addr': 5.0.0 abstract-logging: 2.0.1 avvio: 9.1.0 - fast-json-stringify: 6.0.1 + fast-json-stringify: 7.0.1 find-my-way: 9.7.0 light-my-request: 6.6.0 pino: 10.1.0 @@ -16670,6 +16860,10 @@ snapshots: optionalDependencies: debug: 4.4.3(supports-color@10.2.2) + follow-redirects@1.16.0(debug@4.4.3(supports-color@7.2.0)): + optionalDependencies: + debug: 4.4.3(supports-color@7.2.0) + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -16872,10 +17066,6 @@ snapshots: dependencies: hookified: 1.15.1 - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -16945,6 +17135,13 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-agent@7.0.2(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + https-proxy-agent@5.0.1(supports-color@10.2.2): dependencies: agent-base: 6.0.2(supports-color@10.2.2) @@ -16966,6 +17163,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} i18next-http-backend@3.0.6: @@ -17099,7 +17303,7 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-docker@2.2.1: {} + is-docker@3.0.0: {} is-extglob@2.1.1: {} @@ -17119,6 +17323,10 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-interactive@1.0.0: {} is-map@2.0.3: {} @@ -17184,9 +17392,9 @@ snapshots: is-what@3.14.1: optional: true - is-wsl@2.2.0: + is-wsl@3.1.0: dependencies: - is-docker: 2.2.1 + is-inside-container: 1.0.0 isarray@1.0.0: {} @@ -17591,12 +17799,12 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@3.15.0: + js-yaml@3.15.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.3.0: + js-yaml@4.3.1: dependencies: argparse: 2.0.1 @@ -17628,14 +17836,14 @@ snapshots: - supports-color - utf-8-validate - jsdom@26.1.0(supports-color@10.2.2): + jsdom@26.1.0(supports-color@7.2.0): dependencies: cssstyle: 4.2.1 data-urls: 5.0.0 decimal.js: 10.6.0 html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@7.2.0) + https-proxy-agent: 7.0.6(supports-color@7.2.0) is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.16 parse5: 7.3.0 @@ -17667,6 +17875,10 @@ snapshots: dependencies: dequal: 2.0.3 + json-schema-ref-resolver@3.0.0: + dependencies: + dequal: 2.0.3 + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -17679,8 +17891,6 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.0: {} - jsonc-parser@3.3.1: {} jsonfile@6.1.0: @@ -17735,6 +17945,10 @@ snapshots: dependencies: commander: 8.3.0 + katex@0.16.47: + dependencies: + commander: 8.3.0 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -18047,23 +18261,23 @@ snapshots: merge-stream@2.0.0: {} - mermaid@11.15.0: + mermaid@11.16.1: dependencies: '@braintree/sanitize-url': 7.1.2 '@iconify/utils': 3.1.0 - '@mermaid-js/parser': 1.1.1 + '@mermaid-js/parser': 1.2.0 '@types/d3': 7.4.3 '@upsetjs/venn.js': 2.0.0 - cytoscape: 3.33.1 - cytoscape-cose-bilkent: 4.1.0(cytoscape@3.33.1) - cytoscape-fcose: 2.2.0(cytoscape@3.33.1) + cytoscape: 3.34.0 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.0) + cytoscape-fcose: 2.2.0(cytoscape@3.34.0) d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.14 - dayjs: 1.11.19 - dompurify: 3.4.12 + dayjs: 1.11.21 + dompurify: 3.4.13 es-toolkit: 1.46.1 - katex: 0.16.40 + katex: 0.16.47 khroma: 2.1.0 marked: 16.4.2 roughjs: 4.6.6 @@ -18159,12 +18373,10 @@ snapshots: mute-stream@2.0.0: {} - nanoid@3.3.8: {} + nanoid@3.3.17: {} nanoid@5.1.16: {} - nanoid@5.1.7: {} - napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -18181,23 +18393,23 @@ snapshots: neo-async@2.6.2: {} - nestjs-cls@6.2.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2): + nestjs-cls@6.2.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2): dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 rxjs: 7.8.2 - nestjs-kysely@3.1.2(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(kysely@0.28.17)(reflect-metadata@0.2.2): + nestjs-kysely@3.1.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/core@11.1.27)(kysely@0.28.17)(reflect-metadata@0.2.2): dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) - '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/core': 11.1.27(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) kysely: 0.28.17 reflect-metadata: 0.2.2 - nestjs-pino@4.6.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): + nestjs-pino@4.6.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): dependencies: - '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) + '@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@10.2.2) pino: 10.1.0 pino-http: 11.0.0 rxjs: 7.8.2 @@ -18241,7 +18453,7 @@ snapshots: nwsapi@2.2.16: {} - nx@22.7.2(debug@4.4.3(supports-color@10.2.2)): + nx@23.1.1: dependencies: '@emnapi/core': 1.4.5 '@emnapi/runtime': 1.4.5 @@ -18251,17 +18463,19 @@ snapshots: '@tybys/wasm-util': 0.9.0 '@yarnpkg/lockfile': 1.1.0 '@zkochan/js-yaml': 0.0.7 + agent-base: 6.0.2(supports-color@7.2.0) ansi-colors: 4.1.3 ansi-regex: 5.0.1 ansi-styles: 4.3.0 argparse: 2.0.1 asynckit: 0.4.0 - axios: 1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@7.2.0) + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) balanced-match: 4.0.3 base64-js: 1.5.1 bl: 4.1.0 brace-expansion: 5.0.9 buffer: 5.7.1 + bundle-name: 4.1.0 call-bind-apply-helpers: 1.0.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -18271,8 +18485,11 @@ snapshots: color-convert: 2.0.1 color-name: 1.1.4 combined-stream: 1.0.8 + debug: 4.4.3(supports-color@7.2.0) + default-browser: 5.2.1 + default-browser-id: 5.0.0 defaults: 1.0.4 - define-lazy-prop: 2.0.0 + define-lazy-prop: 3.0.0 delayed-stream: 1.0.0 dotenv: 16.4.7 dotenv-expand: 12.0.3 @@ -18289,7 +18506,7 @@ snapshots: escape-string-regexp: 1.0.5 figures: 3.2.0 flat: 5.0.2 - follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2)) + follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) form-data: 4.0.6 fs-constants: 1.0.0 function-bind: 1.1.2 @@ -18300,17 +18517,20 @@ snapshots: has-flag: 4.0.0 has-symbols: 1.1.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 + https-proxy-agent: 5.0.1(supports-color@7.2.0) ieee754: 1.2.1 ignore: 7.0.5 inherits: 2.0.4 - is-docker: 2.2.1 + is-docker: 3.0.0 is-fullwidth-code-point: 3.0.0 + is-inside-container: 1.0.0 is-interactive: 1.0.0 is-unicode-supported: 0.1.0 - is-wsl: 2.2.0 + is-wsl: 3.1.0 + isexe: 2.0.0 json5: 2.2.3 - jsonc-parser: 3.2.0 + jsonc-parser: 3.3.1 lines-and-columns: 2.0.3 log-symbols: 4.1.0 math-intrinsics: 1.1.0 @@ -18319,11 +18539,12 @@ snapshots: mimic-fn: 2.1.0 minimatch: 10.2.5 minimist: 1.2.8 + ms: 2.1.3 npm-run-path: 4.0.1 once: 1.4.0 onetime: 5.1.2 - open: 8.4.2 - ora: 5.3.0 + open: 10.1.0 + ora: 5.4.1 path-key: 3.1.1 picocolors: 1.1.1 proxy-from-env: 2.1.0 @@ -18331,8 +18552,9 @@ snapshots: require-directory: 2.1.1 resolve.exports: 2.0.3 restore-cursor: 3.1.0 + run-applescript: 7.0.0 safe-buffer: 5.2.1 - semver: 7.7.4 + semver: 7.8.4 signal-exit: 3.0.7 smol-toml: 1.6.1 string-width: 4.2.3 @@ -18342,30 +18564,28 @@ snapshots: supports-color: 7.2.0 tar-stream: 2.2.0 tmp: 0.2.7 - tree-kill: 1.2.2 tsconfig-paths: 4.2.0 tslib: 2.8.1 util-deprecate: 1.0.2 wcwidth: 1.0.1 + which: 3.0.1 wrap-ansi: 7.0.0 wrappy: 1.0.2 y18n: 5.0.8 - yaml: 2.8.3 + yaml: 2.9.0 yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 22.7.2 - '@nx/nx-darwin-x64': 22.7.2 - '@nx/nx-freebsd-x64': 22.7.2 - '@nx/nx-linux-arm-gnueabihf': 22.7.2 - '@nx/nx-linux-arm64-gnu': 22.7.2 - '@nx/nx-linux-arm64-musl': 22.7.2 - '@nx/nx-linux-x64-gnu': 22.7.2 - '@nx/nx-linux-x64-musl': 22.7.2 - '@nx/nx-win32-arm64-msvc': 22.7.2 - '@nx/nx-win32-x64-msvc': 22.7.2 - transitivePeerDependencies: - - debug + '@nx/nx-darwin-arm64': 23.1.1 + '@nx/nx-darwin-x64': 23.1.1 + '@nx/nx-freebsd-x64': 23.1.1 + '@nx/nx-linux-arm-gnueabihf': 23.1.1 + '@nx/nx-linux-arm64-gnu': 23.1.1 + '@nx/nx-linux-arm64-musl': 23.1.1 + '@nx/nx-linux-x64-gnu': 23.1.1 + '@nx/nx-linux-x64-musl': 23.1.1 + '@nx/nx-win32-arm64-msvc': 23.1.1 + '@nx/nx-win32-x64-msvc': 23.1.1 nypm@0.6.6: dependencies: @@ -18435,11 +18655,12 @@ snapshots: dependencies: mimic-fn: 2.1.0 - open@8.4.2: + open@10.1.0: dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 openai@6.2.0(ws@8.21.0)(zod@4.3.6): optionalDependencies: @@ -18465,17 +18686,6 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - ora@5.3.0: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - ora@5.4.1: dependencies: bl: 4.1.0 @@ -18615,8 +18825,6 @@ snapshots: lru-cache: 11.2.7 minipass: 7.1.3 - path-to-regexp@8.4.0: {} - path-to-regexp@8.4.2: {} path-type@4.0.0: {} @@ -18820,7 +19028,7 @@ snapshots: postcss@8.5.25: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.17 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -18845,15 +19053,15 @@ snapshots: '@posthog/core': 1.35.3 '@posthog/types': 1.390.2 core-js: 3.43.0 - dompurify: 3.4.12 + dompurify: 3.4.13 fflate: 0.4.8 preact: 10.29.2 query-selector-shadow-dom: 1.0.1 web-vitals: 5.3.0 - postmark@4.0.7(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2): + postmark@4.0.7(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2): dependencies: - axios: 1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2) transitivePeerDependencies: - debug - supports-color @@ -19389,7 +19597,7 @@ snapshots: depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 - path-to-regexp: 8.4.0 + path-to-regexp: 8.4.2 transitivePeerDependencies: - supports-color @@ -19397,6 +19605,8 @@ snapshots: rrweb-cssom@0.8.0: {} + run-applescript@7.0.0: {} + rw@1.3.3: {} rxjs@7.8.1: @@ -19486,6 +19696,8 @@ snapshots: semver@7.8.1: {} + semver@7.8.4: {} + send@1.2.1(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) @@ -20117,10 +20329,10 @@ snapshots: typescript@5.9.3: {} - typesense@3.0.5(@babel/runtime@7.29.2)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2): + typesense@3.0.5(@babel/runtime@7.29.2)(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2): dependencies: '@babel/runtime': 7.29.2 - axios: 1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@10.2.2) loglevel: 1.9.2 tslib: 2.8.1 transitivePeerDependencies: @@ -20451,6 +20663,10 @@ snapshots: dependencies: isexe: 2.0.0 + which@3.0.1: + dependencies: + isexe: 2.0.0 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -20562,7 +20778,10 @@ snapshots: yaml@1.10.3: {} - yaml@2.8.3: {} + yaml@2.8.3: + optional: true + + yaml@2.9.0: {} yargs-parser@18.1.3: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bb613ba56..ba6f1af39 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,11 +7,11 @@ overrides: prosemirror-changeset: 2.4.0 glob: 13.0.6 ws: 8.21.0 - dompurify: 3.4.12 - mermaid: 11.15.0 + dompurify: 3.4.13 + mermaid: 11.16.1 undici: 7.29.0 tmp: 0.2.7 - nanoid@^3: 3.3.8 + nanoid@^3: 3.3.17 lodash-es: 4.18.1 express-rate-limit: 8.2.2 flatted: 3.4.2 @@ -22,9 +22,11 @@ overrides: ip-address: 10.3.1 fast-uri: 3.1.5 form-data@>=4.0.0 <4.0.6: 4.0.6 - nanoid@>=4.0.0 <5.0.9: 5.1.16 + nanoid@>=4.0.0 <5.1.16: 5.1.16 esbuild@>=0.27.3 <0.28.1: 0.28.1 '@opentelemetry/core@>=2.0.0 <2.8.0': 2.9.0 + js-yaml@>=3.0.0 <3.15.1: 3.15.1 + js-yaml@>=4.0.0 <4.3.1: 4.3.1 shamefullyHoist: true minimumReleaseAge: 4320 allowBuilds: From a0b2ac6ae3f481dc05028877eeeebaaf7ab05fde Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:30:30 +0100 Subject: [PATCH 4/9] feat: footnotes (#2384) * feat: footnotes * feat: proper DOCX support --- .../public/locales/en-US/translation.json | 2 + .../groups/more-inserts-group.tsx | 7 + .../components/slash-menu/menu-items.ts | 11 + .../features/editor/extensions/extensions.ts | 14 +- .../src/features/editor/styles/footnotes.css | 26 +++ .../src/features/editor/styles/index.css | 1 + .../src/collaboration/collaboration.util.ts | 13 +- apps/server/src/ee | 2 +- packages/editor-ext/src/index.ts | 1 + .../editor-ext/src/lib/footnotes/footnote.ts | 189 +++++++++++++++ .../editor-ext/src/lib/footnotes/footnotes.ts | 46 ++++ .../editor-ext/src/lib/footnotes/index.ts | 4 + .../editor-ext/src/lib/footnotes/reference.ts | 221 ++++++++++++++++++ .../editor-ext/src/lib/footnotes/rules.ts | 90 +++++++ .../editor-ext/src/lib/footnotes/utils.ts | 123 ++++++++++ .../lib/markdown/utils/footnotes.marked.ts | 110 +++++++++ .../src/lib/markdown/utils/marked.utils.ts | 18 +- .../src/lib/markdown/utils/turndown.utils.ts | 52 +++++ .../src/lib/prosemirror-docx/schema.ts | 23 +- .../src/lib/prosemirror-docx/serializer.ts | 23 ++ packages/editor-ext/src/lib/trailing-node.ts | 20 +- 21 files changed, 987 insertions(+), 9 deletions(-) create mode 100644 apps/client/src/features/editor/styles/footnotes.css create mode 100644 packages/editor-ext/src/lib/footnotes/footnote.ts create mode 100644 packages/editor-ext/src/lib/footnotes/footnotes.ts create mode 100644 packages/editor-ext/src/lib/footnotes/index.ts create mode 100644 packages/editor-ext/src/lib/footnotes/reference.ts create mode 100644 packages/editor-ext/src/lib/footnotes/rules.ts create mode 100644 packages/editor-ext/src/lib/footnotes/utils.ts create mode 100644 packages/editor-ext/src/lib/markdown/utils/footnotes.marked.ts diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 18c981434..aaa340181 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -387,6 +387,8 @@ "Insert horizontal rule divider": "Insert horizontal rule divider", "Page break": "Page break", "Insert a page break for printing.": "Insert a page break for printing.", + "Footnote": "Footnote", + "Insert a footnote reference.": "Insert a footnote reference.", "Upload any image from your device.": "Upload any image from your device.", "Upload any video from your device.": "Upload any video from your device.", "Upload any audio from your device.": "Upload any audio from your device.", diff --git a/apps/client/src/features/editor/components/fixed-toolbar/groups/more-inserts-group.tsx b/apps/client/src/features/editor/components/fixed-toolbar/groups/more-inserts-group.tsx index b12f609cf..f2ae8b912 100644 --- a/apps/client/src/features/editor/components/fixed-toolbar/groups/more-inserts-group.tsx +++ b/apps/client/src/features/editor/components/fixed-toolbar/groups/more-inserts-group.tsx @@ -12,6 +12,7 @@ import { IconMathFunction, IconRotate2, IconSitemap, + IconSuperscript, IconTable, IconTag, } from "@tabler/icons-react"; @@ -270,6 +271,12 @@ export const MoreInsertsGroup: FC = ({ editor, templateMode }) => { > {t("Math block")} + } + onClick={() => editor.chain().focus().addFootnote().run()} + > + {t("Footnote")} + ); diff --git a/apps/client/src/features/editor/components/slash-menu/menu-items.ts b/apps/client/src/features/editor/components/slash-menu/menu-items.ts index 0327acdde..d8598c5ea 100644 --- a/apps/client/src/features/editor/components/slash-menu/menu-items.ts +++ b/apps/client/src/features/editor/components/slash-menu/menu-items.ts @@ -30,6 +30,7 @@ import { IconTag, IconMoodSmile, IconRotate2, + IconSuperscript, } from "@tabler/icons-react"; import { CommandProps, @@ -177,6 +178,16 @@ const CommandGroups: SlashMenuGroupedItemsType = { command: ({ editor, range }: CommandProps) => editor.chain().focus().deleteRange(range).setPageBreak().run(), }, + { + title: "Footnote", + description: "Insert a footnote reference.", + searchTerms: ["footnote", "reference", "citation", "note"], + icon: IconSuperscript, + command: ({ editor, range }: CommandProps) => { + editor.chain().focus().deleteRange(range).run(); + editor.commands.addFootnote(); + }, + }, { title: "Image", description: "Upload any image from your device.", diff --git a/apps/client/src/features/editor/extensions/extensions.ts b/apps/client/src/features/editor/extensions/extensions.ts index bdbd78ad8..c72456e6e 100644 --- a/apps/client/src/features/editor/extensions/extensions.ts +++ b/apps/client/src/features/editor/extensions/extensions.ts @@ -1,5 +1,6 @@ import { markInputRule } from "@tiptap/core"; import { StarterKit } from "@tiptap/starter-kit"; +import { Document } from "@tiptap/extension-document"; import { Code } from "@tiptap/extension-code"; import { TextAlign } from "@tiptap/extension-text-align"; import { TaskList, TaskItem } from "@tiptap/extension-list"; @@ -63,6 +64,9 @@ import { TransclusionReference, TableView, BaseEmbed as BaseEmbedNode, + Footnotes, + Footnote, + FootnoteReference, } from "@docmost/editor-ext"; import { randomElement, @@ -132,6 +136,7 @@ lowlight.register("scala", scala); // @ts-ignore export const mainExtensions = [ StarterKit.configure({ + document: false, heading: false, undoRedo: false, link: false, @@ -143,6 +148,9 @@ export const mainExtensions = [ codeBlock: false, code: false, }), + Document.extend({ + content: "block+ footnotes?", + }), // Override TipTap's Code extension to fix the inline code input rule. // The upstream regex /(^|[^`])`([^`]+)`(?!`)$/ captures the character // before the opening backtick as part of the match, causing markInputRule @@ -203,7 +211,8 @@ export const mainExtensions = [ parentName === "tableCell" || parentName === "tableHeader" || parentName === "callout" || - parentName === "blockquote" + parentName === "blockquote" || + parentName === "footnote" ) { return i18n.t("Write..."); } @@ -417,6 +426,9 @@ export const mainExtensions = [ }).configure(), Columns, Column, + Footnotes, + Footnote, + FootnoteReference, AutoJoiner.configure({ elementsToJoin: [], }), diff --git a/apps/client/src/features/editor/styles/footnotes.css b/apps/client/src/features/editor/styles/footnotes.css new file mode 100644 index 000000000..26edf51cf --- /dev/null +++ b/apps/client/src/features/editor/styles/footnotes.css @@ -0,0 +1,26 @@ +.ProseMirror sup a.footnote-ref { + color: var(--mantine-primary-color-filled); + text-decoration: none; + cursor: pointer; + font-weight: 600; +} + +.ProseMirror sup:has(a.footnote-ref) { + padding: 0 1px; +} + +.ProseMirror ol.footnotes { + margin-top: 2rem; + padding-top: 0.75rem; + font-size: 0.875rem; + color: var(--mantine-color-dimmed); + list-style-type: decimal; +} + +.ProseMirror ol.footnotes:has(li) { + border-top: 1px solid var(--mantine-color-default-border); +} + +.ProseMirror ol.footnotes li p { + margin: 0.15rem 0; +} diff --git a/apps/client/src/features/editor/styles/index.css b/apps/client/src/features/editor/styles/index.css index 7b1ce93e8..cb49785ab 100644 --- a/apps/client/src/features/editor/styles/index.css +++ b/apps/client/src/features/editor/styles/index.css @@ -18,3 +18,4 @@ @import "./columns.css"; @import "./status.css"; @import "./base-embed.css"; +@import "./footnotes.css"; diff --git a/apps/server/src/collaboration/collaboration.util.ts b/apps/server/src/collaboration/collaboration.util.ts index e8e8d4273..7ee5ba4aa 100644 --- a/apps/server/src/collaboration/collaboration.util.ts +++ b/apps/server/src/collaboration/collaboration.util.ts @@ -1,4 +1,5 @@ import { StarterKit } from '@tiptap/starter-kit'; +import { Document } from '@tiptap/extension-document'; import { TextAlign } from '@tiptap/extension-text-align'; import { Superscript } from '@tiptap/extension-superscript'; import SubScript from '@tiptap/extension-subscript'; @@ -45,6 +46,9 @@ import { TransclusionSource, TransclusionReference, BaseEmbed, + Footnotes, + Footnote, + FootnoteReference, } from '@docmost/editor-ext'; import { generateText, getSchema, JSONContent } from '@tiptap/core'; import { generateHTML, generateJSON } from '../common/helpers/prosemirror/html'; @@ -58,11 +62,15 @@ import { Logger } from '@nestjs/common'; export const tiptapExtensions = [ StarterKit.configure({ + document: false, codeBlock: false, link: false, trailingNode: false, heading: false, }), + Document.extend({ + content: 'block+ footnotes?', + }), Heading, UniqueID.configure({ types: ['heading', 'paragraph', 'transclusionSource'], @@ -110,7 +118,10 @@ export const tiptapExtensions = [ Status, TransclusionSource, TransclusionReference, - BaseEmbed + BaseEmbed, + Footnotes, + Footnote, + FootnoteReference, ] as any; export function jsonToHtml(tiptapJson: any) { diff --git a/apps/server/src/ee b/apps/server/src/ee index 05529bcf9..c7b77ffb9 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 05529bcf97919d84f17442a9faf1a93904a5a85a +Subproject commit c7b77ffb9ed6a7bf462a4683de4f84355122e00b diff --git a/packages/editor-ext/src/index.ts b/packages/editor-ext/src/index.ts index d8ed68f2f..80a67f449 100644 --- a/packages/editor-ext/src/index.ts +++ b/packages/editor-ext/src/index.ts @@ -32,6 +32,7 @@ export * from "./lib/columns"; export * from "./lib/status"; export * from "./lib/pdf"; export * from "./lib/page-break"; +export * from "./lib/footnotes"; export * from "./lib/resizable-nodeview"; export { pageNodeToDocxBuffer, diff --git a/packages/editor-ext/src/lib/footnotes/footnote.ts b/packages/editor-ext/src/lib/footnotes/footnote.ts new file mode 100644 index 000000000..f83ab757a --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/footnote.ts @@ -0,0 +1,189 @@ +//Source MIT - https://github.com/buttondown/tiptap-footnotes +import { mergeAttributes } from "@tiptap/core"; +import ListItem, { ListItemOptions } from "@tiptap/extension-list-item"; + +declare module "@tiptap/core" { + interface Commands { + footnote: { + /** + * scrolls to & sets the text selection at the end of the footnote with the given id + * @param id the id of the footote (i.e. the `data-id` attribute value of the footnote) + * @example editor.commands.focusFootnote("a43956c1-1ab8-462f-96e4-be3a4b27fd50") + */ + focusFootnote: (id: string) => ReturnType; + }; + } +} + +export interface FootnoteOptions extends ListItemOptions { + /** + * Content expression for this node + * @default "paragraph+" + */ + content: string; +} + +const Footnote = ListItem.extend({ + name: "footnote", + content() { + return this.options.content; + }, + isolating: true, + defining: true, + draggable: false, + + addOptions() { + return { + HTMLAttributes: {}, + bulletListTypeName: 'bulletList', + orderedListTypeName: 'orderedList', + ...this.parent?.(), + content: "paragraph+", + }; + }, + + addAttributes() { + return { + id: { + isRequired: true, + }, + // the data-id field should match the data-id field of a footnote reference. + // it's used to link footnotes and references together. + "data-id": { + isRequired: true, + }, + }; + }, + parseHTML() { + return [ + { + tag: "li", + getAttrs(node) { + const id = node.getAttribute("data-id"); + if (id) { + return { + "data-id": node.getAttribute("data-id"), + }; + } + return false; + }, + priority: 1000, + }, + ]; + }, + renderHTML({ HTMLAttributes }) { + return [ + "li", + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), + 0, + ]; + }, + + addCommands() { + return { + focusFootnote: + (id: string) => + ({ editor, chain }) => { + const matchedFootnote = editor.$node("footnote", { + "data-id": id, + }); + if (matchedFootnote) { + // sets the text selection to the end of the footnote definition and scroll to it. + chain() + .focus() + .setTextSelection( + matchedFootnote.from + matchedFootnote.content.size + ) + .run(); + + matchedFootnote.element.scrollIntoView(); + return true; + } + return false; + }, + }; + }, + addKeyboardShortcuts() { + return { + // when inside a footnote, Mod-a should select only the footnote content + "Mod-a": ({ editor }) => { + try { + const { selection } = editor.state; + const { $from } = selection; + + for (let depth = $from.depth; depth >= 0; depth--) { + const node = $from.node(depth); + if (node.type.name === "footnote") { + const start = $from.start(depth); + const end = $from.end(depth); + + editor.commands.setTextSelection({ + from: start + 1, + to: end - 1, + }); + return true; + } + } + + return false; + } catch (e) { + return false; + } + }, + // when the user presses tab, adjust the text selection to be at the end of the next footnote + Tab: ({ editor }) => { + try { + const { selection } = editor.state; + const pos = editor.$pos(selection.anchor); + if (!pos.after) return false; + // if the next node is "footnotes", place the text selection at the end of the first footnote + if (pos.after.node.type.name == "footnotes") { + const firstChild = pos.after.node.child(0); + editor + .chain() + .setTextSelection(pos.after.from + firstChild.content.size) + .scrollIntoView() + .run(); + return true; + } else { + const startPos = selection.$from.start(2); + if (Number.isNaN(startPos)) return false; + const parent = editor.$pos(startPos); + if (parent.node.type.name != "footnote" || !parent.after) { + return false; + } + // if the next node is a footnote, place the text selection at the end of it + editor + .chain() + .setTextSelection(parent.after.to - 1) + .scrollIntoView() + .run(); + return true; + } + } catch { + return false; + } + }, + // inverse of the tab command - place the text selection at the end of the previous footnote + "Shift-Tab": ({ editor }) => { + const { selection } = editor.state; + const startPos = selection.$from.start(2); + if (Number.isNaN(startPos)) return false; + const parent = editor.$pos(startPos); + if (parent.node.type.name != "footnote" || !parent.before) { + return false; + } + + editor + .chain() + .setTextSelection(parent.before.to - 1) + .scrollIntoView() + .run(); + return true; + }, + }; + }, + +}); + +export default Footnote; diff --git a/packages/editor-ext/src/lib/footnotes/footnotes.ts b/packages/editor-ext/src/lib/footnotes/footnotes.ts new file mode 100644 index 000000000..c07528b16 --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/footnotes.ts @@ -0,0 +1,46 @@ +//Source MIT - https://github.com/buttondown/tiptap-footnotes +import OrderedList from "@tiptap/extension-ordered-list"; +import FootnoteRules from "./rules"; + +const Footnotes = OrderedList.extend({ + name: "footnotes", + group: "", // removed the default group of the ordered list extension + isolating: true, + defining: true, + draggable: false, + + content() { + return "footnote*"; + }, + addAttributes() { + return { + class: { + default: "footnotes", + }, + }; + }, + parseHTML() { + return [ + { + tag: "ol.footnotes", + priority: 1000, + }, + ]; + }, + + addKeyboardShortcuts() { + return {}; + }, + addCommands() { + return {}; + }, + addInputRules() { + return []; + }, + + addExtensions() { + return [FootnoteRules]; + }, +}); + +export default Footnotes; diff --git a/packages/editor-ext/src/lib/footnotes/index.ts b/packages/editor-ext/src/lib/footnotes/index.ts new file mode 100644 index 000000000..b22501b3b --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/index.ts @@ -0,0 +1,4 @@ +export { default as Footnotes } from "./footnotes"; +export { default as Footnote } from "./footnote"; +export type { FootnoteOptions } from "./footnote"; +export { default as FootnoteReference } from "./reference"; diff --git a/packages/editor-ext/src/lib/footnotes/reference.ts b/packages/editor-ext/src/lib/footnotes/reference.ts new file mode 100644 index 000000000..6bada1281 --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/reference.ts @@ -0,0 +1,221 @@ +//Source MIT - https://github.com/buttondown/tiptap-footnotes +import { mergeAttributes, Node } from "@tiptap/core"; +import { + Fragment as PMFragment, + Node as PMNode, + Slice, +} from "@tiptap/pm/model"; +import { NodeSelection, Plugin, PluginKey } from "@tiptap/pm/state"; +import { generateNodeId } from "../utils"; + + +const REFNUM_ATTR = "data-reference-number"; +const REF_CLASS = "footnote-ref"; + +declare module "@tiptap/core" { + interface Commands { + footnoteReference: { + /** + * add a new footnote reference + * @example editor.commands.addFootnote() + */ + addFootnote: () => ReturnType; + }; + } +} + +const FootnoteReference = Node.create({ + name: "footnoteReference", + inline: true, + content: "text*", + group: "inline", + atom: true, + draggable: true, + + parseHTML() { + return [ + { + tag: `sup`, + priority: 1000, + getAttrs(node) { + const anchor = node.querySelector( + `a.${REF_CLASS}:first-child` + ); + + if (!anchor) { + return false; + } + + const id = anchor.getAttribute("data-id"); + const ref = anchor.getAttribute(REFNUM_ATTR); + + return { + "data-id": id ?? generateNodeId(), + referenceNumber: ref ?? anchor.innerText, + }; + }, + contentElement(node) { + return node.firstChild as HTMLElement; + }, + }, + ]; + }, + + addAttributes() { + return { + class: { + default: REF_CLASS, + }, + "data-id": { + renderHTML(attributes) { + return { + "data-id": attributes["data-id"] || generateNodeId(), + }; + }, + }, + referenceNumber: {}, + + href: { + renderHTML(attributes) { + return { + href: `#fn:${attributes["referenceNumber"]}`, + }; + }, + }, + }; + }, + + renderHTML({ HTMLAttributes }) { + const { referenceNumber, ...attributes } = HTMLAttributes; + const attrs = mergeAttributes(this.options.HTMLAttributes, attributes); + attrs[REFNUM_ATTR] = referenceNumber; + + return [ + "sup", + { id: `fnref:${referenceNumber}` }, + ["a", attrs, HTMLAttributes.referenceNumber], + ]; + }, + + addProseMirrorPlugins() { + const { editor } = this; + + // Ensures pasted footnote references get unique IDs. + const mapNode = (node: PMNode): PMNode => { + if (node.type.name === this.name) { + const newAttrs = { ...node.attrs, "data-id": generateNodeId() }; + return node.type.create(newAttrs, node.content, node.marks); + } + + if (node.content && node.content.size > 0) { + const newChildren: PMNode[] = []; + let changed = false; + + node.content.forEach((child) => { + const mapped = mapNode(child); + if (mapped !== child) { + changed = true; + } + + newChildren.push(mapped); + }); + + if (changed) { + return node.copy(PMFragment.from(newChildren)); + } + } + + return node; + }; + + return [ + new Plugin({ + key: new PluginKey("footnotePasteHandler"), + props: { + transformPasted(slice) { + const mappedNodes: PMNode[] = []; + let changed = false; + + slice.content.forEach((node) => { + const mapped = mapNode(node); + if (mapped !== node) { + changed = true; + } + mappedNodes.push(mapped); + }); + + if (!changed) { + return slice; + } + + return new Slice( + PMFragment.from(mappedNodes), + slice.openStart, + slice.openEnd + ); + }, + }, + }), + new Plugin({ + key: new PluginKey("footnoteRefClick"), + + props: { + // on double-click, focus on the footnote + handleDoubleClickOn(view, pos, node, nodePos, event) { + if (node.type.name != "footnoteReference") return false; + event.preventDefault(); + const id = node.attrs["data-id"]; + return editor.commands.focusFootnote(id); + }, + // click the footnote reference once to get focus, click twice to scroll to the footnote + handleClickOn(view, pos, node, nodePos, event) { + if (node.type.name != "footnoteReference") return false; + event.preventDefault(); + const { selection } = editor.state.tr; + if (selection instanceof NodeSelection && selection.node.eq(node)) { + const id = node.attrs["data-id"]; + return editor.commands.focusFootnote(id); + } else { + editor.chain().setNodeSelection(nodePos).run(); + return true; + } + }, + }, + }), + ]; + }, + + addCommands() { + return { + addFootnote: + () => + ({ state, tr }) => { + const node = this.type.create({ + "data-id": generateNodeId(), + }); + tr.insert(state.selection.anchor, node); + return true; + }, + }; + }, + + addInputRules() { + // when a user types [^text], add a new footnote + return [ + { + find: /\[\^(.*?)\]/, + type: this.type, + undoable: true, + handler({ range, match, chain }) { + const start = range.from; + let end = range.to; + if (match[1]) { + chain().deleteRange({ from: start, to: end }).addFootnote().run(); + } + }, + }, + ]; + }, +}); + +export default FootnoteReference; diff --git a/packages/editor-ext/src/lib/footnotes/rules.ts b/packages/editor-ext/src/lib/footnotes/rules.ts new file mode 100644 index 000000000..7064916c0 --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/rules.ts @@ -0,0 +1,90 @@ +//Source MIT - https://github.com/buttondown/tiptap-footnotes +import { Plugin, PluginKey } from "@tiptap/pm/state"; +import { ReplaceStep } from "@tiptap/pm/transform"; +import { Extension } from "@tiptap/core"; +import { updateFootnotesList } from "./utils"; + +const FootnoteRules = Extension.create({ + name: "footnoteRules", + priority: 1000, + addProseMirrorPlugins() { + return [ + new Plugin({ + key: new PluginKey("footnoteRules"), + filterTransaction(tr) { + const { from, to } = tr.selection; + + // Allow full document selections (Mod-a/Ctrl-a) + if (from === 0 && to === tr.doc.content.size) return true; + + let selectedFootnotes = false; + let selectedContent = false; + let footnoteCount = 0; + tr.doc.nodesBetween(from, to, (node, _, parent) => { + if (parent?.type.name == "doc" && node.type.name != "footnotes") { + selectedContent = true; + } else if (node.type.name == "footnote") { + footnoteCount += 1; + } else if (node.type.name == "footnotes") { + selectedFootnotes = true; + } + }); + const overSelected = selectedContent && selectedFootnotes; + /* + * Here, we don't allow any transaction that spans between the "content" nodes and the "footnotes" node. This also rejects any transaction that spans between more than 1 footnote. + */ + return !overSelected && footnoteCount <= 1; + }, + + // if there are some to the footnote references (added/deleted/dragged), append a transaction that updates the footnotes list accordingly + appendTransaction(transactions, oldState, newState) { + let newTr = newState.tr; + let refsChanged = false; // true if the footnote references have been changed, false otherwise + for (let tr of transactions) { + if (!tr.docChanged) continue; + if (refsChanged) break; + + for (let step of tr.steps) { + if (!(step instanceof ReplaceStep)) continue; + if (refsChanged) break; + + const isDelete = step.from != step.to; // the user deleted items from the document (from != to & the step is a replace step) + const isInsert = step.slice.size > 0; + + // check if any footnote references have been inserted + if (isInsert) { + step.slice.content.descendants((node) => { + if (node?.type.name == "footnoteReference") { + refsChanged = true; + return false; + } + }); + } + if (isDelete && !refsChanged) { + // check if any footnote references have been deleted + tr.before.nodesBetween( + step.from, + Math.min(tr.before.content.size, step.to), // make sure to not go over the old document's limit + (node) => { + if (node.type.name == "footnoteReference") { + refsChanged = true; + return false; + } + }, + ); + } + } + } + + if (refsChanged) { + updateFootnotesList(newTr, newState); + return newTr; + } + + return null; + }, + }), + ]; + }, +}); +export default FootnoteRules; diff --git a/packages/editor-ext/src/lib/footnotes/utils.ts b/packages/editor-ext/src/lib/footnotes/utils.ts new file mode 100644 index 000000000..cb9190178 --- /dev/null +++ b/packages/editor-ext/src/lib/footnotes/utils.ts @@ -0,0 +1,123 @@ +//Source MIT - https://github.com/buttondown/tiptap-footnotes +import { EditorState, Transaction } from "@tiptap/pm/state"; +import { Fragment, Node } from "@tiptap/pm/model"; + +// update the reference number of all the footnote references in the document +export function updateFootnoteReferences(tr: Transaction) { + let count = 1; + + const nodes: any[] = []; + + tr.doc.descendants((node, pos) => { + if (node.type.name == "footnoteReference") { + tr.setNodeAttribute(pos, "referenceNumber", `${count}`); + + nodes.push(node); + count += 1; + } + }); + // return the updated footnote references (in the order that they appear in the document) + return nodes; +} + +function getFootnotes(tr: Transaction) { + let footnotesRange: { from: number; to: number } | undefined; + const footnotes: Node[] = []; + tr.doc.descendants((node, pos) => { + if (node.type.name == "footnote") { + footnotes.push(node); + } else if (node.type.name == "footnotes") { + footnotesRange = { from: pos, to: pos + node.nodeSize }; + } else { + return false; + } + }); + return { footnotesRange, footnotes }; +} + +// update the "footnotes" ordered list based on the footnote references in the document +export function updateFootnotesList(tr: Transaction, state: EditorState) { + const footnoteReferences = updateFootnoteReferences(tr); + + const footnoteType = state.schema.nodes.footnote; + const footnotesType = state.schema.nodes.footnotes; + + const emptyParagraph = state.schema.nodeFromJSON({ + type: "paragraph", + content: [], + }); + + const { footnotesRange, footnotes } = getFootnotes(tr); + + // a mapping of footnote id -> footnote node + const footnoteIds: { [key: string]: Node } = footnotes.reduce( + (obj, footnote) => { + obj[footnote.attrs["data-id"]] = footnote; + return obj; + }, + {} as any, + ); + + const newFootnotes: Node[] = []; + + let footnoteRefIds = new Set( + footnoteReferences.map((ref) => ref.attrs["data-id"]), + ); + const deleteFootnoteIds: Set = new Set(); + for (let footnote of footnotes) { + const id = footnote.attrs["data-id"]; + if (!footnoteRefIds.has(id) || deleteFootnoteIds.has(id)) { + deleteFootnoteIds.add(id); + // we traverse through this footnote's content because it may contain footnote references. + // we want to delete the footnotes associated with these references, so we add them to the delete set. + footnote.content.descendants((node) => { + if (node.type.name == "footnoteReference") + deleteFootnoteIds.add(node.attrs["data-id"]); + }); + } + } + + for (let i = 0; i < footnoteReferences.length; i++) { + let refId = footnoteReferences[i].attrs["data-id"]; + + if (deleteFootnoteIds.has(refId)) continue; + // if there is a footnote w/ the same id as this `ref`, we preserve its content and update its id attribute + if (refId in footnoteIds) { + let footnote = footnoteIds[refId]; + newFootnotes.push( + footnoteType.create( + { ...footnote.attrs, id: `fn:${i + 1}` }, + footnote.content, + ), + ); + } else { + let newNode = footnoteType.create( + { + "data-id": refId, + id: `fn:${i + 1}`, + }, + [emptyParagraph], + ); + newFootnotes.push(newNode); + } + } + + if (newFootnotes.length == 0) { + // no footnotes in the doc, delete the "footnotes" node + if (footnotesRange) { + tr.delete(footnotesRange.from, footnotesRange.to); + } + } else if (!footnotesRange) { + // there is no footnotes node present in the doc, add it + tr.insert( + tr.doc.content.size, + footnotesType.create(undefined, Fragment.from(newFootnotes)), + ); + } else { + tr.replaceWith( + footnotesRange!.from + 1, // add 1 to point at the position after the opening ol tag + footnotesRange!.to - 1, // substract 1 to point to the position before the closing ol tag + Fragment.from(newFootnotes), + ); + } +} diff --git a/packages/editor-ext/src/lib/markdown/utils/footnotes.marked.ts b/packages/editor-ext/src/lib/markdown/utils/footnotes.marked.ts new file mode 100644 index 000000000..11c732d57 --- /dev/null +++ b/packages/editor-ext/src/lib/markdown/utils/footnotes.marked.ts @@ -0,0 +1,110 @@ +import { Token, marked } from 'marked'; +import { generateNodeId } from '../../utils'; + +interface FootnoteRefToken { + type: 'footnoteRef'; + label: string; + raw: string; +} + +interface FootnoteDefToken { + type: 'footnoteDef'; + label: string; + text: string; + raw: string; +} + +// Parse-scoped state: markdownToHtml resets before the top-level parse and +// appends the collected list after it. Nested marked.parse calls (callout, +// footnote definitions) share this state, so hooks cannot be used here. +let footnoteRefs: { label: string; id: string; number: number }[] = []; +let footnoteDefs = new Map(); + +export function resetFootnotes() { + footnoteRefs = []; + footnoteDefs = new Map(); +} + +export function renderFootnotesList(): string { + if (!footnoteRefs.length) return ''; + const items = footnoteRefs.map(({ label, id, number }) => { + const body = footnoteDefs.get(label) || '

'; + return `
  • ${body}
  • `; + }); + return `
      \n${items.join('\n')}\n
    \n`; +} + +export const footnoteRefExtension = { + name: 'footnoteRef', + level: 'inline', + start(src: string) { + return src.indexOf('[^'); + }, + tokenizer(src: string): FootnoteRefToken | undefined { + const match = /^\[\^([^\]\s]+)\]/.exec(src); + if (match) { + return { + type: 'footnoteRef', + raw: match[0], + label: match[1].toLowerCase(), + }; + } + }, + renderer(token: Token) { + const refToken = token as FootnoteRefToken; + const number = footnoteRefs.length + 1; + const id = generateNodeId(); + footnoteRefs.push({ label: refToken.label, id, number }); + return `${number}`; + }, +}; + +export const footnoteDefExtension = { + name: 'footnoteDef', + level: 'block', + start(src: string) { + return src.match(/^\[\^[^\]\s]+\]:/m)?.index ?? -1; + }, + tokenizer(src: string): FootnoteDefToken | undefined { + const firstLine = /^\[\^([^\]\s]+)\]:[ \t]*/.exec(src); + if (!firstLine) return undefined; + + const lines = src.split('\n'); + const contentLines = [lines[0].slice(firstLine[0].length)]; + let consumed = 1; + while (consumed < lines.length) { + const line = lines[consumed]; + if (/^[ \t]{2,}\S/.test(line)) { + contentLines.push(line.replace(/^[ \t]{1,4}/, '')); + consumed += 1; + } else if ( + /^[ \t]*$/.test(line) && + consumed + 1 < lines.length && + /^[ \t]{2,}\S/.test(lines[consumed + 1]) + ) { + contentLines.push(''); + consumed += 1; + } else { + break; + } + } + + const raw = + lines.slice(0, consumed).join('\n') + + (consumed < lines.length ? '\n' : ''); + return { + type: 'footnoteDef', + raw, + label: firstLine[1].toLowerCase(), + text: contentLines.join('\n').trim(), + }; + }, + renderer(token: Token) { + const defToken = token as FootnoteDefToken; + const body = defToken.text + ? marked.parse(defToken.text).toString() + : '

    '; + footnoteDefs.set(defToken.label, body); + return ''; + }, +}; diff --git a/packages/editor-ext/src/lib/markdown/utils/marked.utils.ts b/packages/editor-ext/src/lib/markdown/utils/marked.utils.ts index 7556aa4f0..0377ab7f7 100644 --- a/packages/editor-ext/src/lib/markdown/utils/marked.utils.ts +++ b/packages/editor-ext/src/lib/markdown/utils/marked.utils.ts @@ -2,6 +2,12 @@ import { marked } from "marked"; import { calloutExtension } from "./callout.marked"; import { mathBlockExtension } from "./math-block.marked"; import { mathInlineExtension } from "./math-inline.marked"; +import { + footnoteDefExtension, + footnoteRefExtension, + renderFootnotesList, + resetFootnotes, +} from "./footnotes.marked"; marked.use({ renderer: { @@ -34,7 +40,13 @@ marked.use({ }); marked.use({ - extensions: [calloutExtension, mathBlockExtension, mathInlineExtension], + extensions: [ + calloutExtension, + mathBlockExtension, + mathInlineExtension, + footnoteDefExtension, + footnoteRefExtension, + ], }); marked.setOptions({ breaks: true }); @@ -48,5 +60,7 @@ export function markdownToHtml( .replace(YAML_FONT_MATTER_REGEX, "") .trimStart(); - return marked.parse(markdown).toString(); + resetFootnotes(); + const html = marked.parse(markdown).toString(); + return html + renderFootnotesList(); } diff --git a/packages/editor-ext/src/lib/markdown/utils/turndown.utils.ts b/packages/editor-ext/src/lib/markdown/utils/turndown.utils.ts index ebfc3423e..55f4afd37 100644 --- a/packages/editor-ext/src/lib/markdown/utils/turndown.utils.ts +++ b/packages/editor-ext/src/lib/markdown/utils/turndown.utils.ts @@ -34,6 +34,8 @@ export function htmlToMarkdown(html: string): string { iframeEmbed, image, video, + footnoteRef, + footnotesList, ]); return turndownService.turndown(html).replaceAll('
    ', ' '); } @@ -203,6 +205,56 @@ function image(turndownService: _TurndownService) { }); } +function getFootnoteAnchor(node: HTMLElement): HTMLElement | null { + const child = node.firstElementChild as HTMLElement | null; + return child?.nodeName === 'A' && child.classList.contains('footnote-ref') + ? child + : null; +} + +function footnoteRef(turndownService: _TurndownService) { + turndownService.addRule('footnoteRef', { + filter: function (node: HTMLInputElement) { + return node.nodeName === 'SUP' && !!getFootnoteAnchor(node); + }, + replacement: function (_content: string, node: HTMLInputElement) { + const anchor = getFootnoteAnchor(node); + const number = + anchor.getAttribute('data-reference-number') || anchor.textContent; + return `[^${number}]`; + }, + }); +} + +function footnotesList(turndownService: _TurndownService) { + turndownService.addRule('footnotesList', { + filter: function (node: HTMLInputElement) { + return node.nodeName === 'OL' && node.classList.contains('footnotes'); + }, + replacement: function (_content: string, node: HTMLInputElement) { + const items = Array.from(node.children).filter( + (child) => child.nodeName === 'LI', + ); + const definitions = items.map((li, index) => { + const number = + (li.getAttribute('id') || '').replace('fn:', '') || + String(index + 1); + const markdown = turndownService + .turndown((li as HTMLElement).innerHTML) + .trim(); + // continuation lines need a 4-space indent to stay in the footnote + const [first, ...rest] = markdown.split('\n'); + const body = [ + first, + ...rest.map((line: string) => (line.trim() ? ` ${line}` : line)), + ].join('\n'); + return `[^${number}]: ${body}`; + }); + return `\n\n${definitions.join('\n')}\n\n`; + }, + }); +} + function video(turndownService: _TurndownService) { turndownService.addRule('video', { filter: function (node: HTMLInputElement) { diff --git a/packages/editor-ext/src/lib/prosemirror-docx/schema.ts b/packages/editor-ext/src/lib/prosemirror-docx/schema.ts index 1a2797213..df89cf1d7 100644 --- a/packages/editor-ext/src/lib/prosemirror-docx/schema.ts +++ b/packages/editor-ext/src/lib/prosemirror-docx/schema.ts @@ -1,4 +1,4 @@ -import { HeadingLevel, ShadingType } from 'docx'; +import { FootnoteReferenceRun, HeadingLevel, Paragraph, ShadingType } from 'docx'; import { Node } from 'prosemirror-model'; import { DocxSerializerAsync, @@ -168,6 +168,27 @@ export const defaultAsyncNodes: NodeSerializerAsync = { pageBreak(state, node) { state.closeBlock(node, { pageBreakBefore: true }); }, + footnoteReference(state, node) { + const number = + Number(node.attrs?.referenceNumber) || state.$footnoteCounter + 1; + state.$footnoteCounter = Math.max(state.$footnoteCounter, number); + // seed an empty body so the reference stays valid even if the trailing + // footnotes list is missing; the footnotes node overwrites it with content + if (!state.footnotes[number]) { + state.footnotes[number] = { children: [new Paragraph('')] }; + } + state.current.push(new FootnoteReferenceRun(number)); + }, + async footnotes(state, node) { + for (let i = 0; i < node.childCount; i += 1) { + const item = node.child(i); + const number = + Number(String(item.attrs?.id ?? '').replace('fn:', '')) || i + 1; + await state.footnoteDefinition(item, number); + } + }, + // items are consumed by the footnotes handler above + footnote() {}, // No usable static export representation: skip without failing. subpages() {}, transclusionReference() {}, diff --git a/packages/editor-ext/src/lib/prosemirror-docx/serializer.ts b/packages/editor-ext/src/lib/prosemirror-docx/serializer.ts index fa62a8cf6..b349ece3e 100644 --- a/packages/editor-ext/src/lib/prosemirror-docx/serializer.ts +++ b/packages/editor-ext/src/lib/prosemirror-docx/serializer.ts @@ -824,6 +824,29 @@ export class DocxSerializerStateAsync { this.current.push(new FootnoteReferenceRun(this.$footnoteCounter)); } + // Fills the footnote body for an already-referenced footnote number from a + // node holding block content (Docmost keeps footnote text in a trailing + // list, separate from the inline reference). + async footnoteDefinition(node: Node, number: number) { + const { current, children, nextRunOpts, nextParentParagraphOpts } = this; + this.current = []; + this.children = []; + delete this.nextRunOpts; + delete this.nextParentParagraphOpts; + + await this.renderContent(node); + this.footnotes[number] = { + children: this.children.filter( + (child): child is Paragraph => child instanceof Paragraph, + ), + }; + + this.current = current; + this.children = children; + this.nextRunOpts = nextRunOpts; + this.nextParentParagraphOpts = nextParentParagraphOpts; + } + closeBlock(node: Node, props?: IParagraphOptions) { const paragraph = new Paragraph({ children: this.current, diff --git a/packages/editor-ext/src/lib/trailing-node.ts b/packages/editor-ext/src/lib/trailing-node.ts index a4d77b3df..6b3d0f584 100644 --- a/packages/editor-ext/src/lib/trailing-node.ts +++ b/packages/editor-ext/src/lib/trailing-node.ts @@ -7,9 +7,19 @@ export interface TrailingNodeExtensionOptions { } function nodeEqualsType({ types, node }: { types: any, node: any }) { + if (!node) return false return (Array.isArray(types) && types.includes(node.type)) || node.type === types } +// footnotes must stay the last doc child, so the trailing node goes before it +function lastNodeBeforeFootnotes(doc: any) { + const lastChild = doc.lastChild + if (lastChild?.type.name === 'footnotes') { + return doc.childCount > 1 ? doc.child(doc.childCount - 2) : null + } + return lastChild +} + // @ts-ignore /** * Extension based on: @@ -40,19 +50,23 @@ export const TrailingNode = Extension.create({ appendTransaction: (_, __, state) => { const { doc, tr, schema } = state; const shouldInsertNodeAtEnd = plugin.getState(state); - const endPosition = doc.content.size; const type = schema.nodes[this.options.node] if (!shouldInsertNodeAtEnd) { return; } + const lastChild = doc.lastChild + const endPosition = lastChild?.type.name === 'footnotes' + ? doc.content.size - lastChild.nodeSize + : doc.content.size + return tr.insert(endPosition, type.create()); }, state: { init: (_, state) => { try { - const lastNode = state.tr.doc.lastChild + const lastNode = lastNodeBeforeFootnotes(state.tr.doc) return !nodeEqualsType({ node: lastNode, types: disabledNodes }) } catch (err){ console.log(err) @@ -70,7 +84,7 @@ export const TrailingNode = Extension.create({ return value } - const lastNode = tr.doc.lastChild + const lastNode = lastNodeBeforeFootnotes(tr.doc) return !nodeEqualsType({ node: lastNode, types: disabledNodes }) }, }, From 737cd67965d50012fef8d1c275521af1ced91b23 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:31:02 +0100 Subject: [PATCH 5/9] feat: compare two page versions (#2385) --- .../public/locales/en-US/translation.json | 8 +- .../page-history/atoms/history-atoms.ts | 11 +- .../components/css/history.module.css | 31 ++- .../components/history-editor.tsx | 1 - .../page-history/components/history-item.tsx | 188 +++++++++++++----- .../page-history/components/history-list.tsx | 97 ++++++++- .../components/history-modal-body.tsx | 58 +++++- .../components/history-modal-mobile.tsx | 2 +- .../page-history/components/history-view.tsx | 18 +- .../page-history/hooks/use-history-reset.ts | 29 ++- .../hooks/use-history-restore.tsx | 100 ++++++---- .../queries/page-history-query.ts | 8 + .../utils/resolve-compare-pair.test.ts | 32 +++ .../utils/resolve-compare-pair.ts | 18 ++ 14 files changed, 486 insertions(+), 115 deletions(-) create mode 100644 apps/client/src/features/page-history/utils/resolve-compare-pair.test.ts create mode 100644 apps/client/src/features/page-history/utils/resolve-compare-pair.ts diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index aaa340181..e99f4b761 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -1291,5 +1291,11 @@ "{{count}} rows deleted_one": "1 row deleted", "{{count}} rows deleted_other": "{{count}} rows deleted", "{{count}} selected_one": "1 selected", - "{{count}} selected_other": "{{count}} selected" + "{{count}} selected_other": "{{count}} selected", + "Compare": "Compare", + "Compare versions": "Compare versions", + "Select version from {{date}}": "Select version from {{date}}", + "Version actions for {{date}}": "Version actions for {{date}}", + "Comparing {{newer}} and {{older}}": "Comparing {{newer}} and {{older}}", + "Exit compare": "Exit compare" } diff --git a/apps/client/src/features/page-history/atoms/history-atoms.ts b/apps/client/src/features/page-history/atoms/history-atoms.ts index 2acf163d5..76e0d54cc 100644 --- a/apps/client/src/features/page-history/atoms/history-atoms.ts +++ b/apps/client/src/features/page-history/atoms/history-atoms.ts @@ -6,4 +6,13 @@ export const activeHistoryPrevIdAtom = atom(""); export const highlightChangesAtom = atom(true); export type DiffCounts = { added: number; deleted: number; total: number }; -export const diffCountsAtom = atom(null); +export const diffCountsAtom = atom( + null as DiffCounts | null, +); + +export type ComparePair = { newerId: string; olderId: string }; +export const compareModeAtom = atom(false); +export const compareSelectionAtom = atom([]); +export const comparePairAtom = atom( + null as ComparePair | null, +); diff --git a/apps/client/src/features/page-history/components/css/history.module.css b/apps/client/src/features/page-history/components/css/history.module.css index a4be38194..cd3186323 100644 --- a/apps/client/src/features/page-history/components/css/history.module.css +++ b/apps/client/src/features/page-history/components/css/history.module.css @@ -1,7 +1,7 @@ .history { - display: block; + display: flex; + align-items: center; width: 100%; - padding: var(--mantine-spacing-md); color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0)); @mixin hover { @@ -12,6 +12,28 @@ } } +.historyButton { + flex: 1; + min-width: 0; + color: inherit; +} + +.compareCheckbox { + padding-left: var(--mantine-spacing-xs); +} + +.itemMenu { + opacity: 0; + margin-right: var(--mantine-spacing-xs); +} + +.history:hover .itemMenu, +.history:focus-within .itemMenu, +.history.active .itemMenu, +.itemMenu[aria-expanded="true"] { + opacity: 1; +} + .historyEditor { :global(.ProseMirror) { padding: 0 !important; @@ -77,3 +99,8 @@ flex: 1; padding: rem(16px) rem(40px); } + +.compareBanner { + border-bottom: rem(1px) solid + light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); +} diff --git a/apps/client/src/features/page-history/components/history-editor.tsx b/apps/client/src/features/page-history/components/history-editor.tsx index c7fa07036..3773f6bcf 100644 --- a/apps/client/src/features/page-history/components/history-editor.tsx +++ b/apps/client/src/features/page-history/components/history-editor.tsx @@ -170,7 +170,6 @@ export function HistoryEditor({ } const total = addedCount + deletedCount; - // @ts-ignore setDiffCounts({ added: addedCount, deleted: deletedCount, total }); editor.setOptions({ diff --git a/apps/client/src/features/page-history/components/history-item.tsx b/apps/client/src/features/page-history/components/history-item.tsx index cc56b1911..2143fc305 100644 --- a/apps/client/src/features/page-history/components/history-item.tsx +++ b/apps/client/src/features/page-history/components/history-item.tsx @@ -1,10 +1,21 @@ -import { Text, Group, UnstyledButton, Avatar, Tooltip } from "@mantine/core"; +import { + Text, + Group, + UnstyledButton, + Avatar, + Tooltip, + ActionIcon, + Checkbox, + Menu, +} from "@mantine/core"; +import { IconDots } from "@tabler/icons-react"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; import { formattedDate } from "@/lib/time"; import classes from "./css/history.module.css"; import clsx from "clsx"; import { IPageHistory } from "@/features/page-history/types/page.types"; import { memo, useCallback } from "react"; +import { useTranslation } from "react-i18next"; const MAX_VISIBLE_AVATARS = 5; @@ -15,6 +26,13 @@ interface HistoryItemProps { onHover?: (id: string, index: number) => void; onHoverEnd?: () => void; isActive: boolean; + compareMode: boolean; + isChecked: boolean; + isCheckboxDisabled: boolean; + canCompare: boolean; + onToggleCompare: (id: string) => void; + onStartCompare: (id: string) => void; + onRestore?: (id: string, index: number) => void; } const HistoryItem = memo(function HistoryItem({ @@ -24,10 +42,24 @@ const HistoryItem = memo(function HistoryItem({ onHover, onHoverEnd, isActive, + compareMode, + isChecked, + isCheckboxDisabled, + canCompare, + onToggleCompare, + onStartCompare, + onRestore, }: HistoryItemProps) { + const { t } = useTranslation(); + const date = formattedDate(new Date(historyItem.createdAt)); + const handleClick = useCallback(() => { - onSelect(historyItem.id, index); - }, [onSelect, historyItem.id, index]); + if (compareMode) { + onToggleCompare(historyItem.id); + } else { + onSelect(historyItem.id, index); + } + }, [compareMode, onToggleCompare, onSelect, historyItem.id, index]); const handleMouseEnter = useCallback(() => { onHover?.(historyItem.id, index); @@ -37,63 +69,115 @@ const HistoryItem = memo(function HistoryItem({ const hasContributors = contributors && contributors.length > 0; return ( - - {formattedDate(new Date(historyItem.createdAt))} + {compareMode && ( + onToggleCompare(historyItem.id)} + aria-label={t("Select version from {{date}}", { date })} + /> + )} - - {hasContributors ? ( - <> - - - {contributors.slice(0, MAX_VISIBLE_AVATARS).map((contributor) => ( - - - - ))} - {contributors.length > MAX_VISIBLE_AVATARS && ( - ( -
    {c.name}
    + + {date} + + + {hasContributors ? ( + <> + + + {contributors + .slice(0, MAX_VISIBLE_AVATARS) + .map((contributor) => ( + + + ))} - > - - +{contributors.length - MAX_VISIBLE_AVATARS} - -
    - )} -
    -
    - {contributors.length === 1 && ( + {contributors.length > MAX_VISIBLE_AVATARS && ( + ( +
    {c.name}
    + ))} + > + + +{contributors.length - MAX_VISIBLE_AVATARS} + +
    + )} + + + {contributors.length === 1 && ( + + {contributors[0].name} + + )} + + ) : ( + <> + - {contributors[0].name} + {historyItem.lastUpdatedBy?.name} + + )} +
    +
    + + {!compareMode && ( + + + e.stopPropagation()} + > + + + + + onStartCompare(historyItem.id)} + > + {t("Compare")} + + {onRestore && ( + onRestore(historyItem.id, index)}> + {t("Restore")} + )} - - ) : ( - <> - - - {historyItem.lastUpdatedBy?.name} - - - )} - - + + + )} +
    ); }); diff --git a/apps/client/src/features/page-history/components/history-list.tsx b/apps/client/src/features/page-history/components/history-list.tsx index 4024901b3..ac761ba82 100644 --- a/apps/client/src/features/page-history/components/history-list.tsx +++ b/apps/client/src/features/page-history/components/history-list.tsx @@ -6,8 +6,12 @@ import HistoryItem from "@/features/page-history/components/history-item"; import { activeHistoryIdAtom, activeHistoryPrevIdAtom, + compareModeAtom, + comparePairAtom, + compareSelectionAtom, historyAtoms, } from "@/features/page-history/atoms/history-atoms"; +import { resolveComparePair } from "@/features/page-history/utils/resolve-compare-pair"; import { useAtom, useSetAtom } from "jotai"; import { useCallback, useEffect, useMemo, useRef } from "react"; import { @@ -32,6 +36,9 @@ function HistoryList({ pageId }: Props) { const [activeHistoryId, setActiveHistoryId] = useAtom(activeHistoryIdAtom); const setActiveHistoryPrevId = useSetAtom(activeHistoryPrevIdAtom); const setHistoryModalOpen = useSetAtom(historyAtoms); + const [compareMode, setCompareMode] = useAtom(compareModeAtom); + const [compareSelection, setCompareSelection] = useAtom(compareSelectionAtom); + const setComparePair = useSetAtom(comparePairAtom); const { data: pageHistoryData, @@ -79,10 +86,58 @@ function HistoryList({ pageId }: Props) { const handleSelect = useCallback( (id: string, index: number) => { + setComparePair(null); setActiveHistoryId(id); setActiveHistoryPrevId(historyItems[index + 1]?.id ?? ""); }, - [historyItems, setActiveHistoryId, setActiveHistoryPrevId], + [historyItems, setActiveHistoryId, setActiveHistoryPrevId, setComparePair], + ); + + const handleToggleCompare = useCallback( + (id: string) => { + setCompareSelection((prev) => { + if (prev.includes(id)) return prev.filter((item) => item !== id); + if (prev.length >= 2) return prev; + return [...prev, id]; + }); + }, + [setCompareSelection], + ); + + const handleStartCompare = useCallback( + (id: string) => { + setComparePair(null); + setCompareMode(true); + setCompareSelection([id]); + }, + [setComparePair, setCompareMode, setCompareSelection], + ); + + const handleCancelCompare = useCallback(() => { + setCompareMode(false); + setCompareSelection([]); + }, [setCompareMode, setCompareSelection]); + + const handleConfirmCompare = useCallback(() => { + const pair = resolveComparePair(historyItems, compareSelection); + if (!pair) return; + setComparePair(pair); + setCompareMode(false); + setCompareSelection([]); + }, [ + historyItems, + compareSelection, + setComparePair, + setCompareMode, + setCompareSelection, + ]); + + const handleRestoreItem = useCallback( + (id: string, index: number) => { + handleSelect(id, index); + confirmRestore(id); + }, + [handleSelect, confirmRestore], ); useEffect(() => { @@ -138,6 +193,16 @@ function HistoryList({ pageId }: Props) { onHover={handleHover} onHoverEnd={clearPrefetchTimeout} isActive={historyItem.id === activeHistoryId} + compareMode={compareMode} + isChecked={compareSelection.includes(historyItem.id)} + isCheckboxDisabled={ + !compareSelection.includes(historyItem.id) && + compareSelection.length >= 2 + } + canCompare={historyItems.length >= 2} + onToggleCompare={handleToggleCompare} + onStartCompare={handleStartCompare} + onRestore={canRestore ? handleRestoreItem : undefined} /> ))} {hasNextPage &&
    } @@ -148,22 +213,44 @@ function HistoryList({ pageId }: Props) { )} - {canRestore && ( + {compareMode ? ( <> - + ) : ( + canRestore && ( + <> + + + + + + + ) )}
    ); diff --git a/apps/client/src/features/page-history/components/history-modal-body.tsx b/apps/client/src/features/page-history/components/history-modal-body.tsx index 5673c82a1..ef2820e89 100644 --- a/apps/client/src/features/page-history/components/history-modal-body.tsx +++ b/apps/client/src/features/page-history/components/history-modal-body.tsx @@ -1,5 +1,6 @@ import { ActionIcon, + CloseButton, Group, Paper, ScrollArea, @@ -12,17 +13,20 @@ import { useAtom, useAtomValue } from "jotai"; import { activeHistoryIdAtom, activeHistoryPrevIdAtom, + comparePairAtom, diffCountsAtom, highlightChangesAtom, } from "@/features/page-history/atoms/history-atoms"; import HistoryView from "@/features/page-history/components/history-view"; -import { useRef } from "react"; +import { useMemo, useRef } from "react"; import { IconChevronUp, IconChevronDown } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; import { useDiffNavigation, useHistoryReset, } from "@/features/page-history/hooks"; +import { usePageHistoryListQuery } from "@/features/page-history/queries/page-history-query"; +import { formattedDate } from "@/lib/time"; interface Props { pageId: string; @@ -36,6 +40,28 @@ export default function HistoryModalBody({ pageId }: Props) { const activeHistoryPrevId = useAtomValue(activeHistoryPrevIdAtom); const [highlightChanges, setHighlightChanges] = useAtom(highlightChangesAtom); const diffCounts = useAtomValue(diffCountsAtom); + const [comparePair, setComparePair] = useAtom(comparePairAtom); + + const { data: pageHistoryData } = usePageHistoryListQuery(pageId); + const historyItems = useMemo( + () => pageHistoryData?.pages.flatMap((page) => page.items) ?? [], + [pageHistoryData], + ); + + const compareLabel = useMemo(() => { + if (!comparePair) return null; + const newerItem = historyItems.find( + (item) => item.id === comparePair.newerId, + ); + const olderItem = historyItems.find( + (item) => item.id === comparePair.olderId, + ); + if (!newerItem || !olderItem) return null; + return t("Comparing {{newer}} and {{older}}", { + newer: formattedDate(new Date(newerItem.createdAt)), + older: formattedDate(new Date(olderItem.createdAt)), + }); + }, [comparePair, historyItems, t]); useHistoryReset(pageId); const { currentChangeIndex, handlePrevChange, handleNextChange } = @@ -50,6 +76,25 @@ export default function HistoryModalBody({ pageId }: Props) {
    + {comparePair && ( + + + {compareLabel ?? t("Compare versions")} + + setComparePair(null)} + /> + + )} +
    - {activeHistoryId && } + {comparePair ? ( + + ) : ( + activeHistoryId && + )}
    - {activeHistoryId && activeHistoryPrevId && ( + {(comparePair || (activeHistoryId && activeHistoryPrevId)) && ( setHistoryModalOpen(false)}> {t("Cancel")} - + )} diff --git a/apps/client/src/features/page-history/components/history-view.tsx b/apps/client/src/features/page-history/components/history-view.tsx index ed8a41f9a..028fa4ac1 100644 --- a/apps/client/src/features/page-history/components/history-view.tsx +++ b/apps/client/src/features/page-history/components/history-view.tsx @@ -7,21 +7,29 @@ import { activeHistoryPrevIdAtom, } from "@/features/page-history/atoms/history-atoms"; -function HistoryView() { +interface Props { + historyId?: string; + prevHistoryId?: string; +} + +function HistoryView({ historyId, prevHistoryId }: Props) { const { t } = useTranslation(); - const historyId = useAtomValue(activeHistoryIdAtom); - const prevHistoryId = useAtomValue(activeHistoryPrevIdAtom); + const activeId = useAtomValue(activeHistoryIdAtom); + const activePrevId = useAtomValue(activeHistoryPrevIdAtom); + + const resolvedId = historyId ?? activeId; + const resolvedPrevId = prevHistoryId ?? activePrevId; const { data, isLoading: isLoadingCurrent, isError: isErrorCurrent, - } = usePageHistoryQuery(historyId); + } = usePageHistoryQuery(resolvedId); const { data: prevData, isLoading: isLoadingPrev, isError: isErrorPrev, - } = usePageHistoryQuery(prevHistoryId); + } = usePageHistoryQuery(resolvedPrevId); if (isLoadingCurrent || isLoadingPrev) { return <>; diff --git a/apps/client/src/features/page-history/hooks/use-history-reset.ts b/apps/client/src/features/page-history/hooks/use-history-reset.ts index 15ae05874..cda0cbaa1 100644 --- a/apps/client/src/features/page-history/hooks/use-history-reset.ts +++ b/apps/client/src/features/page-history/hooks/use-history-reset.ts @@ -3,22 +3,45 @@ import { useEffect } from "react"; import { activeHistoryIdAtom, activeHistoryPrevIdAtom, + compareModeAtom, + comparePairAtom, + compareSelectionAtom, diffCountsAtom, } from "@/features/page-history/atoms/history-atoms"; /** * Resets history state when pageId changes. - * Clears active selection and diff counts. + * Clears active selection, diff counts, and compare state. + * Compare state also resets on unmount so reopening the modal starts clean. */ export function useHistoryReset(pageId: string) { const [, setActiveHistoryId] = useAtom(activeHistoryIdAtom); const [, setActiveHistoryPrevId] = useAtom(activeHistoryPrevIdAtom); const [, setDiffCounts] = useAtom(diffCountsAtom); + const [, setCompareMode] = useAtom(compareModeAtom); + const [, setCompareSelection] = useAtom(compareSelectionAtom); + const [, setComparePair] = useAtom(comparePairAtom); useEffect(() => { + const resetCompare = () => { + setCompareMode(false); + setCompareSelection([]); + setComparePair(null); + }; + setActiveHistoryId(""); setActiveHistoryPrevId(""); - // @ts-ignore setDiffCounts(null); - }, [pageId, setActiveHistoryId, setActiveHistoryPrevId, setDiffCounts]); + resetCompare(); + + return resetCompare; + }, [ + pageId, + setActiveHistoryId, + setActiveHistoryPrevId, + setDiffCounts, + setCompareMode, + setCompareSelection, + setComparePair, + ]); } diff --git a/apps/client/src/features/page-history/hooks/use-history-restore.tsx b/apps/client/src/features/page-history/hooks/use-history-restore.tsx index f457c696a..17c4eb983 100644 --- a/apps/client/src/features/page-history/hooks/use-history-restore.tsx +++ b/apps/client/src/features/page-history/hooks/use-history-restore.tsx @@ -1,4 +1,4 @@ -import { useAtom, useAtomValue, useSetAtom } from "jotai"; +import { useAtomValue, useSetAtom } from "jotai"; import { useCallback } from "react"; import { useTranslation } from "react-i18next"; import { Text } from "@mantine/core"; @@ -9,7 +9,8 @@ import { activeHistoryIdAtom, historyAtoms, } from "@/features/page-history/atoms/history-atoms"; -import { usePageHistoryQuery } from "@/features/page-history/queries/page-history-query"; +import { fetchPageHistory } from "@/features/page-history/queries/page-history-query"; +import { IPageHistory } from "@/features/page-history/types/page.types"; import { pageEditorAtom, titleEditorAtom, @@ -25,8 +26,6 @@ export function useHistoryRestore() { const { t } = useTranslation(); const activeHistoryId = useAtomValue(activeHistoryIdAtom); - const { data: activeHistoryData } = usePageHistoryQuery(activeHistoryId); - const mainEditor = useAtomValue(pageEditorAtom); const mainEditorTitle = useAtomValue(titleEditorAtom); const setHistoryModalOpen = useSetAtom(historyAtoms); @@ -40,47 +39,66 @@ export function useHistoryRestore() { SpaceCaslSubject.Page, ); - const handleRestore = useCallback(() => { - if (!activeHistoryData) return; - if ( - !mainEditor || - mainEditor.isDestroyed || - !mainEditorTitle || - mainEditorTitle.isDestroyed - ) { - return; - } + const handleRestore = useCallback( + async (historyId: string) => { + let historyData: IPageHistory; + try { + historyData = await fetchPageHistory(historyId); + } catch { + notifications.show({ + message: t("Error fetching page data."), + color: "red", + }); + return; + } - mainEditorTitle - .chain() - .clearContent() - .setContent(activeHistoryData.title, { emitUpdate: true }) - .run(); + if ( + !mainEditor || + mainEditor.isDestroyed || + !mainEditorTitle || + mainEditorTitle.isDestroyed + ) { + return; + } - mainEditor - .chain() - .clearContent() - .setContent(activeHistoryData.content) - .run(); + mainEditorTitle + .chain() + .clearContent() + .setContent(historyData.title, { emitUpdate: true }) + .run(); - setHistoryModalOpen(false); - notifications.show({ message: t("Successfully restored") }); - }, [activeHistoryData, mainEditor, mainEditorTitle, setHistoryModalOpen, t]); + mainEditor + .chain() + .clearContent() + .setContent(historyData.content) + .run(); - const confirmRestore = useCallback(() => { - modals.openConfirmModal({ - title: t("Please confirm your action"), - children: ( - - {t( - "Are you sure you want to restore this version? Any changes not versioned will be lost.", - )} - - ), - labels: { confirm: t("Confirm"), cancel: t("Cancel") }, - onConfirm: handleRestore, - }); - }, [t, handleRestore]); + setHistoryModalOpen(false); + notifications.show({ message: t("Successfully restored") }); + }, + [mainEditor, mainEditorTitle, setHistoryModalOpen, t], + ); + + const confirmRestore = useCallback( + (historyId?: string) => { + const targetId = historyId ?? activeHistoryId; + if (!targetId) return; + + modals.openConfirmModal({ + title: t("Please confirm your action"), + children: ( + + {t( + "Are you sure you want to restore this version? Any changes not versioned will be lost.", + )} + + ), + labels: { confirm: t("Confirm"), cancel: t("Cancel") }, + onConfirm: () => handleRestore(targetId), + }); + }, + [t, handleRestore, activeHistoryId], + ); return { canRestore, confirmRestore }; } diff --git a/apps/client/src/features/page-history/queries/page-history-query.ts b/apps/client/src/features/page-history/queries/page-history-query.ts index 0fbfc6c9e..312d8aff7 100644 --- a/apps/client/src/features/page-history/queries/page-history-query.ts +++ b/apps/client/src/features/page-history/queries/page-history-query.ts @@ -23,6 +23,14 @@ export function prefetchPageHistory(historyId: string) { }); } +export function fetchPageHistory(historyId: string): Promise { + return queryClient.fetchQuery({ + queryKey: ["page-history", historyId], + queryFn: () => getPageHistoryById(historyId), + staleTime: HISTORY_STALE_TIME, + }); +} + export function usePageHistoryListQuery( pageId: string, ): UseInfiniteQueryResult, unknown>> { diff --git a/apps/client/src/features/page-history/utils/resolve-compare-pair.test.ts b/apps/client/src/features/page-history/utils/resolve-compare-pair.test.ts new file mode 100644 index 000000000..449188f02 --- /dev/null +++ b/apps/client/src/features/page-history/utils/resolve-compare-pair.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { resolveComparePair } from "./resolve-compare-pair"; + +// list is newest-first, matching usePageHistoryListQuery order +const items = [{ id: "v3" }, { id: "v2" }, { id: "v1" }]; + +describe("resolveComparePair", () => { + it("orders newer before older regardless of selection order", () => { + expect(resolveComparePair(items, ["v1", "v3"])).toEqual({ + newerId: "v3", + olderId: "v1", + }); + expect(resolveComparePair(items, ["v3", "v1"])).toEqual({ + newerId: "v3", + olderId: "v1", + }); + }); + + it("returns null unless exactly two versions are selected", () => { + expect(resolveComparePair(items, [])).toBeNull(); + expect(resolveComparePair(items, ["v1"])).toBeNull(); + expect(resolveComparePair(items, ["v1", "v2", "v3"])).toBeNull(); + }); + + it("returns null when a selected id is not in the list", () => { + expect(resolveComparePair(items, ["v1", "missing"])).toBeNull(); + }); + + it("returns null when the same id is selected twice", () => { + expect(resolveComparePair(items, ["v2", "v2"])).toBeNull(); + }); +}); diff --git a/apps/client/src/features/page-history/utils/resolve-compare-pair.ts b/apps/client/src/features/page-history/utils/resolve-compare-pair.ts new file mode 100644 index 000000000..d1d914346 --- /dev/null +++ b/apps/client/src/features/page-history/utils/resolve-compare-pair.ts @@ -0,0 +1,18 @@ +import { ComparePair } from "@/features/page-history/atoms/history-atoms"; + +/** + * Resolves which of the two selected versions is newer using their position + * in the history list (list is newest-first: lower index = newer). + */ +export function resolveComparePair( + historyItems: { id: string }[], + selection: string[], +): ComparePair | null { + if (selection.length !== 2) return null; + const indexA = historyItems.findIndex((item) => item.id === selection[0]); + const indexB = historyItems.findIndex((item) => item.id === selection[1]); + if (indexA === -1 || indexB === -1 || indexA === indexB) return null; + return indexA < indexB + ? { newerId: selection[0], olderId: selection[1] } + : { newerId: selection[1], olderId: selection[0] }; +} From 089286f6cf408586795d0f3ff37f19b2a7dd9461 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:33:34 +0100 Subject: [PATCH 6/9] fix: delete pnpm cache --- Dockerfile | 2 +- apps/server/src/ee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 242532634..c8f6a6f46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,7 +42,7 @@ RUN chown -R node:node /app USER node -RUN pnpm install --frozen-lockfile --prod +RUN pnpm install --frozen-lockfile --prod && rm -rf /home/node/.cache/pnpm RUN mkdir -p /app/data/storage diff --git a/apps/server/src/ee b/apps/server/src/ee index c7b77ffb9..41acc8af7 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit c7b77ffb9ed6a7bf462a4683de4f84355122e00b +Subproject commit 41acc8af7da27b6b6b3491357b22dabee9ce3695 From 9414a38215285c48b24a8accb3c277e645d0f2b9 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 14:04:33 +0100 Subject: [PATCH 7/9] feat: page attachments endpoint and modal (#2386) * feat: page attachments endpoint * feat: attachments modal --- .../public/locales/en-US/translation.json | 7 +- .../components/attachment-file-icon.tsx | 59 ++++++ .../components/page-attachments-modal.tsx | 191 ++++++++++++++++++ .../attachments/queries/attachment-query.ts | 25 +++ .../services/attachment-service.ts | 10 + .../features/attachments/services/index.ts | 1 + .../attachments/types/attachment.types.ts | 9 + .../components/header/page-header-menu.tsx | 21 ++ .../core/attachment/attachment.controller.ts | 50 ++++- .../src/core/attachment/dto/attachment.dto.ts | 15 +- .../repos/attachment/attachment.repo.ts | 40 ++++ apps/server/src/ee | 2 +- 12 files changed, 424 insertions(+), 6 deletions(-) create mode 100644 apps/client/src/features/attachments/components/attachment-file-icon.tsx create mode 100644 apps/client/src/features/attachments/components/page-attachments-modal.tsx create mode 100644 apps/client/src/features/attachments/queries/attachment-query.ts diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index e99f4b761..03e10c53e 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -1297,5 +1297,10 @@ "Select version from {{date}}": "Select version from {{date}}", "Version actions for {{date}}": "Version actions for {{date}}", "Comparing {{newer}} and {{older}}": "Comparing {{newer}} and {{older}}", - "Exit compare": "Exit compare" + "Exit compare": "Exit compare", + "Search attachments...": "Search attachments...", + "Error loading attachments.": "Error loading attachments.", + "No attachments on this page yet.": "No attachments on this page yet.", + "Uploaded by {{name}}": "Uploaded by {{name}}", + "Download {{name}}": "Download {{name}}" } diff --git a/apps/client/src/features/attachments/components/attachment-file-icon.tsx b/apps/client/src/features/attachments/components/attachment-file-icon.tsx new file mode 100644 index 000000000..b28e8de2c --- /dev/null +++ b/apps/client/src/features/attachments/components/attachment-file-icon.tsx @@ -0,0 +1,59 @@ +import { ThemeIcon } from "@mantine/core"; +import { + IconFile, + IconFileTypeCsv, + IconFileTypeDocx, + IconFileTypePdf, + IconFileTypePpt, + IconFileTypeXls, + IconFileZip, + IconMovie, + IconMusic, + IconPhoto, + type Icon, +} from "@tabler/icons-react"; + +const EXT_ICONS: Record = { + ".pdf": { icon: IconFileTypePdf, color: "red" }, + ".doc": { icon: IconFileTypeDocx, color: "blue" }, + ".docx": { icon: IconFileTypeDocx, color: "blue" }, + ".xls": { icon: IconFileTypeXls, color: "teal" }, + ".xlsx": { icon: IconFileTypeXls, color: "teal" }, + ".csv": { icon: IconFileTypeCsv, color: "teal" }, + ".ppt": { icon: IconFileTypePpt, color: "orange" }, + ".pptx": { icon: IconFileTypePpt, color: "orange" }, + ".zip": { icon: IconFileZip, color: "gray" }, + ".rar": { icon: IconFileZip, color: "gray" }, + ".7z": { icon: IconFileZip, color: "gray" }, + ".tar": { icon: IconFileZip, color: "gray" }, + ".gz": { icon: IconFileZip, color: "gray" }, +}; + +const MIME_ICONS: Array<{ prefix: string; icon: Icon; color: string }> = [ + { prefix: "image/", icon: IconPhoto, color: "grape" }, + { prefix: "video/", icon: IconMovie, color: "violet" }, + { prefix: "audio/", icon: IconMusic, color: "pink" }, +]; + +interface AttachmentFileIconProps { + fileExt?: string; + mimeType?: string; +} + +export function AttachmentFileIcon({ + fileExt, + mimeType, +}: AttachmentFileIconProps) { + const byExt = fileExt ? EXT_ICONS[fileExt.toLowerCase()] : undefined; + const byMime = mimeType + ? MIME_ICONS.find((entry) => mimeType.startsWith(entry.prefix)) + : undefined; + const { icon: FileIcon, color } = byExt ?? + byMime ?? { icon: IconFile, color: "gray" }; + + return ( + + + + ); +} diff --git a/apps/client/src/features/attachments/components/page-attachments-modal.tsx b/apps/client/src/features/attachments/components/page-attachments-modal.tsx new file mode 100644 index 000000000..53189b749 --- /dev/null +++ b/apps/client/src/features/attachments/components/page-attachments-modal.tsx @@ -0,0 +1,191 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + ActionIcon, + Anchor, + Center, + Group, + Loader, + Modal, + ScrollArea, + Text, + Tooltip, +} from "@mantine/core"; +import { IconDownload } from "@tabler/icons-react"; +import { useTranslation } from "react-i18next"; +import { SearchInput } from "@/components/common/search-input.tsx"; +import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; +import { usePageAttachmentsQuery } from "@/features/attachments/queries/attachment-query.ts"; +import { IPageAttachment } from "@/features/attachments/types/attachment.types.ts"; +import { AttachmentFileIcon } from "@/features/attachments/components/attachment-file-icon.tsx"; +import { formatBytes } from "@/lib"; +import { getFileUrl } from "@/lib/config.ts"; +import { formattedDate } from "@/lib/time.ts"; + +interface PageAttachmentsModalProps { + pageId: string; + open: boolean; + onClose: () => void; +} + +export default function PageAttachmentsModal({ + pageId, + open, + onClose, +}: PageAttachmentsModalProps) { + const { t } = useTranslation(); + + return ( + + + + ); +} + +function PageAttachmentsList({ pageId }: { pageId: string }) { + const { t } = useTranslation(); + const [search, setSearch] = useState(""); + const { + data, + isLoading, + isError, + isFetching, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + } = usePageAttachmentsQuery(pageId, search); + + const attachments = useMemo( + () => data?.pages.flatMap((page) => page.items) ?? [], + [data], + ); + + const loadMoreRef = useRef(null); + + useEffect(() => { + const sentinel = loadMoreRef.current; + if (!sentinel || !hasNextPage) return; + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && !isFetching) { + fetchNextPage(); + } + }, + { threshold: 0.1 }, + ); + + observer.observe(sentinel); + return () => observer.disconnect(); + }, [fetchNextPage, hasNextPage, isFetching]); + + const handleSearch = useCallback((value: string) => setSearch(value), []); + + return ( + <> + + + {isLoading ? ( +
    + +
    + ) : isError ? ( +
    + + {t("Error loading attachments.")} + +
    + ) : attachments.length === 0 ? ( +
    + + {search + ? t("No results found") + : t("No attachments on this page yet.")} + +
    + ) : ( + + {attachments.map((attachment) => ( + + ))} + {hasNextPage &&
    } + {isFetchingNextPage && ( +
    + +
    + )} + + )} + + ); +} + +function AttachmentRow({ attachment }: { attachment: IPageAttachment }) { + const { t } = useTranslation(); + const fileUrl = getFileUrl(attachment.url); + + return ( + + + +
    + + {attachment.fileName} + + + {formatBytes(Number(attachment.fileSize))} + {" ยท "} + {formattedDate(new Date(attachment.createdAt))} + +
    + + {attachment.creator && ( + + + + )} + + + + + + +
    + ); +} diff --git a/apps/client/src/features/attachments/queries/attachment-query.ts b/apps/client/src/features/attachments/queries/attachment-query.ts new file mode 100644 index 000000000..e9630bdd6 --- /dev/null +++ b/apps/client/src/features/attachments/queries/attachment-query.ts @@ -0,0 +1,25 @@ +import { + InfiniteData, + keepPreviousData, + useInfiniteQuery, + UseInfiniteQueryResult, +} from "@tanstack/react-query"; +import { getPageAttachments } from "@/features/attachments/services/attachment-service.ts"; +import { IPageAttachment } from "@/features/attachments/types/attachment.types.ts"; +import { IPagination } from "@/lib/types.ts"; + +export function usePageAttachmentsQuery( + pageId: string, + search?: string, +): UseInfiniteQueryResult, unknown>> { + return useInfiniteQuery({ + queryKey: ["page-attachments", pageId, search], + queryFn: ({ pageParam }) => + getPageAttachments(pageId, { cursor: pageParam, query: search }), + enabled: !!pageId, + gcTime: 0, + placeholderData: keepPreviousData, + initialPageParam: undefined, + getNextPageParam: (lastPage) => lastPage.meta?.nextCursor ?? undefined, + }); +} diff --git a/apps/client/src/features/attachments/services/attachment-service.ts b/apps/client/src/features/attachments/services/attachment-service.ts index fa43da3ca..e129c248e 100644 --- a/apps/client/src/features/attachments/services/attachment-service.ts +++ b/apps/client/src/features/attachments/services/attachment-service.ts @@ -3,7 +3,17 @@ import loadImage from "blueimp-load-image"; import { AvatarIconType, IAttachment, + IPageAttachment, } from "@/features/attachments/types/attachment.types.ts"; +import { IPagination, QueryParams } from "@/lib/types.ts"; + +export async function getPageAttachments( + pageId: string, + params?: QueryParams, +): Promise> { + const req = await api.post("/pages/attachments", { pageId, ...params }); + return req.data; +} async function compressAndResizeIcon( file: File, diff --git a/apps/client/src/features/attachments/services/index.ts b/apps/client/src/features/attachments/services/index.ts index 1732ba9fb..07e96c6ba 100644 --- a/apps/client/src/features/attachments/services/index.ts +++ b/apps/client/src/features/attachments/services/index.ts @@ -1,4 +1,5 @@ export { + getPageAttachments, uploadIcon, uploadUserAvatar, uploadSpaceIcon, diff --git a/apps/client/src/features/attachments/types/attachment.types.ts b/apps/client/src/features/attachments/types/attachment.types.ts index 018d8c7c1..ca4517517 100644 --- a/apps/client/src/features/attachments/types/attachment.types.ts +++ b/apps/client/src/features/attachments/types/attachment.types.ts @@ -15,6 +15,15 @@ export interface IAttachment { deletedAt: string | null; } +export interface IPageAttachment extends IAttachment { + url: string; + creator: { + id: string; + name: string; + avatarUrl: string | null; + } | null; +} + export enum AvatarIconType { AVATAR = "avatar", SPACE_ICON = "space-icon", diff --git a/apps/client/src/features/page/components/header/page-header-menu.tsx b/apps/client/src/features/page/components/header/page-header-menu.tsx index e011e9ec4..9b02a4596 100644 --- a/apps/client/src/features/page/components/header/page-header-menu.tsx +++ b/apps/client/src/features/page/components/header/page-header-menu.tsx @@ -11,6 +11,7 @@ import { IconList, IconMarkdown, IconMessage, + IconPaperclip, IconPrinter, IconStar, IconStarFilled, @@ -42,6 +43,7 @@ import { import { formattedDate } from "@/lib/time.ts"; import { PageEditModeToggle } from "@/features/user/components/page-state-pref.tsx"; import MovePageModal from "@/features/page/components/move-page-modal.tsx"; +import PageAttachmentsModal from "@/features/attachments/components/page-attachments-modal.tsx"; import { useTimeAgo } from "@/hooks/use-time-ago.tsx"; import { PageShareModal } from "@/ee/page-permission"; import { @@ -157,6 +159,10 @@ function PageActionMenu({ readOnly }: PageActionMenuProps) { verificationOpened, { open: openVerificationModal, close: closeVerificationModal }, ] = useDisclosure(false); + const [ + attachmentsOpened, + { open: openAttachmentsModal, close: closeAttachmentsModal }, + ] = useDisclosure(false); const [pageEditor] = useAtom(pageEditorAtom); const pageUpdatedAt = useTimeAgo(page?.updatedAt); const favoriteIds = useFavoriteIds("page", page?.spaceId); @@ -293,6 +299,15 @@ function PageActionMenu({ readOnly }: PageActionMenuProps) { )} + {!page?.isBase && ( + } + onClick={openAttachmentsModal} + > + {t("Attachments")} + + )} + {!readOnly && !page?.isBase && ( + + ); } diff --git a/apps/server/src/core/attachment/attachment.controller.ts b/apps/server/src/core/attachment/attachment.controller.ts index 736058191..57d4124c3 100644 --- a/apps/server/src/core/attachment/attachment.controller.ts +++ b/apps/server/src/core/attachment/attachment.controller.ts @@ -53,8 +53,14 @@ import { EnvironmentService } from '../../integrations/environment/environment.s import { TokenService } from '../auth/services/token.service'; import { JwtAttachmentPayload, JwtType } from '../auth/dto/jwt-payload'; import * as path from 'path'; -import { AttachmentInfoDto, RemoveIconDto } from './dto/attachment.dto'; +import { + AttachmentInfoDto, + PageIdDto, + RemoveIconDto, +} from './dto/attachment.dto'; +import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; import { PageAccessService } from '../page/page-access/page-access.service'; +import { DomainService } from '../../integrations/environment/domain.service'; import { AuditEvent, AuditResource } from '../../common/events/audit-events'; import { AUDIT_SERVICE, @@ -75,6 +81,7 @@ export class AttachmentController { private readonly environmentService: EnvironmentService, private readonly tokenService: TokenService, private readonly pageAccessService: PageAccessService, + private readonly domainService: DomainService, @Inject(AUDIT_SERVICE) private readonly auditService: IAuditService, ) {} @@ -151,7 +158,10 @@ export class AttachmentController { }, }); - return res.send(fileResponse); + return res.send({ + ...fileResponse, + url: this.buildFileUrl(workspace, fileResponse), + }); } catch (err: any) { if (err?.statusCode === 413) { const errMessage = `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`; @@ -411,7 +421,37 @@ export class AttachmentController { await this.pageAccessService.validateCanView(page, user); - return attachment; + return { ...attachment, url: this.buildFileUrl(workspace, attachment) }; + } + + @UseGuards(JwtAuthGuard) + @HttpCode(HttpStatus.OK) + @Post('pages/attachments') + async getPageAttachments( + @Body() dto: PageIdDto, + @Body() pagination: PaginationOptions, + @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, + ) { + const page = await this.pageRepo.findById(dto.pageId); + if (!page || page.workspaceId !== workspace.id) { + throw new NotFoundException('Page not found'); + } + + await this.pageAccessService.validateCanView(page, user); + + const result = await this.attachmentRepo.findPageAttachments( + page.id, + pagination, + ); + + return { + ...result, + items: result.items.map((attachment) => ({ + ...attachment, + url: this.buildFileUrl(workspace, attachment), + })), + }; } @UseGuards(JwtAuthGuard) @@ -465,6 +505,10 @@ export class AttachmentController { } } + private buildFileUrl(workspace: Workspace, attachment: Attachment): string { + return `${this.domainService.getUrl(workspace.hostname)}/api/files/${attachment.id}/${encodeURIComponent(attachment.fileName)}`; + } + private async sendFileResponse( req: FastifyRequest, res: FastifyReply, diff --git a/apps/server/src/core/attachment/dto/attachment.dto.ts b/apps/server/src/core/attachment/dto/attachment.dto.ts index 850de6f9e..80d510944 100644 --- a/apps/server/src/core/attachment/dto/attachment.dto.ts +++ b/apps/server/src/core/attachment/dto/attachment.dto.ts @@ -1,4 +1,11 @@ -import { IsEnum, IsIn, IsNotEmpty, IsOptional, IsUUID } from 'class-validator'; +import { + IsEnum, + IsIn, + IsNotEmpty, + IsOptional, + IsString, + IsUUID, +} from 'class-validator'; import { AttachmentType } from '../attachment.constants'; export class AttachmentInfoDto { @@ -7,6 +14,12 @@ export class AttachmentInfoDto { attachmentId: string; } +export class PageIdDto { + @IsString() + @IsNotEmpty() + pageId: string; +} + export class RemoveIconDto { @IsEnum(AttachmentType) @IsIn([ diff --git a/apps/server/src/database/repos/attachment/attachment.repo.ts b/apps/server/src/database/repos/attachment/attachment.repo.ts index f7d717ea0..abdc36e00 100644 --- a/apps/server/src/database/repos/attachment/attachment.repo.ts +++ b/apps/server/src/database/repos/attachment/attachment.repo.ts @@ -1,5 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectKysely } from 'nestjs-kysely'; +import { ExpressionBuilder, sql } from 'kysely'; +import { jsonObjectFrom } from 'kysely/helpers/postgres'; +import { DB } from '@docmost/db/types/db'; import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types'; import { dbOrTx } from '@docmost/db/utils'; import { @@ -8,6 +11,8 @@ import { UpdatableAttachment, } from '@docmost/db/types/entity.types'; import { AttachmentType } from '../../../core/attachment/attachment.constants'; +import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; +import { executeWithCursorPagination } from '@docmost/db/pagination/cursor-pagination'; @Injectable() export class AttachmentRepo { @@ -89,6 +94,41 @@ export class AttachmentRepo { .execute(); } + async findPageAttachments(pageId: string, pagination: PaginationOptions) { + let query = this.db + .selectFrom('attachments') + .select(this.baseFields) + .select((eb) => this.withCreator(eb)) + .where('pageId', '=', pageId) + .where('type', '=', AttachmentType.File) + .where('deletedAt', 'is', null); + + if (pagination.query) { + query = query.where( + sql`f_unaccent(file_name)`, + 'ilike', + sql`f_unaccent(${'%' + pagination.query + '%'})`, + ); + } + + return executeWithCursorPagination(query, { + perPage: pagination.limit, + cursor: pagination.cursor, + beforeCursor: pagination.beforeCursor, + fields: [{ expression: 'id', direction: 'desc' }], + parseCursor: (cursor) => ({ id: cursor.id }), + }); + } + + withCreator(eb: ExpressionBuilder) { + return jsonObjectFrom( + eb + .selectFrom('users') + .select(['users.id', 'users.name', 'users.avatarUrl']) + .whereRef('users.id', '=', 'attachments.creatorId'), + ).as('creator'); + } + async findByIds( ids: string[], opts?: { diff --git a/apps/server/src/ee b/apps/server/src/ee index 41acc8af7..c0f9440de 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 41acc8af7da27b6b6b3491357b22dabee9ce3695 +Subproject commit c0f9440de97b91475d924a677073b97ec1b58527 From db3ff54da1b0c670c521650307c5b70ad950dcc3 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:47:32 +0100 Subject: [PATCH 8/9] fix base node --- apps/server/src/ee | 2 +- packages/editor-ext/src/lib/prosemirror-docx/schema.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/server/src/ee b/apps/server/src/ee index c0f9440de..b38dc5ecd 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit c0f9440de97b91475d924a677073b97ec1b58527 +Subproject commit b38dc5ecd10118b687e6cb073cf7202e8c2fe914 diff --git a/packages/editor-ext/src/lib/prosemirror-docx/schema.ts b/packages/editor-ext/src/lib/prosemirror-docx/schema.ts index df89cf1d7..235d796bb 100644 --- a/packages/editor-ext/src/lib/prosemirror-docx/schema.ts +++ b/packages/editor-ext/src/lib/prosemirror-docx/schema.ts @@ -192,6 +192,7 @@ export const defaultAsyncNodes: NodeSerializerAsync = { // No usable static export representation: skip without failing. subpages() {}, transclusionReference() {}, + base() {}, }; export const defaultMarks: MarkSerializer = { From ea59912c7ef99569817204f07e7b57056f5d751c Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:48:03 +0100 Subject: [PATCH 9/9] feat(editor): auto-detect text direction for RTL support (#2389) --- apps/client/src/ee/ai-chat/components/chat-input.tsx | 1 + .../ee/template/components/readonly-template-editor.tsx | 1 + apps/client/src/ee/template/pages/template-editor.tsx | 1 + .../src/features/comment/components/comment-editor.tsx | 1 + .../components/transclusion/transclusion-content.tsx | 1 + apps/client/src/features/editor/page-editor.tsx | 2 ++ apps/client/src/features/editor/readonly-page-editor.tsx | 2 ++ apps/client/src/features/editor/styles/table.css | 2 +- apps/client/src/features/editor/title-editor.tsx | 1 + .../features/page-history/components/history-editor.tsx | 1 + apps/server/src/collaboration/collaboration.util.ts | 8 +++++++- 11 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/client/src/ee/ai-chat/components/chat-input.tsx b/apps/client/src/ee/ai-chat/components/chat-input.tsx index d01381874..d99479d0d 100644 --- a/apps/client/src/ee/ai-chat/components/chat-input.tsx +++ b/apps/client/src/ee/ai-chat/components/chat-input.tsx @@ -255,6 +255,7 @@ export default function ChatInput({ }, content: "", editable: true, + textDirection: "auto", immediatelyRender: true, shouldRerenderOnTransaction: false, autofocus: autofocus ? "end" : false, diff --git a/apps/client/src/ee/template/components/readonly-template-editor.tsx b/apps/client/src/ee/template/components/readonly-template-editor.tsx index ca3c4b2ce..6088cb866 100644 --- a/apps/client/src/ee/template/components/readonly-template-editor.tsx +++ b/apps/client/src/ee/template/components/readonly-template-editor.tsx @@ -41,6 +41,7 @@ export default function ReadonlyTemplateEditor({ diff --git a/apps/client/src/ee/template/pages/template-editor.tsx b/apps/client/src/ee/template/pages/template-editor.tsx index 7fadf05c8..1c8810ce2 100644 --- a/apps/client/src/ee/template/pages/template-editor.tsx +++ b/apps/client/src/ee/template/pages/template-editor.tsx @@ -87,6 +87,7 @@ export default function TemplateEditor() { const editor = useEditor({ extensions: templateExtensions, content: "", + textDirection: "auto", editorProps: { scrollThreshold: 80, scrollMargin: 80, diff --git a/apps/client/src/features/comment/components/comment-editor.tsx b/apps/client/src/features/comment/components/comment-editor.tsx index eeb0983a0..520877c85 100644 --- a/apps/client/src/features/comment/components/comment-editor.tsx +++ b/apps/client/src/features/comment/components/comment-editor.tsx @@ -103,6 +103,7 @@ const CommentEditor = forwardRef( }, content: defaultContent, editable, + textDirection: "auto", immediatelyRender: true, shouldRerenderOnTransaction: false, autofocus: (autofocus && "end") || false, diff --git a/apps/client/src/features/editor/components/transclusion/transclusion-content.tsx b/apps/client/src/features/editor/components/transclusion/transclusion-content.tsx index 946291225..828c42bbc 100644 --- a/apps/client/src/features/editor/components/transclusion/transclusion-content.tsx +++ b/apps/client/src/features/editor/components/transclusion/transclusion-content.tsx @@ -40,6 +40,7 @@ export default function TransclusionContent({ content }: Props) { diff --git a/apps/client/src/features/editor/page-editor.tsx b/apps/client/src/features/editor/page-editor.tsx index 7149e7938..77233f34f 100644 --- a/apps/client/src/features/editor/page-editor.tsx +++ b/apps/client/src/features/editor/page-editor.tsx @@ -249,6 +249,7 @@ function CollabPageEditor({ { extensions, editable, + textDirection: "auto", immediatelyRender: true, shouldRerenderOnTransaction: false, editorProps: { @@ -484,6 +485,7 @@ function StaticPageEditor({ @@ -93,6 +94,7 @@ export default function ReadonlyPageEditor({ { diff --git a/apps/client/src/features/editor/styles/table.css b/apps/client/src/features/editor/styles/table.css index 32a427936..7d9018a12 100644 --- a/apps/client/src/features/editor/styles/table.css +++ b/apps/client/src/features/editor/styles/table.css @@ -54,7 +54,7 @@ var(--mantine-color-dark-5) ); font-weight: bold; - text-align: left; + text-align: start; } .column-resize-handle { diff --git a/apps/client/src/features/editor/title-editor.tsx b/apps/client/src/features/editor/title-editor.tsx index 04317099d..26925b154 100644 --- a/apps/client/src/features/editor/title-editor.tsx +++ b/apps/client/src/features/editor/title-editor.tsx @@ -86,6 +86,7 @@ export function TitleEditor({ }, editable: editable, content: title, + textDirection: "auto", immediatelyRender: true, shouldRerenderOnTransaction: false, editorProps: { diff --git a/apps/client/src/features/page-history/components/history-editor.tsx b/apps/client/src/features/page-history/components/history-editor.tsx index 3773f6bcf..18a7dfda3 100644 --- a/apps/client/src/features/page-history/components/history-editor.tsx +++ b/apps/client/src/features/page-history/components/history-editor.tsx @@ -31,6 +31,7 @@ export function HistoryEditor({ const editor = useEditor({ extensions: mainExtensions, editable: false, + textDirection: "auto", }); useEffect(() => { diff --git a/apps/server/src/collaboration/collaboration.util.ts b/apps/server/src/collaboration/collaboration.util.ts index 7ee5ba4aa..ed182cf7f 100644 --- a/apps/server/src/collaboration/collaboration.util.ts +++ b/apps/server/src/collaboration/collaboration.util.ts @@ -50,7 +50,12 @@ import { Footnote, FootnoteReference, } from '@docmost/editor-ext'; -import { generateText, getSchema, JSONContent } from '@tiptap/core'; +import { + extensions as coreExtensions, + generateText, + getSchema, + JSONContent, +} from '@tiptap/core'; import { generateHTML, generateJSON } from '../common/helpers/prosemirror/html'; // @tiptap/html library works best for generating prosemirror json state but not HTML // see: https://github.com/ueberdosis/tiptap/issues/5352 @@ -61,6 +66,7 @@ import * as Y from 'yjs'; import { Logger } from '@nestjs/common'; export const tiptapExtensions = [ + coreExtensions.TextDirection.configure({ direction: 'auto' }), StarterKit.configure({ document: false, codeBlock: false,