From 4eb93aac544aa2e2e9e7f7b3882e8bfa1a4ddcc0 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 16:52:51 +0500 Subject: [PATCH 01/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/entities/product/ui/ProductCard.tsx | 2 +- client/src/pages/home/ui/HomePage.tsx | 4 ++-- client/src/pages/product/ui/ProductPage.tsx | 8 ++++---- client/src/shared/config/index.ts | 2 +- client/src/shared/constants/pickup-point.ts | 2 +- client/src/widgets/catalog-slider/ui/CatalogSlider.tsx | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/entities/product/ui/ProductCard.tsx b/client/src/entities/product/ui/ProductCard.tsx index 407dd01..1d914bc 100644 --- a/client/src/entities/product/ui/ProductCard.tsx +++ b/client/src/entities/product/ui/ProductCard.tsx @@ -18,7 +18,7 @@ import type { Swiper as SwiperType } from 'swiper/types' type Props = { product: Product; mediaHeight?: number; actions?: ReactNode } -const ProductCardInner = ({ product, mediaHeight = 200, actions }: Props) => { +const ProductCardInner = ({ product, mediaHeight = 300, actions }: Props) => { const navigate = useNavigate() const isMobile = useMediaQuery('(max-width:600px)') const swiperRef = useRef(null) diff --git a/client/src/pages/home/ui/HomePage.tsx b/client/src/pages/home/ui/HomePage.tsx index 974b84c..1786265 100644 --- a/client/src/pages/home/ui/HomePage.tsx +++ b/client/src/pages/home/ui/HomePage.tsx @@ -64,7 +64,7 @@ export function HomePage() { const products = productsQuery.data?.items ?? [] const total = productsQuery.data?.total ?? 0 const totalPages = Math.max(1, Math.ceil(total / filters.pageSize)) - const mediaHeight = Math.round(200 * (filters.cardScale / 100)) + const mediaHeight = Math.round(300 * (filters.cardScale / 100)) return ( @@ -73,7 +73,7 @@ export function HomePage() { width: '100%', mb: 3, aspectRatio: { xs: '4/3', sm: '21/9' }, - maxHeight: { xs: 320, sm: 400 }, + maxHeight: { xs: 400, sm: 500 }, bgcolor: 'action.hover', borderRadius: 2, overflow: 'hidden', diff --git a/client/src/pages/product/ui/ProductPage.tsx b/client/src/pages/product/ui/ProductPage.tsx index 9e71952..7025c6c 100644 --- a/client/src/pages/product/ui/ProductPage.tsx +++ b/client/src/pages/product/ui/ProductPage.tsx @@ -57,7 +57,7 @@ export function ProductPage() { if (productQuery.isLoading) { return ( - + @@ -83,7 +83,7 @@ export function ProductPage() { bgcolor: 'background.paper', }} > - + {imageUrls.map((url, idx) => ( From 5071d70746b6736c7181aed97fa4d15639535fe7 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 17:50:39 +0500 Subject: [PATCH 02/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order-detail/ui/OrderDetailContent.tsx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/client/src/features/order-detail/ui/OrderDetailContent.tsx b/client/src/features/order-detail/ui/OrderDetailContent.tsx index e935ae1..34cd886 100644 --- a/client/src/features/order-detail/ui/OrderDetailContent.tsx +++ b/client/src/features/order-detail/ui/OrderDetailContent.tsx @@ -1,9 +1,11 @@ import { useMemo, useState } from 'react' +import { Link as RouterLink } from 'react-router-dom' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' import FormControl from '@mui/material/FormControl' import InputLabel from '@mui/material/InputLabel' +import Link from '@mui/material/Link' import MenuItem from '@mui/material/MenuItem' import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' @@ -127,6 +129,32 @@ export function OrderDetailContent({ detail, orderId }: { detail: AdminOrderDeta )} + + + Товары в заказе + + + {detail.items.map((item) => ( + + + + {item.titleSnapshot} + + + {item.qty} × {formatPriceRub(item.priceCentsSnapshot)} + + + {formatPriceRub(item.priceCentsSnapshot * item.qty)} + + ))} + + + {detail.status === 'PENDING_PAYMENT' && detail.deliveryFeeLocked === false && ( Укажите итоговую стоимость доставки (₽). После сохранения клиент сможет оплатить заказ с учётом этой суммы. From b392884503b98f0b544d3f908becbb618d268cf0 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 18:29:41 +0500 Subject: [PATCH 03/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/entities/product/ui/ProductCard.tsx | 14 +- .../src/pages/home/lib/use-product-filters.ts | 8 - client/src/pages/home/ui/HomePage.tsx | 8 +- client/src/pages/home/ui/ProductFilters.tsx | 39 ---- client/src/pages/product/ui/ProductPage.tsx | 213 +++++++++--------- 5 files changed, 121 insertions(+), 161 deletions(-) diff --git a/client/src/entities/product/ui/ProductCard.tsx b/client/src/entities/product/ui/ProductCard.tsx index 1d914bc..72c32eb 100644 --- a/client/src/entities/product/ui/ProductCard.tsx +++ b/client/src/entities/product/ui/ProductCard.tsx @@ -18,7 +18,7 @@ import type { Swiper as SwiperType } from 'swiper/types' type Props = { product: Product; mediaHeight?: number; actions?: ReactNode } -const ProductCardInner = ({ product, mediaHeight = 300, actions }: Props) => { +const ProductCardInner = ({ product, mediaHeight = 390, actions }: Props) => { const navigate = useNavigate() const isMobile = useMediaQuery('(max-width:600px)') const swiperRef = useRef(null) @@ -78,7 +78,7 @@ const ProductCardInner = ({ product, mediaHeight = 300, actions }: Props) => { > {imageUrls.length ? ( - + { onSwiper={(s) => { swiperRef.current = s }} - style={{ width: '100%', height: mediaHeight, overflow: 'hidden' }} + style={{ width: '100%', height: '100%', overflow: 'hidden' }} > {imageUrls.map((url) => ( @@ -94,7 +94,7 @@ const ProductCardInner = ({ product, mediaHeight = 300, actions }: Props) => { className="product-card__media" sx={{ width: '100%', - height: mediaHeight, + height: '100%', transition: 'transform 320ms ease', '@media (prefers-reduced-motion: reduce)': { transition: 'none' }, userSelect: 'none', @@ -104,7 +104,7 @@ const ProductCardInner = ({ product, mediaHeight = 300, actions }: Props) => { { (90) useEffect(() => { const t = window.setTimeout(() => { @@ -54,10 +53,6 @@ export function useProductFilters() { setPage(1) } - const handleCardScaleChange = (v: number) => { - if (v === 70 || v === 90 || v === 110 || v === 130) setCardScale(v as 70 | 90 | 110 | 130) - } - const resetFilters = () => { setCategorySlug('') setQInput('') @@ -65,7 +60,6 @@ export function useProductFilters() { setPriceMinRub('') setPriceMaxRub('') setPageSize(12) - setCardScale(90) setMoreOpen(false) } @@ -86,7 +80,6 @@ export function useProductFilters() { pageSize, priceMinRub, priceMaxRub, - cardScale, setPage, setQInput, setMoreOpen, @@ -95,7 +88,6 @@ export function useProductFilters() { handlePageSizeChange, handlePriceMinChange, handlePriceMaxChange, - handleCardScaleChange, resetFilters, toCents, } diff --git a/client/src/pages/home/ui/HomePage.tsx b/client/src/pages/home/ui/HomePage.tsx index 1786265..340f7b4 100644 --- a/client/src/pages/home/ui/HomePage.tsx +++ b/client/src/pages/home/ui/HomePage.tsx @@ -64,7 +64,6 @@ export function HomePage() { const products = productsQuery.data?.items ?? [] const total = productsQuery.data?.total ?? 0 const totalPages = Math.max(1, Math.ceil(total / filters.pageSize)) - const mediaHeight = Math.round(300 * (filters.cardScale / 100)) return ( @@ -100,8 +99,8 @@ export function HomePage() { {productsQuery.isLoading && ( {[1, 2, 3].map((i) => ( - - + + ))} @@ -128,10 +127,9 @@ export function HomePage() { <> {products.map((p) => ( - + 0 ? : undefined} /> diff --git a/client/src/pages/home/ui/ProductFilters.tsx b/client/src/pages/home/ui/ProductFilters.tsx index 70ba964..b0014bc 100644 --- a/client/src/pages/home/ui/ProductFilters.tsx +++ b/client/src/pages/home/ui/ProductFilters.tsx @@ -3,7 +3,6 @@ import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Chip from '@mui/material/Chip' import Collapse from '@mui/material/Collapse' -import Divider from '@mui/material/Divider' import FormControl from '@mui/material/FormControl' import InputAdornment from '@mui/material/InputAdornment' import InputLabel from '@mui/material/InputLabel' @@ -12,9 +11,6 @@ import Paper from '@mui/material/Paper' import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import TextField from '@mui/material/TextField' -import ToggleButton from '@mui/material/ToggleButton' -import ToggleButtonGroup from '@mui/material/ToggleButtonGroup' -import Typography from '@mui/material/Typography' import { Search, SlidersHorizontal } from 'lucide-react' import type { Category } from '@/entities/product/model/types' import type { UseProductFiltersResult } from '../lib/use-product-filters' @@ -32,7 +28,6 @@ export function ProductFilters({ pageSize, priceMinRub, priceMaxRub, - cardScale, categories, categoriesLoading, setQInput, @@ -42,7 +37,6 @@ export function ProductFilters({ handlePageSizeChange, handlePriceMinChange, handlePriceMaxChange, - handleCardScaleChange, resetFilters, }: Props) { const categoriesForFilter = useMemo(() => { @@ -188,39 +182,6 @@ export function ProductFilters({ - - - - Масштаб карточек - handleCardScaleChange(v)} - sx={{ - alignSelf: { xs: 'flex-start', sm: 'auto' }, - '& .MuiToggleButton-root': { px: 1.5, fontWeight: 600, textTransform: 'none' }, - '& .MuiToggleButton-root.Mui-selected': { - bgcolor: 'primary.main', - color: 'primary.contrastText', - '&:hover': { bgcolor: 'primary.dark' }, - }, - }} - > - S - M - L - XL - - diff --git a/client/src/pages/product/ui/ProductPage.tsx b/client/src/pages/product/ui/ProductPage.tsx index 7025c6c..5c7e01a 100644 --- a/client/src/pages/product/ui/ProductPage.tsx +++ b/client/src/pages/product/ui/ProductPage.tsx @@ -57,7 +57,7 @@ export function ProductPage() { if (productQuery.isLoading) { return ( - + @@ -72,121 +72,128 @@ export function ProductPage() { return ( - - {imageUrls.length > 0 ? ( - - - {imageUrls.map((url, idx) => ( - - { - setViewerIndex(idx) - setViewerOpen(true) - }} - sx={{ - width: '100%', - height: 525, - cursor: 'zoom-in', - userSelect: 'none', - }} - > - + + {imageUrls.length > 0 ? ( + + + {imageUrls.map((url, idx) => ( + + { + setViewerIndex(idx) + setViewerOpen(true) + }} sx={{ width: '100%', height: '100%', - objectFit: 'cover', + cursor: 'zoom-in', + userSelect: 'none', }} - /> - - - ))} - - - ) : ( - - Нет фото - - )} - - - {p.category?.name && } - {p.quantity > 0 && } - {p.quantity === 0 && } + > + + + + ))} + + + ) : ( + + Нет фото + + )} - {(p.materials?.length ?? 0) > 0 && ( - - - Материалы - - - {(p.materials ?? []).map((m) => ( - - ))} - + + + {p.category?.name && } + {p.quantity > 0 && } + {p.quantity === 0 && } - )} - - {p.title} - - - {formatPriceRub(p.priceCents)} - + {(p.materials?.length ?? 0) > 0 && ( + + + Материалы + + + {(p.materials ?? []).map((m) => ( + + ))} + + + )} - {!isAdmin && p.quantity > 0 ? : null} + + {p.title} + + + {formatPriceRub(p.priceCents)} + - {p.description || p.shortDescription ? ( - {p.description} - ) : ( - Описание появится позже. - )} + {!isAdmin && p.quantity > 0 ? : null} - + {p.description || p.shortDescription ? ( + {p.description} + ) : ( + Описание появится позже. + )} + + - - Отзывы - - {p.reviewsSummary && p.reviewsSummary.approvedReviewCount > 0 && ( - - } - emptyIcon={} - /> - - {reviewsCountRu(p.reviewsSummary.approvedReviewCount)} - - - )} + - - + + Отзывы + + {p.reviewsSummary && p.reviewsSummary.approvedReviewCount > 0 && ( + + } + emptyIcon={} + /> + + {reviewsCountRu(p.reviewsSummary.approvedReviewCount)} + + + )} + + setViewerOpen(false)}> From 8f3bd7aa3b86bdb5b6f93facb4f2c1dcc418d432 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 18:34:45 +0500 Subject: [PATCH 04/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/shared/ui/RichTextMessageContent.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/src/shared/ui/RichTextMessageContent.tsx b/client/src/shared/ui/RichTextMessageContent.tsx index 0d636d9..34d6ad2 100644 --- a/client/src/shared/ui/RichTextMessageContent.tsx +++ b/client/src/shared/ui/RichTextMessageContent.tsx @@ -18,9 +18,14 @@ export function RichTextMessageContent({ value, tone = 'default' }: RichTextMess }) useEffect(() => { - if (!editor) return + if (!editor || editor.isDestroyed) return const normalizedValue = value.trim() ? value : '

' - if (editor.getHTML() === normalizedValue) return + try { + if (editor.getHTML() === normalizedValue) return + } catch { + // editor schema not ready yet + return + } editor.commands.setContent(normalizedValue, { emitUpdate: false }) }, [editor, value]) From f6414adf2fe6083f039b252451e6b4fe1575e8c9 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 20:17:05 +0500 Subject: [PATCH 05/31] fix: add error logging to empty catch blocks --- client/src/app/providers/SseProvider.tsx | 4 +- client/src/app/providers/theme-controller.tsx | 7 +- .../ui/AddressMapPicker.tsx | 4 +- .../address-map-picker/ui/MapPickerMap.tsx | 4 +- .../admin-gallery/ui/AdminGalleryPage.tsx | 3 +- .../pages/admin-users/ui/AdminUsersPage.tsx | 3 +- client/src/pages/auth/ui/AuthPage.tsx | 3 +- client/src/shared/api/client.ts | 3 +- .../src/shared/lib/order-address-snapshot.ts | 3 +- client/src/shared/lib/persist-token.ts | 11 +- client/src/shared/ui/CookieConsentBanner.tsx | 7 +- .../src/shared/ui/RichTextMessageContent.tsx | 4 +- .../plans/2026-05-27-api-error-handling.md | 289 +++++++++++++ .../plans/2026-05-27-client-duplication.md | 175 ++++++++ .../plans/2026-05-27-empty-catch-blocks.md | 178 +++++++++ .../plans/2026-05-27-server-duplication.md | 318 +++++++++++++++ .../plans/2026-05-27-toast-notifications.md | 378 ++++++++++++++++++ .../2026-05-27-refactoring-audit-design.md | 201 ++++++++++ server/src/index.js | 8 +- server/src/plugins/auth.js | 3 +- server/src/routes/api/admin-products.js | 3 +- server/src/routes/api/admin-users.js | 3 +- server/src/routes/api/public-reviews.js | 3 +- server/src/routes/sse.js | 3 +- server/src/routes/user-payments.js | 3 +- server/src/routes/webhook-yookassa.js | 3 +- 26 files changed, 1590 insertions(+), 34 deletions(-) create mode 100644 docs/superpowers/plans/2026-05-27-api-error-handling.md create mode 100644 docs/superpowers/plans/2026-05-27-client-duplication.md create mode 100644 docs/superpowers/plans/2026-05-27-empty-catch-blocks.md create mode 100644 docs/superpowers/plans/2026-05-27-server-duplication.md create mode 100644 docs/superpowers/plans/2026-05-27-toast-notifications.md create mode 100644 docs/superpowers/specs/2026-05-27-refactoring-audit-design.md diff --git a/client/src/app/providers/SseProvider.tsx b/client/src/app/providers/SseProvider.tsx index b13c74f..c0258ad 100644 --- a/client/src/app/providers/SseProvider.tsx +++ b/client/src/app/providers/SseProvider.tsx @@ -53,8 +53,8 @@ export function SseProvider() { queryClient.invalidateQueries({ queryKey: ['admin', 'orders'] }) break } - } catch { - // ignore parse errors (e.g. heartbit comments) + } catch (err) { + console.warn('[sse] Failed to parse event data', err) } } } diff --git a/client/src/app/providers/theme-controller.tsx b/client/src/app/providers/theme-controller.tsx index 9537648..7dd2fe2 100644 --- a/client/src/app/providers/theme-controller.tsx +++ b/client/src/app/providers/theme-controller.tsx @@ -29,7 +29,8 @@ function readStoredTheme(): ThemeSettings | null { const schemeOk = scheme === 'craft' || scheme === 'forest' || scheme === 'ocean' || scheme === 'berry' if (!modeOk || !schemeOk) return null return { mode, scheme } - } catch { + } catch (err) { + console.warn('[theme] Failed to read stored theme', err) return null } } @@ -80,8 +81,8 @@ export function ThemeControllerProvider({ children }: PropsWithChildren) { useEffect(() => { try { localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify(settings)) - } catch { - // ignore + } catch (err) { + console.warn('[theme] Failed to persist theme setting', err) } }, [settings]) diff --git a/client/src/features/address-map-picker/ui/AddressMapPicker.tsx b/client/src/features/address-map-picker/ui/AddressMapPicker.tsx index bdacf86..4a2b769 100644 --- a/client/src/features/address-map-picker/ui/AddressMapPicker.tsx +++ b/client/src/features/address-map-picker/ui/AddressMapPicker.tsx @@ -42,8 +42,8 @@ export function AddressMapPicker(props: { setHint(addr) onChange({ lat: pos.lat, lng: pos.lng, addressLine: addr }) } - } catch { - // ignore + } catch (err) { + console.warn('[address-map-picker] Failed to reverse geocode', err) } } diff --git a/client/src/features/address-map-picker/ui/MapPickerMap.tsx b/client/src/features/address-map-picker/ui/MapPickerMap.tsx index bee9f3b..e11cfb2 100644 --- a/client/src/features/address-map-picker/ui/MapPickerMap.tsx +++ b/client/src/features/address-map-picker/ui/MapPickerMap.tsx @@ -52,8 +52,8 @@ export function MapPickerMap({ value, onChange, center }: MapPickerMapProps) { if (addr) { onChange({ lat: pos.lat, lng: pos.lng, addressLine: addr }) } - } catch { - // ignore + } catch (err) { + console.warn('[map-picker] Failed to reverse geocode', err) } } diff --git a/client/src/pages/admin-gallery/ui/AdminGalleryPage.tsx b/client/src/pages/admin-gallery/ui/AdminGalleryPage.tsx index 1c7ffe1..f84b0f2 100644 --- a/client/src/pages/admin-gallery/ui/AdminGalleryPage.tsx +++ b/client/src/pages/admin-gallery/ui/AdminGalleryPage.tsx @@ -35,7 +35,8 @@ function getApiErrorMessage(error: unknown): string | null { function formatDate(iso: string): string { try { return new Date(iso).toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric' }) - } catch { + } catch (err) { + console.warn('[gallery] Failed to format date', err) return '' } } diff --git a/client/src/pages/admin-users/ui/AdminUsersPage.tsx b/client/src/pages/admin-users/ui/AdminUsersPage.tsx index 4c2a506..c6d3975 100644 --- a/client/src/pages/admin-users/ui/AdminUsersPage.tsx +++ b/client/src/pages/admin-users/ui/AdminUsersPage.tsx @@ -35,7 +35,8 @@ function formatDt(v: string) { const d = new Date(v) if (Number.isNaN(d.getTime())) return '—' return d.toLocaleString() - } catch { + } catch (err) { + console.warn('[admin-users] Failed to format date', err) return '—' } } diff --git a/client/src/pages/auth/ui/AuthPage.tsx b/client/src/pages/auth/ui/AuthPage.tsx index d7b679a..fc6df61 100644 --- a/client/src/pages/auth/ui/AuthPage.tsx +++ b/client/src/pages/auth/ui/AuthPage.tsx @@ -23,7 +23,8 @@ function readStoredScheme(): ColorScheme { const parsed = JSON.parse(raw) const scheme = parsed?.scheme return scheme === 'forest' || scheme === 'ocean' || scheme === 'berry' ? scheme : 'craft' - } catch { + } catch (err) { + console.warn('[auth] Failed to read stored theme scheme', err) return 'craft' } } diff --git a/client/src/shared/api/client.ts b/client/src/shared/api/client.ts index 2c6be99..def7a5a 100644 --- a/client/src/shared/api/client.ts +++ b/client/src/shared/api/client.ts @@ -17,7 +17,8 @@ apiClient.interceptors.request.use((config) => { config.headers.delete('content-type') } return config - } catch { + } catch (err) { + console.warn('[api-client] Failed to set auth token', err) return config } }) diff --git a/client/src/shared/lib/order-address-snapshot.ts b/client/src/shared/lib/order-address-snapshot.ts index d25a4bc..b94cf7c 100644 --- a/client/src/shared/lib/order-address-snapshot.ts +++ b/client/src/shared/lib/order-address-snapshot.ts @@ -12,7 +12,8 @@ export function parseOrderAddressSnapshot(json: string | null | undefined): Orde if (!json) return null try { return JSON.parse(json) as OrderAddressSnapshot - } catch { + } catch (err) { + console.warn('[order-address-snapshot] Failed to parse address snapshot', err) return null } } diff --git a/client/src/shared/lib/persist-token.ts b/client/src/shared/lib/persist-token.ts index 62635b6..ed6dea3 100644 --- a/client/src/shared/lib/persist-token.ts +++ b/client/src/shared/lib/persist-token.ts @@ -3,7 +3,8 @@ const TOKEN_KEY = 'craftshop_auth_token' export function readStoredToken(): string | null { try { return localStorage.getItem(TOKEN_KEY) - } catch { + } catch (err) { + console.warn('[persist-token] Failed to read from localStorage', err) return null } } @@ -12,15 +13,15 @@ export function persistToken(token: string | null): void { try { if (!token) localStorage.removeItem(TOKEN_KEY) else localStorage.setItem(TOKEN_KEY, token) - } catch { - // ignore + } catch (err) { + console.warn('[persist-token] Failed to write to localStorage', err) } } export function removeStoredToken(): void { try { localStorage.removeItem(TOKEN_KEY) - } catch { - // ignore + } catch (err) { + console.warn('[persist-token] Failed to remove from localStorage', err) } } diff --git a/client/src/shared/ui/CookieConsentBanner.tsx b/client/src/shared/ui/CookieConsentBanner.tsx index 2e7196e..cef36d3 100644 --- a/client/src/shared/ui/CookieConsentBanner.tsx +++ b/client/src/shared/ui/CookieConsentBanner.tsx @@ -10,7 +10,8 @@ const STORAGE_KEY = 'cookie-consent-accepted' function wasAccepted(): boolean { try { return localStorage.getItem(STORAGE_KEY) === '1' - } catch { + } catch (err) { + console.warn('[cookie-consent] Failed to read cookie consent', err) return false } } @@ -18,8 +19,8 @@ function wasAccepted(): boolean { function markAccepted() { try { localStorage.setItem(STORAGE_KEY, '1') - } catch { - // ignore + } catch (err) { + console.warn('[cookie-consent] Failed to persist cookie consent', err) } } diff --git a/client/src/shared/ui/RichTextMessageContent.tsx b/client/src/shared/ui/RichTextMessageContent.tsx index 34d6ad2..5cc6f8c 100644 --- a/client/src/shared/ui/RichTextMessageContent.tsx +++ b/client/src/shared/ui/RichTextMessageContent.tsx @@ -22,8 +22,8 @@ export function RichTextMessageContent({ value, tone = 'default' }: RichTextMess const normalizedValue = value.trim() ? value : '

' try { if (editor.getHTML() === normalizedValue) return - } catch { - // editor schema not ready yet + } catch (err) { + console.warn('[tiptap] Failed to get editor HTML', err) return } editor.commands.setContent(normalizedValue, { emitUpdate: false }) diff --git a/docs/superpowers/plans/2026-05-27-api-error-handling.md b/docs/superpowers/plans/2026-05-27-api-error-handling.md new file mode 100644 index 0000000..6975986 --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-api-error-handling.md @@ -0,0 +1,289 @@ +# API Error Handling — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. + +**Goal:** Создать `useMutationWithToast` обёртку, улучшить `getApiErrorMessage`, исправить CheckoutPage error display. + +**Architecture:** Обёртка над `useMutation` с автоматическим показом toast (через notification store из подпроекта 1), улучшенный парсинг ошибок API. + +**Tech Stack:** TypeScript, TanStack React Query, Vitest + +**Depends on:** Subproject 1 (toast notifications store) + +--- + +### Task 1: Улучшить getApiErrorMessage + +**Files:** +- Modify: `client/src/shared/lib/get-api-error-message.ts` +- Test: modify existing or add new tests + +- [ ] **Step 1: Write/update tests** + +```ts +// client/src/shared/lib/__tests__/get-api-error-message.test.ts +import { describe, it, expect } from 'vitest' +import { getApiErrorMessage } from '../get-api-error-message' + +describe('getApiErrorMessage', () => { + it('returns server error message when axios error has response.data.error', () => { + const err = { response: { data: { error: 'Email already taken' } } } + expect(getApiErrorMessage(err)).toBe('Email already taken') + }) + + it('returns network error message when no response', () => { + const err = { message: 'Network Error', code: 'ERR_NETWORK' } + expect(getApiErrorMessage(err)).toBe('Нет соединения с сервером. Проверьте подключение к интернету.') + }) + + it('returns generic 500 message', () => { + const err = { response: { status: 500, data: {} } } + expect(getApiErrorMessage(err)).toBe('Произошла ошибка. Попробуйте повторить позже.') + }) + + it('falls back to error message', () => { + const err = new Error('Something went wrong') + expect(getApiErrorMessage(err)).toBe('Something went wrong') + }) + + it('handles unknown error shape', () => { + expect(getApiErrorMessage({})).toBe('Произошла неизвестная ошибка') + }) +}) +``` + +- [ ] **Step 2: Run to see failure** + +Run: `cd client && npx vitest run shared/lib/__tests__/get-api-error-message.test.ts` +Expected: FAIL (existing tests may not cover new cases) + +- [ ] **Step 3: Implement improved getApiErrorMessage** + +```ts +// client/src/shared/lib/get-api-error-message.ts +import { isAxiosError } from 'axios' + +export function getApiErrorMessage(error: unknown): string { + if (!error) return 'Произошла неизвестная ошибка' + + if (isAxiosError(error)) { + if (error.response?.data?.error && typeof error.response.data.error === 'string') { + return error.response.data.error + } + if (!error.response) { + return 'Нет соединения с сервером. Проверьте подключение к интернету.' + } + if (error.response.status >= 500) { + return 'Произошла ошибка. Попробуйте повторить позже.' + } + } + + if (error instanceof Error) { + return error.message + } + + return 'Произошла неизвестная ошибка' +} +``` + +- [ ] **Step 4: Run tests** + +Run: `cd client && npx vitest run shared/lib/__tests__/get-api-error-message.test.ts` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add client/src/shared/lib/get-api-error-message.ts client/src/shared/lib/__tests__/get-api-error-message.test.ts +git commit -m "feat: improve getApiErrorMessage with user-friendly messages" +``` + +--- + +### Task 2: useMutationWithToast обёртка + +**Files:** +- Create: `client/src/shared/lib/use-mutation-with-toast.ts` +- Test: `client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx` + +- [ ] **Step 1: Write failing tests** + +```tsx +// client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { renderHook, waitFor } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { useMutationWithToast } from '../use-mutation-with-toast' +import { addNotification } from '../../model/notification' + +vi.mock('../../model/notification', () => ({ + addNotification: vi.fn(), +})) + +function createWrapper() { + const qc = new QueryClient() + return ({ children }: { children: React.ReactNode }) => ( + {children} + ) +} + +describe('useMutationWithToast', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('shows success toast on success', async () => { + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + + const { result } = renderHook( + () => useMutationWithToast({ mutationFn, successMessage: 'Done!' }), + { wrapper: createWrapper() }, + ) + + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(addNotification).toHaveBeenCalledWith({ type: 'success', message: 'Done!' }) + }) + + it('shows error toast on error', async () => { + const mutationFn = vi.fn().mockRejectedValue(new Error('Boom')) + + const { result } = renderHook( + () => useMutationWithToast({ mutationFn }), + { wrapper: createWrapper() }, + ) + + result.current.mutate() + await waitFor(() => expect(result.current.isError).toBe(true)) + + expect(addNotification).toHaveBeenCalledWith({ type: 'error', message: 'Boom' }) + }) + + it('calls user-provided onSuccess', async () => { + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const onSuccess = vi.fn() + + const { result } = renderHook( + () => useMutationWithToast({ mutationFn, onSuccess, successMessage: 'Done!' }), + { wrapper: createWrapper() }, + ) + + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(onSuccess).toHaveBeenCalled() + }) + + it('does not show success toast if no successMessage', async () => { + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + + const { result } = renderHook( + () => useMutationWithToast({ mutationFn }), + { wrapper: createWrapper() }, + ) + + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(addNotification).not.toHaveBeenCalled() + }) +}) +``` + +- [ ] **Step 2: Run to verify failure** + +Run: `cd client && npx vitest run shared/lib/__tests__/use-mutation-with-toast.test.tsx` +Expected: FAIL + +- [ ] **Step 3: Implement useMutationWithToast** + +```ts +// client/src/shared/lib/use-mutation-with-toast.ts +import { useMutation, type UseMutationOptions } from '@tanstack/react-query' +import { addNotification } from '../model/notification' +import { getApiErrorMessage } from './get-api-error-message' + +type MutationWithToastOptions = + UseMutationOptions & { + successMessage?: string + } + +export function useMutationWithToast( + options: MutationWithToastOptions, +) { + const { successMessage, onSuccess, onError, ...mutationOptions } = options + + return useMutation({ + ...mutationOptions, + onSuccess: (data, variables, context) => { + if (successMessage) { + addNotification({ type: 'success', message: successMessage }) + } + onSuccess?.(data, variables, context) + }, + onError: (error, variables, context) => { + addNotification({ type: 'error', message: getApiErrorMessage(error) }) + onError?.(error, variables, context) + }, + }) +} +``` + +- [ ] **Step 4: Run tests** + +Run: `cd client && npx vitest run shared/lib/__tests__/use-mutation-with-toast.test.tsx` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add client/src/shared/lib/use-mutation-with-toast.ts client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx +git commit -m "feat: add useMutationWithToast wrapper" +``` + +--- + +### Task 3: Исправить CheckoutPage error display + +**Files:** +- Modify: `client/src/pages/checkout/CheckoutPage.tsx` + +- [ ] **Step 1: Найти прямой вызов error.message** + +Search for: `(createMut.error as Error).message` + +- [ ] **Step 2: Заменить на getApiErrorMessage** + +Before: +```tsx +{createMut.isError && ( + + {(createMut.error as Error).message} + +)} +``` + +After: +```tsx +import { getApiErrorMessage } from '@/shared/lib/get-api-error-message' + +{createMut.isError && ( + + {getApiErrorMessage(createMut.error)} + +)} +``` + +- [ ] **Step 3: Run lint + test + build** + +```bash +cd client && npm run lint && npm test && npm run build +``` + +- [ ] **Step 4: Commit** + +```bash +git add client/src/pages/checkout/CheckoutPage.tsx +git commit -m "fix: use getApiErrorMessage in CheckoutPage for user-friendly error display" +``` diff --git a/docs/superpowers/plans/2026-05-27-client-duplication.md b/docs/superpowers/plans/2026-05-27-client-duplication.md new file mode 100644 index 0000000..97209ad --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-client-duplication.md @@ -0,0 +1,175 @@ +# Client Duplication — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. + +**Goal:** Устранить дублирование `useQuery` для корзины (4 копии → 1 хук), устранить дублирование статусов заказа. + +**Architecture:** Кастомный хук `useCartQuery` в `entities/cart/lib/`, единый источник `ORDER_STATUS_DATA`. + +**Tech Stack:** TypeScript, TanStack React Query, Vitest + +**Depends on:** none + +--- + +### Task 1: useCartQuery хук + тесты + +**Files:** +- Create: `client/src/entities/cart/lib/use-cart-query.ts` +- Test: `client/src/entities/cart/lib/use-cart-query.test.tsx` +- Modify: `client/src/widgets/catalog-slider/ui/AppHeader.tsx` +- Modify: `client/src/pages/cart/CartPage.tsx` +- Modify: `client/src/pages/checkout/CheckoutPage.tsx` +- Modify: `client/src/features/cart/ui/ToggleCartIcon/ToggleCartIcon.tsx` + +- [ ] **Step 1: Write failing tests** + +```tsx +// client/src/entities/cart/lib/use-cart-query.test.tsx +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { renderHook, waitFor } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { useCartQuery } from './use-cart-query' +import { fetchMyCart } from '../../api' + +vi.mock('../../api', () => ({ + fetchMyCart: vi.fn(), +})) + +vi.mock('@/shared/model/auth', () => ({ + useAuthUser: vi.fn(), +})) + +import { useAuthUser } from '@/shared/model/auth' + +function createWrapper() { + const qc = new QueryClient() + return ({ children }: { children: React.ReactNode }) => ( + {children} + ) +} + +describe('useCartQuery', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('returns query with correct key and enabled flag for authenticated user', async () => { + vi.mocked(useAuthUser).mockReturnValue({ id: '1', email: 'test@test.com' }) + vi.mocked(fetchMyCart).mockResolvedValue({ items: [] }) + + const { result } = renderHook(() => useCartQuery(), { wrapper: createWrapper() }) + + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + expect(fetchMyCart).toHaveBeenCalled() + expect(result.current.queryKey).toEqual(['me', 'cart']) + }) + + it('does not fetch when user is not authenticated', () => { + vi.mocked(useAuthUser).mockReturnValue(null) + + const { result } = renderHook(() => useCartQuery(), { wrapper: createWrapper() }) + + expect(fetchMyCart).not.toHaveBeenCalled() + expect(result.current.fetchStatus).toBe('idle') + }) +}) +``` + +- [ ] **Step 2: Run to verify failure** + +Run: `cd client && npx vitest run entities/cart/lib/use-cart-query.test.tsx` +Expected: FAIL + +- [ ] **Step 3: Implement useCartQuery** + +```ts +// client/src/entities/cart/lib/use-cart-query.ts +import { useQuery } from '@tanstack/react-query' +import { useAuthUser } from '@/shared/model/auth' +import { fetchMyCart } from '../../api' + +export function useCartQuery() { + const user = useAuthUser() + + return useQuery({ + queryKey: ['me', 'cart'], + queryFn: fetchMyCart, + enabled: Boolean(user), + }) +} +``` + +- [ ] **Step 4: Run tests** + +Run: `cd client && npx vitest run entities/cart/lib/use-cart-query.test.tsx` +Expected: PASS + +- [ ] **Step 5: Apply to AppHeader.tsx** + +Before: +```tsx +const { data: cart } = useQuery({ + queryKey: ['me', 'cart'], + queryFn: fetchMyCart, + enabled: Boolean(user), +}) +``` + +After: +```tsx +import { useCartQuery } from '@/entities/cart/lib/use-cart-query' +const { data: cart } = useCartQuery() +``` + +- [ ] **Step 6: Apply to CartPage.tsx, CheckoutPage.tsx, ToggleCartIcon.tsx** + +Same replacement in each file. + +- [ ] **Step 7: Run lint + test + build** + +```bash +cd client && npm run lint && npm test && npm run build +``` + +- [ ] **Step 8: Commit** + +```bash +git add client/src/entities/cart/lib/use-cart-query.ts client/src/entities/cart/lib/use-cart-query.test.tsx client/src/widgets/catalog-slider/ui/AppHeader.tsx client/src/pages/cart/CartPage.tsx client/src/pages/checkout/CheckoutPage.tsx client/src/features/cart/ui/ToggleCartIcon/ToggleCartIcon.tsx +git commit -m "refactor: extract useCartQuery hook" +``` + +--- + +### Task 2: Устранить дублирование статусов заказа + +**Files:** +- Read: `client/src/shared/lib/order-status-data.ts` +- Read: `client/src/shared/lib/order-status-labels.ts` +- Delete: `client/src/shared/lib/order-status-labels.ts` +- Modify: all files importing from `order-status-labels` + +- [ ] **Step 1: Найти все импорты orderStatusLabelRu** + +Run: `rg 'orderStatusLabelRu' client/src/ --include '*.ts' --include '*.tsx'` + +- [ ] **Step 2: Заменить импорты на ORDER_STATUS_DATA** + +Each file importing `{ orderStatusLabelRu }` from `order-status-labels`: +- Change to import `{ ORDER_STATUS_DATA }` from `order-status-data` +- Replace `orderStatusLabelRu(status)` with `ORDER_STATUS_DATA[status].label` + +- [ ] **Step 3: Delete order-status-labels.ts** + +- [ ] **Step 4: Run lint + test + build** + +```bash +cd client && npm run lint && npm test && npm run build +``` + +- [ ] **Step 5: Commit** + +```bash +git add client/src/shared/lib/order-status-labels.ts client/src/shared/lib/order-status-data.ts +git commit -m "refactor: remove duplicate order status labels, use ORDER_STATUS_DATA as single source" +``` diff --git a/docs/superpowers/plans/2026-05-27-empty-catch-blocks.md b/docs/superpowers/plans/2026-05-27-empty-catch-blocks.md new file mode 100644 index 0000000..cb7a57c --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-empty-catch-blocks.md @@ -0,0 +1,178 @@ +# Empty Catch Blocks — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. + +**Goal:** Добавить логирование во все пустые catch-блоки (17 мест), убрать `// ignore` комментарии. + +**Architecture:** В каждом catch добавить `console.warn` (клиент) или `request.log.error` (сервер) с контекстным сообщением. Минимальные, безопасные изменения. + +**Tech Stack:** TypeScript, JavaScript, ESLint (no-console разрешает warn/error/info) + +**Depends on:** none + +--- + +### Task 1: Пустые catch на клиенте — persist-token.ts (3 места) + +**Files:** +- Modify: `client/src/shared/model/persist-token.ts` + +- [ ] **Step 1: Read file to find empty catch blocks** + +Run: read `client/src/shared/model/persist-token.ts` + +- [ ] **Step 2: Add console.warn to each catch** + +Each `catch { /* ignore */ }` becomes: +```ts +catch (err) { + console.warn('[persist-token] Failed to ...', err) +} +``` + +Specific messages based on context: +- localStorage.getItem error → `'[persist-token] Failed to read from localStorage'` +- localStorage.setItem error → `'[persist-token] Failed to write to localStorage'` +- JSON.parse error → `'[persist-token] Failed to parse stored value'` + +- [ ] **Step 3: Run lint** + +Run: `cd client && npm run lint` +Expected: PASS + +- [ ] **Step 4: Commit** + +```bash +git add client/src/shared/model/persist-token.ts +git commit -m "fix: add error logging to persist-token catch blocks" +``` + +--- + +### Task 2: Пустые catch на клиенте — theme-controller.tsx (2 места) + +**Files:** +- Modify: `client/src/shared/model/theme-controller.tsx` + +- [ ] **Step 1: Read file** + +Run: read `client/src/shared/model/theme-controller.tsx` + +- [ ] **Step 2: Add console.warn to each catch** + +```ts +catch (err) { + console.warn('[theme] Failed to ...', err) +} +``` + +- [ ] **Step 3: Run lint** + +- [ ] **Step 4: Commit** + +```bash +git add client/src/shared/model/theme-controller.tsx +git commit -m "fix: add error logging to theme-controller catch blocks" +``` + +--- + +### Task 3: Пустые catch на клиенте — CookieConsentBanner (2 места) + +**Files:** +- Modify: `client/src/widgets/navigation-drawer/ui/CookieConsentBanner.tsx` + +- [ ] **Step 1: Read file** + +- [ ] **Step 2: Add console.warn** + +```ts +catch (err) { + console.warn('[cookie-consent] Failed to ...', err) +} +``` + +- [ ] **Step 3: Run lint** + +- [ ] **Step 4: Commit** + +```bash +git add client/src/widgets/navigation-drawer/ui/CookieConsentBanner.tsx +git commit -m "fix: add error logging to CookieConsentBanner catch blocks" +``` + +--- + +### Task 4: Пустые catch на клиенте — SseProvider.tsx + +**Files:** +- Modify: `client/src/app/SseProvider.tsx` + +- [ ] **Step 1: Read file, find empty catch** + +- [ ] **Step 2: Add console.warn** + +```ts +catch (err) { + console.warn('[sse] Connection error:', err) +} +``` + +- [ ] **Step 3: Run lint** + +- [ ] **Step 4: Commit** + +```bash +git add client/src/app/SseProvider.tsx +git commit -m "fix: add error logging to SseProvider catch block" +``` + +--- + +### Task 5: Пустые catch на сервере + +**Files:** (find exact paths from exploration, likely in admin routes) + +- [ ] **Step 1: Find all empty catch blocks in server/src/** + +Run: `rg 'catch\s*\{' server/src/ --include '*.js'` + +- [ ] **Step 2: Add request.log.error to each** + +```js +catch (err) { + request.log.error({ err }, 'Failed to [operation description]') +} +``` + +- [ ] **Step 3: Run lint** + +Run: `cd server && npm run lint` +Expected: PASS + +- [ ] **Step 4: Run tests** + +Run: `cd server && npm test` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add server/src/ +git commit -m "fix: add error logging to server catch blocks" +``` + +--- + +### Task 6: Финальная проверка + +- [ ] **Step 1: Run all lints + tests** + +```bash +cd client && npm run lint && npm test +cd server && npm run lint && npm test +``` + +- [ ] **Step 2: Verify no new ESLint errors** + +Expected: PASS all diff --git a/docs/superpowers/plans/2026-05-27-server-duplication.md b/docs/superpowers/plans/2026-05-27-server-duplication.md new file mode 100644 index 0000000..5dba1a2 --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-server-duplication.md @@ -0,0 +1,318 @@ +# Server Duplication — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. + +**Goal:** Устранить дублирование в серверных роутах: asyncHandler декоратор, validateGalleryImages, findUserOrder. + +**Architecture:** Вынос повторяющихся паттернов в shared-хелперы (`server/src/lib/`), замена ручного try/catch на декоратор. + +**Tech Stack:** JavaScript, Fastify, Prisma, Vitest + +**Depends on:** none + +--- + +### Task 1: asyncHandler декоратор + тесты + +**Files:** +- Create: `server/src/lib/async-handler.js` +- Test: `server/src/lib/__tests__/async-handler.test.js` + +- [ ] **Step 1: Write failing tests** + +```js +// server/src/lib/__tests__/async-handler.test.js +import { describe, it, expect, vi } from 'vitest' +import { asyncHandler } from '../async-handler.js' + +describe('asyncHandler', () => { + it('calls the handler and returns result on success', async () => { + const handler = vi.fn().mockResolvedValue({ hello: 'world' }) + const request = {} + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + await asyncHandler(handler)(request, reply) + expect(handler).toHaveBeenCalledWith(request, reply) + expect(reply.send).toHaveBeenCalledWith({ hello: 'world' }) + }) + + it('catches errors and sends 500 with message', async () => { + const handler = vi.fn().mockRejectedValue(new Error('boom')) + const request = { log: { error: vi.fn() } } + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + await asyncHandler(handler)(request, reply) + expect(reply.code).toHaveBeenCalledWith(500) + expect(reply.send).toHaveBeenCalledWith({ error: 'Internal server error' }) + }) + + it('uses statusCode from error if present', async () => { + const err = new Error('Not found') + err.statusCode = 404 + const handler = vi.fn().mockRejectedValue(err) + const request = { log: { error: vi.fn() } } + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + await asyncHandler(handler)(request, reply) + expect(reply.code).toHaveBeenCalledWith(404) + expect(reply.send).toHaveBeenCalledWith({ error: 'Not found' }) + }) +}) +``` + +- [ ] **Step 2: Run to verify failure** + +Run: `cd server && npx vitest run lib/__tests__/async-handler.test.js` +Expected: FAIL + +- [ ] **Step 3: Implement asyncHandler** + +```js +// server/src/lib/async-handler.js +export function asyncHandler(fn) { + return async (request, reply) => { + try { + return await fn(request, reply) + } catch (err) { + request.log.error(err) + const statusCode = err.statusCode || 500 + const message = err.statusCode ? err.message : 'Internal server error' + return reply.code(statusCode).send({ error: message }) + } + } +} +``` + +- [ ] **Step 4: Run tests** + +Run: `cd server && npx vitest run lib/__tests__/async-handler.test.js` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add server/src/lib/async-handler.js server/src/lib/__tests__/async-handler.test.js +git commit -m "feat: add asyncHandler decorator for route error handling" +``` + +--- + +### Task 2: Применить asyncHandler в роутах + +**Files:** +- Modify: `server/src/routes/user-orders.js` +- Modify: `server/src/routes/user-messages.js` +- Modify: `server/src/routes/user-payments.js` +- Modify: `server/src/routes/admin-gallery.js` +- Modify: all other route files with manual try/catch + +- [ ] **Step 1: Найти все ручные try/catch в роутах** + +Run: `rg 'try\s*\{' server/src/routes/ --include '*.js'` + +- [ ] **Step 2: Заменить каждый try/catch на asyncHandler** + +Before: +```js +fastify.get('/orders', async (request, reply) => { + try { + const orders = await prisma.order.findMany(...) + return reply.send(orders) + } catch (err) { + request.log.error(err) + return reply.code(500).send({ error: 'Internal server error' }) + } +}) +``` + +After: +```js +import { asyncHandler } from '../../lib/async-handler.js' + +fastify.get('/orders', asyncHandler(async (request, reply) => { + const orders = await prisma.order.findMany(...) + return reply.send(orders) +})) +``` + +- [ ] **Step 3: Run lint + tests** + +```bash +cd server && npm run lint && npm test +``` + +- [ ] **Step 4: Commit** + +```bash +git add server/src/routes/ +git commit -m "refactor: apply asyncHandler to all route handlers" +``` + +--- + +### Task 3: validateGalleryImages хелпер + +**Files:** +- Create: `server/src/lib/validate-gallery-images.js` +- Test: `server/src/lib/__tests__/validate-gallery-images.test.js` +- Modify: `server/src/routes/api/admin-products.js` + +- [ ] **Step 1: Write tests** + +```js +// server/src/lib/__tests__/validate-gallery-images.test.js +import { describe, it, expect, vi } from 'vitest' +import { validateGalleryImages } from '../validate-gallery-images.js' + +describe('validateGalleryImages', () => { + it('returns null when galleryImages is empty', async () => { + const prisma = { galleryImage: { findMany: vi.fn() } } + const result = await validateGalleryImages(prisma, []) + expect(result).toBeNull() + }) + + it('throws when image not found', async () => { + const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue([]) } } + await expect(validateGalleryImages(prisma, [1])).rejects.toThrow('not found') + }) +}) +``` + +- [ ] **Step 2: Implement** + +```js +// server/src/lib/validate-gallery-images.js +export async function validateGalleryImages(prisma, galleryImages) { + if (!galleryImages || galleryImages.length === 0) return null + + const existing = await prisma.galleryImage.findMany({ + where: { id: { in: galleryImages } }, + select: { id: true, resized: true }, + }) + + const foundIds = new Set(existing.map((img) => img.id)) + const missing = galleryImages.filter((id) => !foundIds.has(id)) + if (missing.length > 0) { + throw Object.assign(new Error(`Gallery images not found: ${missing.join(', ')}`), { statusCode: 404 }) + } + + const notResized = existing.filter((img) => !img.resized) + if (notResized.length > 0) { + throw Object.assign(new Error('Some gallery images have not been processed yet. Please try again later.'), { statusCode: 400 }) + } + + return existing +} +``` + +- [ ] **Step 3: Заменить дублирующийся код в admin-products.js** + +Before (in POST /admin/products): +```js +// validate gallery images +if (galleryImages && galleryImages.length > 0) { + const existingImages = await prisma.galleryImage.findMany({ ... }) + // ... duplicate validation logic +} +``` + +After: +```js +import { validateGalleryImages } from '../../lib/validate-gallery-images.js' + +// single call +await validateGalleryImages(prisma, galleryImages) +``` + +Same replacement for PATCH /admin/products/:id. + +- [ ] **Step 4: Run tests** + +```bash +cd server && npm run lint && npm test +``` + +- [ ] **Step 5: Commit** + +```bash +git add server/src/lib/validate-gallery-images.js server/src/lib/__tests__/validate-gallery-images.test.js server/src/routes/api/admin-products.js +git commit -m "refactor: extract validateGalleryImages helper" +``` + +--- + +### Task 4: findUserOrder хелпер + +**Files:** +- Create: `server/src/lib/find-user-order.js` +- Test: `server/src/lib/__tests__/find-user-order.test.js` +- Modify: `server/src/routes/user-orders.js` +- Modify: `server/src/routes/user-messages.js` +- Modify: `server/src/routes/user-payments.js` + +- [ ] **Step 1: Write tests** + +```js +// server/src/lib/__tests__/find-user-order.test.js +import { describe, it, expect, vi } from 'vitest' +import { findUserOrder } from '../find-user-order.js' + +describe('findUserOrder', () => { + it('returns order when found', async () => { + const mockOrder = { id: '1', userId: 'user1' } + const prisma = { order: { findFirst: vi.fn().mockResolvedValue(mockOrder) } } + const result = await findUserOrder(prisma, '1', 'user1') + expect(result).toEqual(mockOrder) + expect(prisma.order.findFirst).toHaveBeenCalledWith(expect.objectContaining({ + where: { id: '1', userId: 'user1' }, + })) + }) + + it('throws 404 when not found', async () => { + const prisma = { order: { findFirst: vi.fn().mockResolvedValue(null) } } + await expect(findUserOrder(prisma, '999', 'user1')).rejects.toMatchObject({ statusCode: 404 }) + }) +}) +``` + +- [ ] **Step 2: Implement** + +```js +// server/src/lib/find-user-order.js +export async function findUserOrder(prisma, orderId, userId, include = {}) { + const order = await prisma.order.findFirst({ + where: { id: orderId, userId }, + include, + }) + + if (!order) { + throw Object.assign(new Error('Order not found'), { statusCode: 404 }) + } + + return order +} +``` + +- [ ] **Step 3: Заменить дублирующийся код в роутах** + +Each instance of: +```js +const order = await prisma.order.findFirst({ where: { id, userId } }) +if (!order) return reply.code(404).send({ error: 'Order not found' }) +``` + +Becomes: +```js +import { findUserOrder } from '../../lib/find-user-order.js' +const order = await findUserOrder(prisma, id, userId) +``` + +- [ ] **Step 4: Run tests** + +```bash +cd server && npm run lint && npm test +``` + +- [ ] **Step 5: Commit** + +```bash +git add server/src/lib/find-user-order.js server/src/lib/__tests__/find-user-order.test.js server/src/routes/user-{orders,messages,payments}.js +git commit -m "refactor: extract findUserOrder helper" +``` diff --git a/docs/superpowers/plans/2026-05-27-toast-notifications.md b/docs/superpowers/plans/2026-05-27-toast-notifications.md new file mode 100644 index 0000000..b9a78d7 --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-toast-notifications.md @@ -0,0 +1,378 @@ +# Toast Notifications System — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. + +**Goal:** Создать общую систему toast-уведомлений на Effector + MUI, мигрировать CartSnackbar, удалить старый код. + +**Architecture:** Effector-стор `$notifications` с очередью (макс 3 видимых), компонент `NotificationStack` с MUI Snackbar + Alert, интеграция через события `addNotification`/`dismissNotification`. + +**Tech Stack:** Effector, MUI Snackbar + Alert, TypeScript, Vitest + @testing-library/react + +**Depends on:** none + +--- + +### Task 1: Effector-стор уведомлений + +**Files:** +- Create: `client/src/shared/model/notification.ts` +- Test: `client/src/shared/model/notification.test.ts` + +- [ ] **Step 1: Write failing tests for notification store** + +```ts +// client/src/shared/model/notification.test.ts +import { describe, it, expect } from 'vitest' +import { + $notifications, + addNotification, + dismissNotification, + dismissAll, +} from './notification' + +describe('notification store', () => { + it('starts empty', () => { + expect($notifications.getState()).toEqual([]) + }) + + it('adds a notification', () => { + addNotification({ type: 'success', message: 'OK' }) + const state = $notifications.getState() + expect(state).toHaveLength(1) + expect(state[0]).toMatchObject({ type: 'success', message: 'OK' }) + expect(state[0].id).toBeDefined() + }) + + it('caps at 3 visible notifications, queues extras', () => { + addNotification({ type: 'info', message: 'A' }) + addNotification({ type: 'info', message: 'B' }) + addNotification({ type: 'info', message: 'C' }) + addNotification({ type: 'info', message: 'D' }) + expect($notifications.getState()).toHaveLength(3) + // wait for idle and check — actually effector stores are sync + // but we need to verify only 3 are visible and 4th is queued + }) + + it('dismisses a notification by id', () => { + const id = 'test-id' + // manually set state + // add dismiss and check + }) + + it('dismisses all notifications', () => { + // add several, dismissAll, check empty + }) + + it('auto-dismisses after autoHideDuration', () => { + // use fake timers + }) +}) +``` + +- [ ] **Step 2: Run to verify failure** + +Run: `cd client && npx vitest run shared/model/notification.test.ts` +Expected: FAIL, module not found + +- [ ] **Step 3: Implement notification store** + +```ts +// client/src/shared/model/notification.ts +import { createEvent, createStore, sample } from 'effector' + +type NotificationType = 'success' | 'error' | 'info' | 'warning' + +interface Notification { + id: string + type: NotificationType + message: string + autoHideDuration?: number +} + +const MAX_VISIBLE = 3 + +let nextId = 1 + +export const addNotification = createEvent<{ + type: NotificationType + message: string + autoHideDuration?: number +}>() + +export const dismissNotification = createEvent() +export const dismissAll = createEvent() + +export const $notifications = createStore([]) + .on(addNotification, (state, { type, message, autoHideDuration }) => { + const notification: Notification = { + id: String(nextId++), + type, + message, + autoHideDuration: autoHideDuration ?? (type === 'error' ? 6000 : 4000), + } + return [...state, notification].slice(-MAX_VISIBLE) + }) + .on(dismissNotification, (state, id) => + state.filter((n) => n.id !== id), + ) + .reset(dismissAll) +``` + +- [ ] **Step 4: Run tests to verify they pass** + +Run: `cd client && npx vitest run shared/model/notification.test.ts` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add client/src/shared/model/notification.ts client/src/shared/model/notification.test.ts +git commit -m "feat: add notification store (Effector)" +``` + +--- + +### Task 2: NotificationStack component + +**Files:** +- Create: `client/src/shared/ui/NotificationStack/NotificationStack.tsx` +- Create: `client/src/shared/ui/NotificationStack/index.ts` +- Test: `client/src/shared/ui/NotificationStack/NotificationStack.test.tsx` + +- [ ] **Step 1: Write failing tests for NotificationStack** + +```tsx +// client/src/shared/ui/NotificationStack/NotificationStack.test.tsx +import { describe, it, expect, vi, afterEach } from 'vitest' +import { render, screen, act, fireEvent } from '@testing-library/react' +import { NotificationStack } from './NotificationStack' +import { $notifications, addNotification, dismissNotification } from '../../model/notification' +import { fork, allSettled } from 'effector' +import { Provider } from 'effector-react' + +function renderStack() { + const scope = fork() + return { + scope, + ...render( + + + , + ), + } +} + +describe('NotificationStack', () => { + afterEach(() => { + $notifications.reset() + }) + + it('renders nothing when empty', () => { + const { container } = renderStack() + expect(container.textContent).toBe('') + }) + + it('renders a notification when added', async () => { + const scope = fork() + await allSettled(addNotification, { scope, params: { type: 'success', message: 'Test message' } }) + render( + + + , + ) + expect(screen.getByText('Test message')).toBeDefined() + }) + + it('renders correct icon for each type', async () => { + const scope = fork() + // success — CheckCircle, error — Error, info — Info, warning — Warning + // Check MUI Alert has correct severity attribute + await allSettled(addNotification, { scope, params: { type: 'error', message: 'Error!' } }) + render( + + + , + ) + const alert = screen.getByRole('alert') + expect(alert.getAttribute('severity')).toBe('error') + }) +}) +``` + +- [ ] **Step 2: Run to verify failure** + +Run: `cd client && npx vitest run shared/ui/NotificationStack/NotificationStack.test.tsx` +Expected: FAIL + +- [ ] **Step 3: Implement NotificationStack** + +```tsx +// client/src/shared/ui/NotificationStack/NotificationStack.tsx +import { useUnit } from 'effector-react' +import { Snackbar, Alert, Stack, IconButton } from '@mui/material' +import CloseIcon from '@mui/icons-material/Close' +import { $notifications, dismissNotification } from '../../model/notification' + +export function NotificationStack() { + const notifications = useUnit($notifications) + + if (notifications.length === 0) return null + + return ( + + {notifications.map((n) => ( + dismissNotification(n.id)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} + > + dismissNotification(n.id)}> + + + } + > + {n.message} + + + ))} + + ) +} +``` + +```ts +// client/src/shared/ui/NotificationStack/index.ts +export { NotificationStack } from './NotificationStack' +``` + +- [ ] **Step 4: Run tests** + +Run: `cd client && npx vitest run shared/ui/NotificationStack/NotificationStack.test.tsx` +Expected: PASS + +- [ ] **Step 5: Commit** + +```bash +git add client/src/shared/ui/NotificationStack/ +git commit -m "feat: add NotificationStack component" +``` + +--- + +### Task 3: Add NotificationStack to App.tsx + +**Files:** +- Modify: `client/src/app/App.tsx` + +- [ ] **Step 1: Add NotificationStack to App layout** + +```tsx +// App.tsx — add import and component +import { NotificationStack } from '@/shared/ui/NotificationStack' + +// Inside the return, after +<> + + + + + + + + + + + +``` + +- [ ] **Step 2: Run lint + build** + +Run: `cd client && npm run lint && npm test` +Expected: PASS + +- [ ] **Step 3: Commit** + +```bash +git add client/src/app/App.tsx +git commit -m "feat: integrate NotificationStack into App" +``` + +--- + +### Task 4: Migrate CartSnackbar to notification store + +**Files:** +- Modify: `client/src/features/cart/ui/ToggleCartIcon/ToggleCartIcon.tsx` +- Modify: `client/src/features/cart/ui/AddToCartButton/AddToCartButton.tsx` +- Delete: `client/src/features/cart/ui/CartSnackbar/CartSnackbar.tsx` +- Delete: `client/src/features/cart/ui/CartSnackbar/index.ts` +- Delete: `client/src/features/cart/model/cart-notifications.ts` +- Modify: `client/src/app/App.tsx` (remove CartSnackbar import + usage) + +- [ ] **Step 1: Replace cartAdded events with addNotification in ToggleCartIcon** + +```tsx +// ToggleCartIcon.tsx — replace cartAdded with addNotification +import { addNotification } from '@/shared/model/notification' + +// search for: cartAdded() +// replace with: +addNotification({ type: 'info', message: 'Товар добавлен в корзину' }) +``` + +- [ ] **Step 2: Same for AddToCartButton** + +```tsx +// AddToCartButton.tsx — same replacement +addNotification({ type: 'info', message: 'Товар добавлен в корзину' }) +``` + +- [ ] **Step 3: Remove CartSnackbar component files** + +Delete `CartSnackbar.tsx` and `CartSnackbar/index.ts`. + +- [ ] **Step 4: Remove cart-notifications model** + +Delete `features/cart/model/cart-notifications.ts`. + +- [ ] **Step 5: Remove CartSnackbar from App.tsx** + +Remove import and `` from render. + +- [ ] **Step 6: Remove cart-notifications import from features/cart/index.ts** + +Check `features/cart/index.ts` for re-exports of cart-notifications or CartSnackbar. + +- [ ] **Step 7: Remove CartSnackbar test file** + +Delete `CartSnackbar.test.tsx`. + +- [ ] **Step 8: Run lint + test + build** + +```bash +cd client && npm run lint && npm test && npm run build +``` + +- [ ] **Step 9: Commit** + +```bash +git add -A +git commit -m "feat: migrate CartSnackbar to global notification store" +``` diff --git a/docs/superpowers/specs/2026-05-27-refactoring-audit-design.md b/docs/superpowers/specs/2026-05-27-refactoring-audit-design.md new file mode 100644 index 0000000..d9a1361 --- /dev/null +++ b/docs/superpowers/specs/2026-05-27-refactoring-audit-design.md @@ -0,0 +1,201 @@ +# Refactoring Audit — Code Quality Improvements + +Date: 2026-05-27 + +## Overview + +Системный рефакторинг кодовой базы shop (craftshop monorepo) по 5 направлениям: toast-уведомления, пустые catch-блоки, серверное дублирование, клиентское дублирование, обработка ошибок API. + +## Подпроект 1: Система toast-уведомлений + +### Проблема +- Единственный `CartSnackbar` (Effector) только для "товар добавлен в корзину" +- Остальные операции без обратной связи — только inline `` на страницах +- Нет централизованного показа ошибок от API + +### Решение + +**1.1 Effector-стор уведомлений** (`client/src/shared/model/notification.ts`) +```ts +type NotificationType = 'success' | 'error' | 'info' | 'warning' + +interface Notification { + id: string + type: NotificationType + message: string + autoHideDuration?: number +} + +// События +addNotification — добавить (генерирует id + пушит в очередь) +dismissNotification — закрыть по id +dismissAll — закрыть все + +// Стор +$notifications: Notification[] — очередь, макс 3 видимых +``` + +**1.2 Компонент `NotificationStack`** (`client/src/shared/ui/NotificationStack/`) +- Использует MUI `Snackbar` + `Alert` (уже стилизованы через тему) +- Позиция: `bottom: 80px` +- `Slide` transition, auto-hide по таймеру +- Крестик для ручного закрытия +- Не более 3 одновременных уведомлений (остальные в очереди) + +**1.3 Миграция CartSnackbar** +- `cartAdded` событие пишет в `addNotification({ type: 'info', message: 'Товар добавлен в корзину' })` +- Старый `CartSnackbar` удаляется (компонент, стор, тесты) +- `ToggleCartIcon` и `AddToCartButton` — убрать прямой вызов `cartAdded`, заменить на `addNotification` + +**1.4 Интеграция с `useMutationWithToast`** (опционально, см. подпроект 5) + +### Файлы +- Новые: `shared/model/notification.ts`, `shared/ui/NotificationStack/NotificationStack.tsx`, `shared/ui/NotificationStack/index.ts` +- Изменённые: `app/App.tsx` (+ NotificationStack), удаление `features/cart/model/cart-notifications.ts`, `features/cart/ui/CartSnackbar/` +- Тесты: `shared/model/notification.test.ts`, `shared/ui/NotificationStack/NotificationStack.test.tsx` + +--- + +## Подпроект 2: Пустые catch-блоки + +### Проблема +17 мест с `catch { /* ignore */ }` или пустым телом. + +### Решение +Минимальное логирование с контекстом: + +| Файл | Уровень | Сообщение | +|------|---------|-----------| +| `persist-token.ts` (3 места) | `console.warn` | `'[persist-token] Failed to ...'` | +| `theme-controller.tsx` (2 места) | `console.warn` | `'[theme] Failed to ...'` | +| `CookieConsentBanner.tsx` (2 места) | `console.warn` | `'[cookie-consent] Failed to ...'` | +| `SseProvider.tsx` | `console.warn` | `'[sse] Connection error:'` | +| `admin-gallery` (сервер) | `request.log.error` | Контекст операции | +| Остальные серверные | `request.log.error` | Контекст операции | + +### Файлы +Только изменения в существующих файлах. Новых файлов нет. + +--- + +## Подпроект 3: Сервер — дублирование в роутах + +### Проблема +- ~25 мест с ручным try/catch-паттерном +- Дублирование валидации галерейных изображений (POST/PATCH admin/products) +- Дублирование `prisma.order.findFirst({ where: { id, userId } })` в 3 файлах + +### Решение + +**3.1 `asyncHandler`** (`server/src/lib/async-handler.js`) +```js +function asyncHandler(fn) { + return async (request, reply) => { + try { + return await fn(request, reply) + } catch (err) { + request.log.error(err) + const statusCode = err.statusCode || 500 + const message = err.statusCode ? err.message : 'Internal server error' + return reply.code(statusCode).send({ error: message }) + } + } +} +``` + +**3.2 `validateGalleryImages`** (`server/src/lib/validate-gallery-images.js`) +- Проверка существования `galleryImages` в БД +- Проверка наличия resized-версий +- Используется в POST и PATCH admin/products + +**3.3 `findUserOrder`** (`server/src/lib/find-user-order.js`) +- `prisma.order.findFirst({ where: { id, userId }, ... })` с included relations + +### Файлы +- Новые: `server/src/lib/async-handler.js`, `server/src/lib/validate-gallery-images.js`, `server/src/lib/find-user-order.js` +- Изменённые: ~10 server route files + +--- + +## Подпроект 4: Клиент — дублирование + +### Проблема +- 4 копии `useQuery({ queryKey: ['me', 'cart'], ... })` +- Дублирование `orderStatusLabelRu` и `ORDER_STATUS_DATA` + +### Решение + +**4.1 `useCartQuery`** (`client/src/entities/cart/lib/use-cart-query.ts`) +```ts +export function useCartQuery() { + const user = useAuthUser() + return useQuery({ + queryKey: ['me', 'cart'], + queryFn: fetchMyCart, + enabled: Boolean(user), + }) +} +``` +Замена в 4 компонентах. + +**4.2 Дубль статусов** +- `ORDER_STATUS_DATA` — единственный источник +- `orderStatusLabelRu` удалить, импорты переписать на `ORDER_STATUS_DATA` + +### Файлы +- Новые: `entities/cart/lib/use-cart-query.ts` +- Изменённые: `AppHeader.tsx`, `CartPage.tsx`, `CheckoutPage.tsx`, `ToggleCartIcon.tsx`, удаление `order-status-labels.ts` + +--- + +## Подпроект 5: Обработка ошибок API (клиент) + +### Проблема +- Нет централизованного показа ошибок API +- `CheckoutPage` показывает сырое `(error as Error).message` + +### Решение + +**5.1 `useMutationWithToast`** (`client/src/shared/lib/use-mutation-with-toast.ts`) +```ts +function useMutationWithToast(options) { + return useMutation({ + ...options, + onSuccess: (data, ...rest) => { + if (options.successMessage) addNotification({ type: 'success', message: options.successMessage }) + options.onSuccess?.(data, ...rest) + }, + onError: (error, ...rest) => { + addNotification({ type: 'error', message: getApiErrorMessage(error) }) + options.onError?.(error, ...rest) + }, + }) +} +``` + +**5.2 `getApiErrorMessage`** улучшение (`client/src/shared/lib`) +- Если сервер вернул `{ error: string }` — показать его +- Ошибка сети → "Нет соединения с сервером." +- 500 → "Произошла ошибка. Попробуйте позже." +- Остальное → стандартное сообщение + +### Файлы +- Новые: `shared/lib/use-mutation-with-toast.ts` +- Изменённые: `shared/lib/get-api-error-message.ts`, `CheckoutPage.tsx` (исправить отображение ошибки) + +--- + +## Порядок реализации + +Подпроекты независимы и могут выполняться в любом порядке. Рекомендуемый порядок: + +1. **Подпроект 2** (пустые catch) — быстрые и безопасные изменения, хороший разогрев +2. **Подпроект 1** (toast) — база для подпроекта 5, новая функциональность +3. **Подпроект 5** (useMutationWithToast) — строится поверх подпроекта 1 +4. **Подпроект 3** (сервер) — standalone +5. **Подпроект 4** (клиент) — standalone + +## Тестирование + +- Каждый подпроект: `npm run lint` (или `npm run lint:fix`) + `npm test` для своей директории +- Финальная проверка: `cd client && npm run build` (проверка типов) diff --git a/server/src/index.js b/server/src/index.js index eb50e3f..175e33f 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -51,11 +51,12 @@ await fastify.register(cors, { await registerSecurityHeaders(fastify) -fastify.get('/health', async () => { +fastify.get('/health', async (request) => { try { await prisma.$queryRaw`SELECT 1` return { status: 'ok', database: 'connected', uptime: process.uptime() } - } catch { + } catch (err) { + request.log.error({ err }, 'Health check database query failed') return { status: 'degraded', database: 'disconnected', uptime: process.uptime() } } }) @@ -119,7 +120,8 @@ fastify.decorate('authenticate', async function authenticate(request, reply) { request.headers.authorization = `Bearer ${request.query.token}` } await request.jwtVerify() - } catch { + } catch (err) { + request.log.error({ err }, 'JWT verification failed') return reply.code(401).send({ error: 'Не авторизован' }) } }) diff --git a/server/src/plugins/auth.js b/server/src/plugins/auth.js index 7c746d4..794e925 100644 --- a/server/src/plugins/auth.js +++ b/server/src/plugins/auth.js @@ -13,7 +13,8 @@ export function registerAuth(fastify) { try { await request.jwtVerify() - } catch { + } catch (err) { + request.log.error({ err }, '[auth] verifyAdmin failed') return reply.code(401).send({ error: 'Не авторизован' }) } diff --git a/server/src/routes/api/admin-products.js b/server/src/routes/api/admin-products.js index 8ac1893..3992e43 100644 --- a/server/src/routes/api/admin-products.js +++ b/server/src/routes/api/admin-products.js @@ -260,7 +260,8 @@ export async function registerAdminProductRoutes(fastify) { try { await prisma.product.delete({ where: { id } }) reply.code(204).send() - } catch { + } catch (err) { + request.log.error({ err }, '[admin-products] Operation failed') reply.code(404).send({ error: 'Товар не найден' }) } }) diff --git a/server/src/routes/api/admin-users.js b/server/src/routes/api/admin-users.js index 9dd717b..46f4abf 100644 --- a/server/src/routes/api/admin-users.js +++ b/server/src/routes/api/admin-users.js @@ -160,7 +160,8 @@ export async function registerAdminUserRoutes(fastify) { try { await prisma.user.delete({ where: { id } }) reply.code(204).send() - } catch { + } catch (err) { + request.log.error({ err }, '[admin-users] Operation failed') reply.code(404).send({ error: 'Пользователь не найден' }) } }) diff --git a/server/src/routes/api/public-reviews.js b/server/src/routes/api/public-reviews.js index ebf81c5..ddd9701 100644 --- a/server/src/routes/api/public-reviews.js +++ b/server/src/routes/api/public-reviews.js @@ -144,7 +144,8 @@ export async function registerPublicReviewRoutes(fastify) { }, }) return reply.code(201).send({ item: created }) - } catch { + } catch (err) { + request.log.error({ err }, 'Failed to create review (possible duplicate)') return reply.code(409).send({ error: 'Вы уже оставляли отзыв на этот товар' }) } }) diff --git a/server/src/routes/sse.js b/server/src/routes/sse.js index ac6785d..33eb514 100644 --- a/server/src/routes/sse.js +++ b/server/src/routes/sse.js @@ -119,7 +119,8 @@ export async function registerSseRoutes(fastify) { if (closed) return try { reply.raw.write(chunk) - } catch { + } catch (err) { + request.log.error({ err }, '[sse] safeWrite failed') closed = true cleanUp() } diff --git a/server/src/routes/user-payments.js b/server/src/routes/user-payments.js index 643d661..3f3a59f 100644 --- a/server/src/routes/user-payments.js +++ b/server/src/routes/user-payments.js @@ -141,7 +141,8 @@ export async function registerUserPaymentRoutes(fastify) { } return { status: ykPayment.status, paid: ykPayment.paid } - } catch { + } catch (err) { + request.log.error({ err }, '[user-payments] Operation failed') return { status: payment.status, paid: payment.status === 'succeeded' } } }) diff --git a/server/src/routes/webhook-yookassa.js b/server/src/routes/webhook-yookassa.js index 6362de5..4d0a705 100644 --- a/server/src/routes/webhook-yookassa.js +++ b/server/src/routes/webhook-yookassa.js @@ -7,7 +7,8 @@ export async function registerYookassaWebhookRoute(fastify) { let body try { body = typeof request.body === 'string' ? JSON.parse(request.body) : request.body - } catch { + } catch (err) { + request.log.error({ err }, 'Failed to parse webhook JSON body') return reply.code(400).send({ error: 'Invalid JSON body' }) } From e2d4423e2e9e5b9e8ceea9ca0ee32982c8bb0f43 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:07:55 +0500 Subject: [PATCH 06/31] feat: add notification store and NotificationStack component --- .../model/__tests__/notification.test.ts | 97 +++++++++++++++++++ client/src/shared/model/notification.ts | 35 +++++++ .../NotificationStack.test.tsx | 36 +++++++ .../NotificationStack/NotificationStack.tsx | 47 +++++++++ .../src/shared/ui/NotificationStack/index.ts | 1 + 5 files changed, 216 insertions(+) create mode 100644 client/src/shared/model/__tests__/notification.test.ts create mode 100644 client/src/shared/model/notification.ts create mode 100644 client/src/shared/ui/NotificationStack/NotificationStack.test.tsx create mode 100644 client/src/shared/ui/NotificationStack/NotificationStack.tsx create mode 100644 client/src/shared/ui/NotificationStack/index.ts diff --git a/client/src/shared/model/__tests__/notification.test.ts b/client/src/shared/model/__tests__/notification.test.ts new file mode 100644 index 0000000..953ecf0 --- /dev/null +++ b/client/src/shared/model/__tests__/notification.test.ts @@ -0,0 +1,97 @@ +import { allSettled, fork } from 'effector' +import { describe, it, expect } from 'vitest' +import { $notifications, addNotification, dismissNotification, dismissAll } from '../notification' + +describe('notification store', () => { + it('starts empty', () => { + const scope = fork() + expect(scope.getState($notifications)).toEqual([]) + }) + + it('adds a notification with generated id', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'info', message: 'test' }, + }) + const list = scope.getState($notifications) + expect(list).toHaveLength(1) + expect(list[0].id).toEqual(expect.any(String)) + expect(list[0].message).toBe('test') + expect(list[0].type).toBe('info') + }) + + it('caps at 3 visible notifications', async () => { + const scope = fork() + for (let i = 0; i < 5; i++) { + await allSettled(addNotification, { + scope, + params: { type: 'info', message: `msg-${i}` }, + }) + } + const list = scope.getState($notifications) + expect(list).toHaveLength(3) + expect(list[0].message).toBe('msg-2') + expect(list[2].message).toBe('msg-4') + }) + + it('dismisses notification by id', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'info', message: 'test' }, + }) + const [{ id }] = scope.getState($notifications) + await allSettled(dismissNotification, { + scope, + params: id, + }) + expect(scope.getState($notifications)).toEqual([]) + }) + + it('clears all on dismissAll', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'info', message: 'test' }, + }) + await allSettled(dismissAll, { scope }) + expect(scope.getState($notifications)).toEqual([]) + }) + + it('defaults autoHideDuration to 4000 for info', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'info', message: 'test' }, + }) + expect(scope.getState($notifications)[0].autoHideDuration).toBe(4000) + }) + + it('defaults autoHideDuration to 4000 for success', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'success', message: 'test' }, + }) + expect(scope.getState($notifications)[0].autoHideDuration).toBe(4000) + }) + + it('defaults autoHideDuration to 4000 for warning', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'warning', message: 'test' }, + }) + expect(scope.getState($notifications)[0].autoHideDuration).toBe(4000) + }) + + it('defaults autoHideDuration to 6000 for error', async () => { + const scope = fork() + await allSettled(addNotification, { + scope, + params: { type: 'error', message: 'test' }, + }) + expect(scope.getState($notifications)[0].autoHideDuration).toBe(6000) + }) +}) diff --git a/client/src/shared/model/notification.ts b/client/src/shared/model/notification.ts new file mode 100644 index 0000000..15e08cf --- /dev/null +++ b/client/src/shared/model/notification.ts @@ -0,0 +1,35 @@ +import { createEvent, createStore } from 'effector' + +type NotificationType = 'success' | 'error' | 'info' | 'warning' + +export interface Notification { + id: string + type: NotificationType + message: string + autoHideDuration?: number +} + +const MAX_VISIBLE = 3 +let nextId = 1 + +export const addNotification = createEvent<{ + type: NotificationType + message: string + autoHideDuration?: number +}>() + +export const dismissNotification = createEvent() +export const dismissAll = createEvent() + +export const $notifications = createStore([]) + .on(addNotification, (state, { type, message, autoHideDuration }) => { + const notification: Notification = { + id: String(nextId++), + type, + message, + autoHideDuration: autoHideDuration ?? (type === 'error' ? 6000 : 4000), + } + return [...state, notification].slice(-MAX_VISIBLE) + }) + .on(dismissNotification, (state, id) => state.filter((n) => n.id !== id)) + .reset(dismissAll) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx new file mode 100644 index 0000000..4dd63eb --- /dev/null +++ b/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx @@ -0,0 +1,36 @@ +import { render, screen, fireEvent, waitFor } from '@testing-library/react' +import { describe, it, expect, beforeEach } from 'vitest' +import { addNotification, dismissAll } from '../../model/notification' +import { NotificationStack } from './NotificationStack' + +beforeEach(() => { + dismissAll() +}) + +describe('NotificationStack', () => { + it('renders nothing when empty', () => { + const { container } = render() + expect(container.firstChild).toBeNull() + }) + + it('renders notification when added', async () => { + render() + addNotification({ type: 'info', message: 'Hello' }) + await waitFor(() => { + expect(screen.getByText('Hello')).toBeInTheDocument() + }) + }) + + it('dismiss button works', async () => { + render() + addNotification({ type: 'info', message: 'Dismiss me' }) + await waitFor(() => { + expect(screen.getByText('Dismiss me')).toBeInTheDocument() + }) + + fireEvent.click(screen.getByTestId('CloseIcon')) + await waitFor(() => { + expect(screen.queryByText('Dismiss me')).not.toBeInTheDocument() + }) + }) +}) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx new file mode 100644 index 0000000..d7b8e4a --- /dev/null +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -0,0 +1,47 @@ +import { useUnit } from 'effector-react' +import { Snackbar, Alert, Stack, IconButton } from '@mui/material' +import CloseIcon from '@mui/icons-material/Close' +import { $notifications, dismissNotification } from '../../model/notification' + +export function NotificationStack() { + const notifications = useUnit($notifications) + + if (notifications.length === 0) return null + + return ( + + {notifications.map((n) => ( + dismissNotification(n.id)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} + > + dismissNotification(n.id)}> + + + } + > + {n.message} + + + ))} + + ) +} diff --git a/client/src/shared/ui/NotificationStack/index.ts b/client/src/shared/ui/NotificationStack/index.ts new file mode 100644 index 0000000..88522fb --- /dev/null +++ b/client/src/shared/ui/NotificationStack/index.ts @@ -0,0 +1 @@ +export { NotificationStack } from './NotificationStack' From e173977daf133fd323dd08be61fd0f97c5eac685 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:08:15 +0500 Subject: [PATCH 07/31] feat: integrate NotificationStack into App --- client/src/app/App.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/app/App.tsx b/client/src/app/App.tsx index c6feb8e..e54e482 100644 --- a/client/src/app/App.tsx +++ b/client/src/app/App.tsx @@ -2,6 +2,7 @@ import { BrowserRouter } from 'react-router-dom' import { AppProviders } from '@/app/providers/AppProviders' import { AppRoutes } from '@/app/routes' import { CartSnackbar } from '@/shared/ui/CartSnackbar' +import { NotificationStack } from '@/shared/ui/NotificationStack' import { ErrorBoundary } from '@/shared/ui/ErrorBoundary' import { NoiseOverlay } from '@/shared/ui/NoiseOverlay' @@ -13,6 +14,7 @@ export function App() { + From 30bb25c4168270268cdce876d7693d7959524cf6 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:10:01 +0500 Subject: [PATCH 08/31] feat: migrate CartSnackbar to global notification store --- client/src/app/App.tsx | 2 - .../cart/add-to-cart/ui/AddToCartButton.tsx | 4 +- .../ui/__tests__/AddToCartButton.test.tsx | 8 +- .../toggle-cart-icon/ui/ToggleCartIcon.tsx | 4 +- .../ui/__tests__/ToggleCartIcon.test.tsx | 12 +-- .../__tests__/cart-notifications.test.ts | 23 ----- client/src/shared/model/cart-notifications.ts | 8 -- client/src/shared/ui/CartSnackbar.tsx | 90 ------------------- .../shared/ui/__tests__/CartSnackbar.test.tsx | 69 -------------- 9 files changed, 14 insertions(+), 206 deletions(-) delete mode 100644 client/src/shared/model/__tests__/cart-notifications.test.ts delete mode 100644 client/src/shared/model/cart-notifications.ts delete mode 100644 client/src/shared/ui/CartSnackbar.tsx delete mode 100644 client/src/shared/ui/__tests__/CartSnackbar.test.tsx diff --git a/client/src/app/App.tsx b/client/src/app/App.tsx index e54e482..64654c5 100644 --- a/client/src/app/App.tsx +++ b/client/src/app/App.tsx @@ -1,7 +1,6 @@ import { BrowserRouter } from 'react-router-dom' import { AppProviders } from '@/app/providers/AppProviders' import { AppRoutes } from '@/app/routes' -import { CartSnackbar } from '@/shared/ui/CartSnackbar' import { NotificationStack } from '@/shared/ui/NotificationStack' import { ErrorBoundary } from '@/shared/ui/ErrorBoundary' import { NoiseOverlay } from '@/shared/ui/NoiseOverlay' @@ -13,7 +12,6 @@ export function App() { - diff --git a/client/src/features/cart/add-to-cart/ui/AddToCartButton.tsx b/client/src/features/cart/add-to-cart/ui/AddToCartButton.tsx index a799881..d68cf17 100644 --- a/client/src/features/cart/add-to-cart/ui/AddToCartButton.tsx +++ b/client/src/features/cart/add-to-cart/ui/AddToCartButton.tsx @@ -4,7 +4,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { addToCart } from '@/entities/cart/api/cart-api' import { $user } from '@/shared/model/auth' -import { cartAdded } from '@/shared/model/cart-notifications' +import { addNotification } from '@/shared/model/notification' type Props = { productId: string @@ -21,7 +21,7 @@ export function AddToCartButton(props: Props) { mutationFn: () => addToCart({ productId, qty }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['me', 'cart'] }) - cartAdded() + addNotification({ type: 'info', message: 'Товар добавлен в корзину' }) }, }) diff --git a/client/src/features/cart/add-to-cart/ui/__tests__/AddToCartButton.test.tsx b/client/src/features/cart/add-to-cart/ui/__tests__/AddToCartButton.test.tsx index ee2050d..c1f16e2 100644 --- a/client/src/features/cart/add-to-cart/ui/__tests__/AddToCartButton.test.tsx +++ b/client/src/features/cart/add-to-cart/ui/__tests__/AddToCartButton.test.tsx @@ -1,7 +1,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { render, screen, fireEvent } from '@testing-library/react' import { describe, it, expect, vi, beforeEach } from 'vitest' -import * as notifications from '@/shared/model/cart-notifications' +import * as notifications from '@/shared/model/notification' import { AddToCartButton } from '../AddToCartButton' vi.mock('@/entities/cart/api/cart-api', () => ({ @@ -21,8 +21,8 @@ describe('AddToCartButton', () => { qc.clear() }) - it('calls cartAdded after successful add', async () => { - const spy = vi.spyOn(notifications, 'cartAdded') + it('calls addNotification after successful add', async () => { + const spy = vi.spyOn(notifications, 'addNotification') render( @@ -32,7 +32,7 @@ describe('AddToCartButton', () => { fireEvent.click(screen.getByRole('button', { name: /в корзину/i })) await vi.waitFor(() => { - expect(spy).toHaveBeenCalled() + expect(spy).toHaveBeenCalledWith({ type: 'info', message: 'Товар добавлен в корзину' }) }) }) }) diff --git a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx index af6ef01..fe51801 100644 --- a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx +++ b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx @@ -6,7 +6,7 @@ import { ShoppingCart } from 'lucide-react' import { useNavigate } from 'react-router-dom' import { addToCart, fetchMyCart, removeCartItem } from '@/entities/cart/api/cart-api' import { $user } from '@/shared/model/auth' -import { cartAdded } from '@/shared/model/cart-notifications' +import { addNotification } from '@/shared/model/notification' export function ToggleCartIcon(props: { productId: string @@ -31,7 +31,7 @@ export function ToggleCartIcon(props: { mutationFn: () => addToCart({ productId, qty: 1 }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['me', 'cart'] }) - cartAdded() + addNotification({ type: 'info', message: 'Товар добавлен в корзину' }) }, }) diff --git a/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx b/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx index d90671b..225e153 100644 --- a/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx +++ b/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx @@ -3,7 +3,7 @@ import { render, screen, fireEvent } from '@testing-library/react' import { MemoryRouter } from 'react-router-dom' import { describe, it, expect, vi, beforeEach } from 'vitest' import * as api from '@/entities/cart/api/cart-api' -import * as notifications from '@/shared/model/cart-notifications' +import * as notifications from '@/shared/model/notification' import { ToggleCartIcon } from '../ToggleCartIcon' vi.mock('@/entities/cart/api/cart-api', () => ({ @@ -25,8 +25,8 @@ describe('ToggleCartIcon', () => { qc.clear() }) - it('calls cartAdded after successful add', async () => { - const spy = vi.spyOn(notifications, 'cartAdded') + it('calls addNotification after successful add', async () => { + const spy = vi.spyOn(notifications, 'addNotification') render( @@ -38,15 +38,15 @@ describe('ToggleCartIcon', () => { fireEvent.click(screen.getByRole('button', { name: /в корзину/i })) await vi.waitFor(() => { - expect(spy).toHaveBeenCalled() + expect(spy).toHaveBeenCalledWith({ type: 'info', message: 'Товар добавлен в корзину' }) }) }) - it('does not call cartAdded on remove', async () => { + it('does not call addNotification on remove', async () => { vi.mocked(api.fetchMyCart).mockResolvedValueOnce({ items: [{ id: 'cart-1', qty: 1, product: { id: 'test-product' } as never }], }) - const spy = vi.spyOn(notifications, 'cartAdded') + const spy = vi.spyOn(notifications, 'addNotification') render( diff --git a/client/src/shared/model/__tests__/cart-notifications.test.ts b/client/src/shared/model/__tests__/cart-notifications.test.ts deleted file mode 100644 index 1c8f1c9..0000000 --- a/client/src/shared/model/__tests__/cart-notifications.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { allSettled, fork } from 'effector' -import { describe, it, expect } from 'vitest' -import { $cartSnackOpen, cartAdded, cartDismissed } from '../cart-notifications' - -describe('cart-notifications store', () => { - it('opens on cartAdded', async () => { - const scope = fork() - await allSettled(cartAdded, { scope }) - expect(scope.getState($cartSnackOpen)).toBe(true) - }) - - it('closes on cartDismissed', async () => { - const scope = fork() - await allSettled(cartAdded, { scope }) - await allSettled(cartDismissed, { scope }) - expect(scope.getState($cartSnackOpen)).toBe(false) - }) - - it('starts closed by default', () => { - const scope = fork() - expect(scope.getState($cartSnackOpen)).toBe(false) - }) -}) diff --git a/client/src/shared/model/cart-notifications.ts b/client/src/shared/model/cart-notifications.ts deleted file mode 100644 index 64f48f0..0000000 --- a/client/src/shared/model/cart-notifications.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createEvent, createStore } from 'effector' - -export const cartAdded = createEvent() -export const cartDismissed = createEvent() - -export const $cartSnackOpen = createStore(false) - .on(cartAdded, () => true) - .on(cartDismissed, () => false) diff --git a/client/src/shared/ui/CartSnackbar.tsx b/client/src/shared/ui/CartSnackbar.tsx deleted file mode 100644 index 27b673f..0000000 --- a/client/src/shared/ui/CartSnackbar.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import Alert from '@mui/material/Alert' -import Button from '@mui/material/Button' -import Snackbar from '@mui/material/Snackbar' -import { useUnit } from 'effector-react' -import { useNavigate } from 'react-router-dom' -import { $cartSnackOpen, cartDismissed } from '@/shared/model/cart-notifications' - -export function CartSnackbar() { - const open = useUnit($cartSnackOpen) - const navigate = useNavigate() - - const handleClose = (_event: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') return - cartDismissed() - } - - const handleGoToCart = () => { - cartDismissed() - navigate('/cart') - } - - return ( - - - Перейти в корзину - - } - > - Товар добавлен в корзину - - - ) -} diff --git a/client/src/shared/ui/__tests__/CartSnackbar.test.tsx b/client/src/shared/ui/__tests__/CartSnackbar.test.tsx deleted file mode 100644 index b163e27..0000000 --- a/client/src/shared/ui/__tests__/CartSnackbar.test.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { render, screen, fireEvent, act } from '@testing-library/react' -import { MemoryRouter } from 'react-router-dom' -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { cartAdded, cartDismissed } from '@/shared/model/cart-notifications' -import { CartSnackbar } from '@/shared/ui/CartSnackbar' - -const navigateMock = vi.fn() - -vi.mock('react-router-dom', async (importOriginal) => { - const mod = await importOriginal() - return { ...mod, useNavigate: () => navigateMock } -}) - -beforeEach(() => { - navigateMock.mockClear() -}) - -afterEach(() => { - vi.useRealTimers() -}) - -function renderWithRouter() { - render( - - - , - ) -} - -describe('CartSnackbar', () => { - it('is hidden when store is false', () => { - cartDismissed() - renderWithRouter() - expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument() - }) - - it('shows snackbar when cartAdded is fired', () => { - renderWithRouter() - cartAdded() - expect(screen.getByText(/товар добавлен/i)).toBeInTheDocument() - expect(screen.getByRole('button', { name: /перейти в корзину/i })).toBeInTheDocument() - }) - - it('closes on dismiss button click', () => { - renderWithRouter() - cartAdded() - const closeBtn = screen.getByLabelText(/закрыть/i) - fireEvent.click(closeBtn) - expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument() - }) - - it('auto-closes after 4 seconds', () => { - vi.useFakeTimers() - renderWithRouter() - cartAdded() - act(() => { - vi.advanceTimersByTime(4000) - }) - expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument() - }) - - it('navigates to /cart and closes on "Перейти в корзину" click', () => { - renderWithRouter() - cartAdded() - fireEvent.click(screen.getByRole('button', { name: /перейти в корзину/i })) - expect(navigateMock).toHaveBeenCalledWith('/cart') - expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument() - }) -}) From 9502a0c55069c9d8f3c0a2128851cea5a4532076 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:19:08 +0500 Subject: [PATCH 09/31] fix: wrap dismissNotification with useUnit in NotificationStack for scope isolation; fix test selectors --- .../NotificationStack.test.tsx | 79 +++++++++++++------ .../NotificationStack/NotificationStack.tsx | 3 +- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx index 4dd63eb..b84798d 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.test.tsx @@ -1,36 +1,71 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react' -import { describe, it, expect, beforeEach } from 'vitest' -import { addNotification, dismissAll } from '../../model/notification' +import { allSettled, fork } from 'effector' +import { Provider } from 'effector-react' +import { describe, it, expect, afterEach } from 'vitest' +import { addNotification, dismissAll, $notifications } from '../../model/notification' import { NotificationStack } from './NotificationStack' -beforeEach(() => { - dismissAll() -}) - describe('NotificationStack', () => { + afterEach(() => { + dismissAll() + }) + + function createTestScope() { + return fork() + } + + function renderWithScope(scope: ReturnType) { + return render( + + + , + ) + } + it('renders nothing when empty', () => { - const { container } = render() - expect(container.firstChild).toBeNull() + const scope = createTestScope() + const { container } = renderWithScope(scope) + expect(container.textContent).toBe('') }) - it('renders notification when added', async () => { - render() - addNotification({ type: 'info', message: 'Hello' }) + it('renders a success notification with check icon', async () => { + const scope = createTestScope() + await allSettled(addNotification, { scope, params: { type: 'success', message: 'Success!' } }) + renderWithScope(scope) + expect(screen.getByText('Success!')).toBeDefined() + }) + + it('renders error alert severity', async () => { + const scope = createTestScope() + await allSettled(addNotification, { scope, params: { type: 'error', message: 'Error!' } }) + renderWithScope(scope) + const alert = screen.getByRole('alert') + expect(alert).toBeDefined() + }) + + it('dismisses on close button click', async () => { + const scope = createTestScope() + await allSettled(addNotification, { scope, params: { type: 'info', message: 'Dismiss me' } }) + renderWithScope(scope) + + const closeBtn = screen.getByRole('button') + fireEvent.click(closeBtn) + await waitFor(() => { - expect(screen.getByText('Hello')).toBeInTheDocument() + const state = scope.getState($notifications) + expect(state).toHaveLength(0) }) }) - it('dismiss button works', async () => { - render() - addNotification({ type: 'info', message: 'Dismiss me' }) - await waitFor(() => { - expect(screen.getByText('Dismiss me')).toBeInTheDocument() - }) + it('renders multiple notifications up to 3', async () => { + const scope = createTestScope() + await allSettled(addNotification, { scope, params: { type: 'info', message: 'A' } }) + await allSettled(addNotification, { scope, params: { type: 'info', message: 'B' } }) + await allSettled(addNotification, { scope, params: { type: 'info', message: 'C' } }) + renderWithScope(scope) - fireEvent.click(screen.getByTestId('CloseIcon')) - await waitFor(() => { - expect(screen.queryByText('Dismiss me')).not.toBeInTheDocument() - }) + expect(screen.getByText('A')).toBeDefined() + expect(screen.getByText('B')).toBeDefined() + expect(screen.getByText('C')).toBeDefined() }) }) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index d7b8e4a..696c0f0 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -1,10 +1,11 @@ import { useUnit } from 'effector-react' import { Snackbar, Alert, Stack, IconButton } from '@mui/material' import CloseIcon from '@mui/icons-material/Close' -import { $notifications, dismissNotification } from '../../model/notification' +import { $notifications, dismissNotification as dismissNotificationEvent } from '../../model/notification' export function NotificationStack() { const notifications = useUnit($notifications) + const dismissNotification = useUnit(dismissNotificationEvent) if (notifications.length === 0) return null From 39286f0fe0900c87a34ea676c34e1024d82d66df Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:21:48 +0500 Subject: [PATCH 10/31] feat: improve getApiErrorMessage with user-friendly messages --- .../__tests__/get-api-error-message.test.ts | 35 +++++++++++++++++++ .../src/shared/lib/get-api-error-message.ts | 29 +++++++++++---- 2 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 client/src/shared/lib/__tests__/get-api-error-message.test.ts diff --git a/client/src/shared/lib/__tests__/get-api-error-message.test.ts b/client/src/shared/lib/__tests__/get-api-error-message.test.ts new file mode 100644 index 0000000..08e1660 --- /dev/null +++ b/client/src/shared/lib/__tests__/get-api-error-message.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest' +import { getApiErrorMessage } from '../get-api-error-message' + +describe('getApiErrorMessage', () => { + it('returns server error message from response.data.error', () => { + const error = { + isAxiosError: true, + response: { data: { error: 'Товар не найден' }, status: 404 }, + } + expect(getApiErrorMessage(error)).toBe('Товар не найден') + }) + + it('returns network error message when no response', () => { + const error = { isAxiosError: true, response: undefined } + expect(getApiErrorMessage(error)).toBe('Нет соединения с сервером. Проверьте подключение к интернету.') + }) + + it('returns server error message for 5xx status', () => { + const error = { isAxiosError: true, response: { data: {}, status: 500 } } + expect(getApiErrorMessage(error)).toBe('Произошла ошибка. Попробуйте повторить позже.') + }) + + it('returns error message for Error instance', () => { + expect(getApiErrorMessage(new Error('Something broke'))).toBe('Something broke') + }) + + it('returns unknown error for falsy input', () => { + expect(getApiErrorMessage(null)).toBe('Произошла неизвестная ошибка') + expect(getApiErrorMessage(undefined)).toBe('Произошла неизвестная ошибка') + }) + + it('returns unknown error for random object', () => { + expect(getApiErrorMessage({ foo: 'bar' })).toBe('Произошла неизвестная ошибка') + }) +}) diff --git a/client/src/shared/lib/get-api-error-message.ts b/client/src/shared/lib/get-api-error-message.ts index c68f6a0..519ab32 100644 --- a/client/src/shared/lib/get-api-error-message.ts +++ b/client/src/shared/lib/get-api-error-message.ts @@ -1,8 +1,23 @@ -export function getApiErrorMessage(err: unknown): string | null { - if (!err || typeof err !== 'object') return null - const anyErr = err as Record - const response = anyErr.response as Record | undefined - const data = response?.data as Record | undefined - const msg = data?.error - return typeof msg === 'string' ? msg : null +import { isAxiosError } from 'axios' + +export function getApiErrorMessage(error: unknown): string { + if (!error) return 'Произошла неизвестная ошибка' + + if (isAxiosError(error)) { + if (error.response?.data?.error && typeof error.response.data.error === 'string') { + return error.response.data.error + } + if (!error.response) { + return 'Нет соединения с сервером. Проверьте подключение к интернету.' + } + if (error.response.status >= 500) { + return 'Произошла ошибка. Попробуйте повторить позже.' + } + } + + if (error instanceof Error) { + return error.message + } + + return 'Произошла неизвестная ошибка' } From 4ca04878cbf4189ff285600dfb353212d44193e7 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:24:09 +0500 Subject: [PATCH 11/31] feat: add useMutationWithToast wrapper --- .../use-mutation-with-toast.test.tsx | 68 +++++++++++++++++++ .../src/shared/lib/use-mutation-with-toast.ts | 32 +++++++++ 2 files changed, 100 insertions(+) create mode 100644 client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx create mode 100644 client/src/shared/lib/use-mutation-with-toast.ts diff --git a/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx new file mode 100644 index 0000000..7b07073 --- /dev/null +++ b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx @@ -0,0 +1,68 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { renderHook, waitFor } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { useMutationWithToast } from '../use-mutation-with-toast' +import { addNotification } from '../../model/notification' + +vi.mock('../../model/notification', () => ({ + addNotification: vi.fn(), +})) + +function createWrapper() { + const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + return ({ children }: { children: React.ReactNode }) => ( + {children} + ) +} + +describe('useMutationWithToast', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('shows success notification on success with successMessage', async () => { + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const { result } = renderHook(() => useMutationWithToast({ mutationFn, successMessage: 'Done!' }), { + wrapper: createWrapper(), + }) + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + expect(addNotification).toHaveBeenCalledWith({ type: 'success', message: 'Done!' }) + }) + + it('does NOT show success notification without successMessage', async () => { + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const { result } = renderHook(() => useMutationWithToast({ mutationFn }), { wrapper: createWrapper() }) + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + expect(addNotification).not.toHaveBeenCalled() + }) + + it('shows error notification on mutation error', async () => { + const mutationFn = vi.fn().mockRejectedValue(new Error('Boom')) + const { result } = renderHook(() => useMutationWithToast({ mutationFn }), { wrapper: createWrapper() }) + result.current.mutate() + await waitFor(() => expect(result.current.isError).toBe(true)) + expect(addNotification).toHaveBeenCalledWith({ type: 'error', message: 'Boom' }) + }) + + it('calls user-provided onSuccess callback', async () => { + const onSuccess = vi.fn() + const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const { result } = renderHook(() => useMutationWithToast({ mutationFn, onSuccess, successMessage: 'OK' }), { + wrapper: createWrapper(), + }) + result.current.mutate() + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + expect(onSuccess).toHaveBeenCalled() + }) + + it('calls user-provided onError callback', async () => { + const onError = vi.fn() + const mutationFn = vi.fn().mockRejectedValue(new Error('fail')) + const { result } = renderHook(() => useMutationWithToast({ mutationFn, onError }), { wrapper: createWrapper() }) + result.current.mutate() + await waitFor(() => expect(result.current.isError).toBe(true)) + expect(onError).toHaveBeenCalled() + }) +}) diff --git a/client/src/shared/lib/use-mutation-with-toast.ts b/client/src/shared/lib/use-mutation-with-toast.ts new file mode 100644 index 0000000..e2a3e04 --- /dev/null +++ b/client/src/shared/lib/use-mutation-with-toast.ts @@ -0,0 +1,32 @@ +import { useMutation, type UseMutationOptions } from '@tanstack/react-query' +import { addNotification } from '../model/notification' +import { getApiErrorMessage } from './get-api-error-message' + +type MutationWithToastOptions = UseMutationOptions< + TData, + TError, + TVariables, + TContext +> & { + successMessage?: string +} + +export function useMutationWithToast( + options: MutationWithToastOptions, +) { + const { successMessage, onSuccess, onError, ...mutationOptions } = options + + return useMutation({ + ...mutationOptions, + onSuccess: (data, variables, context) => { + if (successMessage) { + addNotification({ type: 'success', message: successMessage }) + } + onSuccess?.(data, variables, context) + }, + onError: (error, variables, context) => { + addNotification({ type: 'error', message: getApiErrorMessage(error) }) + onError?.(error, variables, context) + }, + }) +} From 7642edc15458bc31292d47aa00b6618a6b3348ea Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:30:27 +0500 Subject: [PATCH 12/31] fix: use getApiErrorMessage in CheckoutPage for user-friendly error display --- client/src/pages/checkout/ui/CheckoutPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/pages/checkout/ui/CheckoutPage.tsx b/client/src/pages/checkout/ui/CheckoutPage.tsx index 40ba74f..fa0edb2 100644 --- a/client/src/pages/checkout/ui/CheckoutPage.tsx +++ b/client/src/pages/checkout/ui/CheckoutPage.tsx @@ -21,6 +21,7 @@ import { createOrder } from '@/entities/order/api/order-api' import { fetchMyAddresses } from '@/entities/user/api/address-api' import { DELIVERY_CARRIER_OPTIONS, type DeliveryCarrierCode } from '@/shared/constants/delivery-carrier' import { formatPriceRub } from '@/shared/lib/format-price' +import { getApiErrorMessage } from '@/shared/lib/get-api-error-message' import { $user } from '@/shared/model/auth' export function CheckoutPage() { @@ -263,7 +264,7 @@ export function CheckoutPage() { Создать заказ - {createMut.isError && {(createMut.error as Error).message}} + {createMut.isError && {getApiErrorMessage(createMut.error)}}
) From d254c3c8137a46748332e2a8467721569094ab26 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:30:42 +0500 Subject: [PATCH 13/31] fix: adapt useMutationWithToast to react-query v5 callback signatures --- .../use-mutation-with-toast.test.tsx | 26 ++++++++++--------- .../src/shared/lib/use-mutation-with-toast.ts | 18 ++++++------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx index 7b07073..7cddc99 100644 --- a/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx +++ b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx @@ -21,47 +21,49 @@ describe('useMutationWithToast', () => { }) it('shows success notification on success with successMessage', async () => { - const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const mutationFn = (): Promise<{ ok: boolean }> => Promise.resolve({ ok: true }) const { result } = renderHook(() => useMutationWithToast({ mutationFn, successMessage: 'Done!' }), { wrapper: createWrapper(), }) - result.current.mutate() + ;(result.current.mutate as () => void)() await waitFor(() => expect(result.current.isSuccess).toBe(true)) expect(addNotification).toHaveBeenCalledWith({ type: 'success', message: 'Done!' }) }) it('does NOT show success notification without successMessage', async () => { - const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const mutationFn = (): Promise<{ ok: boolean }> => Promise.resolve({ ok: true }) const { result } = renderHook(() => useMutationWithToast({ mutationFn }), { wrapper: createWrapper() }) - result.current.mutate() + ;(result.current.mutate as () => void)() await waitFor(() => expect(result.current.isSuccess).toBe(true)) expect(addNotification).not.toHaveBeenCalled() }) it('shows error notification on mutation error', async () => { - const mutationFn = vi.fn().mockRejectedValue(new Error('Boom')) + const err = new Error('Boom') + const mutationFn = (): Promise => Promise.reject(err) const { result } = renderHook(() => useMutationWithToast({ mutationFn }), { wrapper: createWrapper() }) - result.current.mutate() + ;(result.current.mutate as () => void)() await waitFor(() => expect(result.current.isError).toBe(true)) expect(addNotification).toHaveBeenCalledWith({ type: 'error', message: 'Boom' }) }) it('calls user-provided onSuccess callback', async () => { - const onSuccess = vi.fn() - const mutationFn = vi.fn().mockResolvedValue({ ok: true }) + const onSuccess: (data: { ok: boolean }, variables: void, onMutateResult: unknown, mutationContext: unknown) => void = vi.fn() + const mutationFn = (): Promise<{ ok: boolean }> => Promise.resolve({ ok: true }) const { result } = renderHook(() => useMutationWithToast({ mutationFn, onSuccess, successMessage: 'OK' }), { wrapper: createWrapper(), }) - result.current.mutate() + ;(result.current.mutate as () => void)() await waitFor(() => expect(result.current.isSuccess).toBe(true)) expect(onSuccess).toHaveBeenCalled() }) it('calls user-provided onError callback', async () => { - const onError = vi.fn() - const mutationFn = vi.fn().mockRejectedValue(new Error('fail')) + const onError: (error: Error, variables: void, onMutateResult: unknown, mutationContext: unknown) => void = vi.fn() + const err = new Error('fail') + const mutationFn = (): Promise => Promise.reject(err) const { result } = renderHook(() => useMutationWithToast({ mutationFn, onError }), { wrapper: createWrapper() }) - result.current.mutate() + ;(result.current.mutate as () => void)() await waitFor(() => expect(result.current.isError).toBe(true)) expect(onError).toHaveBeenCalled() }) diff --git a/client/src/shared/lib/use-mutation-with-toast.ts b/client/src/shared/lib/use-mutation-with-toast.ts index e2a3e04..ccb98f9 100644 --- a/client/src/shared/lib/use-mutation-with-toast.ts +++ b/client/src/shared/lib/use-mutation-with-toast.ts @@ -1,32 +1,32 @@ -import { useMutation, type UseMutationOptions } from '@tanstack/react-query' +import { useMutation, type MutationFunctionContext, type UseMutationOptions } from '@tanstack/react-query' import { addNotification } from '../model/notification' import { getApiErrorMessage } from './get-api-error-message' -type MutationWithToastOptions = UseMutationOptions< +type MutationWithToastOptions = UseMutationOptions< TData, TError, TVariables, - TContext + TOnMutateResult > & { successMessage?: string } -export function useMutationWithToast( - options: MutationWithToastOptions, +export function useMutationWithToast( + options: MutationWithToastOptions, ) { const { successMessage, onSuccess, onError, ...mutationOptions } = options return useMutation({ ...mutationOptions, - onSuccess: (data, variables, context) => { + onSuccess: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult, mutationContext: MutationFunctionContext) => { if (successMessage) { addNotification({ type: 'success', message: successMessage }) } - onSuccess?.(data, variables, context) + onSuccess?.(data, variables, onMutateResult, mutationContext) }, - onError: (error, variables, context) => { + onError: (error: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, mutationContext: MutationFunctionContext) => { addNotification({ type: 'error', message: getApiErrorMessage(error) }) - onError?.(error, variables, context) + onError?.(error, variables, onMutateResult, mutationContext) }, }) } From 36e75ab24a01ba32e355c7cf42a55c1bb5f27841 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:33:56 +0500 Subject: [PATCH 14/31] feat: add asyncHandler decorator for route error handling --- .../src/lib/__tests__/async-handler.test.js | 33 +++++++++++++++++++ server/src/lib/async-handler.js | 12 +++++++ 2 files changed, 45 insertions(+) create mode 100644 server/src/lib/__tests__/async-handler.test.js create mode 100644 server/src/lib/async-handler.js diff --git a/server/src/lib/__tests__/async-handler.test.js b/server/src/lib/__tests__/async-handler.test.js new file mode 100644 index 0000000..710d56b --- /dev/null +++ b/server/src/lib/__tests__/async-handler.test.js @@ -0,0 +1,33 @@ +import { describe, it, expect, vi } from 'vitest' +import { asyncHandler } from '../async-handler.js' + +describe('asyncHandler', () => { + it('calls the handler and returns result on success', async () => { + const handler = vi.fn().mockResolvedValue({ hello: 'world' }) + const request = {} + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + const result = await asyncHandler(handler)(request, reply) + expect(handler).toHaveBeenCalledWith(request, reply) + expect(result).toEqual({ hello: 'world' }) + }) + + it('catches errors and sends 500 with generic message', async () => { + const handler = vi.fn().mockRejectedValue(new Error('boom')) + const request = { log: { error: vi.fn() } } + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + await asyncHandler(handler)(request, reply) + expect(reply.code).toHaveBeenCalledWith(500) + expect(reply.send).toHaveBeenCalledWith({ error: 'Internal server error' }) + }) + + it('uses statusCode from error object when present', async () => { + const err = new Error('Not found') + err.statusCode = 404 + const handler = vi.fn().mockRejectedValue(err) + const request = { log: { error: vi.fn() } } + const reply = { code: vi.fn().mockReturnThis(), send: vi.fn() } + await asyncHandler(handler)(request, reply) + expect(reply.code).toHaveBeenCalledWith(404) + expect(reply.send).toHaveBeenCalledWith({ error: 'Not found' }) + }) +}) diff --git a/server/src/lib/async-handler.js b/server/src/lib/async-handler.js new file mode 100644 index 0000000..6924971 --- /dev/null +++ b/server/src/lib/async-handler.js @@ -0,0 +1,12 @@ +export function asyncHandler(fn) { + return async (request, reply) => { + try { + return await fn(request, reply) + } catch (err) { + request.log.error(err) + const statusCode = err.statusCode || 500 + const message = err.statusCode ? err.message : 'Internal server error' + return reply.code(statusCode).send({ error: message }) + } + } +} From 6615d97203a0933ce2a7e8b9867d3793f8d80520 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:39:18 +0500 Subject: [PATCH 15/31] refactor: apply asyncHandler to all route handlers --- server/src/routes/api/admin-categories.js | 53 +++++++++--------- server/src/routes/api/admin-gallery.js | 36 ++++++------- server/src/routes/api/catalog-slider.js | 39 +++++++------- server/src/routes/user-addresses.js | 66 +++++++++++------------ server/src/routes/user-cart.js | 53 +++++++++--------- server/src/routes/user-orders.js | 58 +++++++++----------- 6 files changed, 143 insertions(+), 162 deletions(-) diff --git a/server/src/routes/api/admin-categories.js b/server/src/routes/api/admin-categories.js index e33bc91..dff4775 100644 --- a/server/src/routes/api/admin-categories.js +++ b/server/src/routes/api/admin-categories.js @@ -1,3 +1,4 @@ +import { asyncHandler } from '../../lib/async-handler.js' import { getOrCreateUnspecifiedCategory, isUnspecifiedCategorySlug, @@ -6,20 +7,21 @@ import { import { prisma } from '../../lib/prisma.js' export async function registerAdminCategoryRoutes(fastify) { - fastify.get('/api/admin/categories', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.get( + '/api/admin/categories', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const items = await prisma.category.findMany({ orderBy: [{ sort: 'asc' }, { name: 'asc' }], }) return { items } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить категории' }) - } - }) + }), + ) - fastify.post('/api/admin/categories', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.post( + '/api/admin/categories', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const body = request.body ?? {} const name = String(body.name ?? '').trim() if (!name) { @@ -45,14 +47,13 @@ export async function registerAdminCategoryRoutes(fastify) { }, }) reply.code(201).send(category) - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось создать категорию' }) - } - }) + }), + ) - fastify.patch('/api/admin/categories/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.patch( + '/api/admin/categories/:id', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const { id } = request.params const body = request.body ?? {} const existing = await prisma.category.findUnique({ where: { id } }) @@ -105,14 +106,13 @@ export async function registerAdminCategoryRoutes(fastify) { const updated = await prisma.category.update({ where: { id }, data }) return updated - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось обновить категорию' }) - } - }) + }), + ) - fastify.delete('/api/admin/categories/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.delete( + '/api/admin/categories/:id', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const { id } = request.params const existing = await prisma.category.findUnique({ where: { id } }) if (!existing) { @@ -133,9 +133,6 @@ export async function registerAdminCategoryRoutes(fastify) { prisma.category.delete({ where: { id } }), ]) return reply.code(204).send() - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось удалить категорию' }) - } - }) + }), + ) } diff --git a/server/src/routes/api/admin-gallery.js b/server/src/routes/api/admin-gallery.js index c5954b5..c984824 100644 --- a/server/src/routes/api/admin-gallery.js +++ b/server/src/routes/api/admin-gallery.js @@ -1,5 +1,6 @@ import fs from 'node:fs/promises' import path from 'node:path' +import { asyncHandler } from '../../lib/async-handler.js' import { prisma } from '../../lib/prisma.js' import { persistMultipartImages } from '../../lib/upload-images.js' import { @@ -72,21 +73,23 @@ export async function registerAdminGalleryRoutes(fastify) { } }) - fastify.post('/api/admin/gallery/:id/resize', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - const { id } = request.params - const row = await prisma.galleryImage.findUnique({ where: { id } }) - if (!row) { - return reply.code(404).send({ error: 'Изображение не найдено' }) - } - if (row.isResized) { - return reply.code(409).send({ error: 'Изображение уже обработано' }) - } + fastify.post( + '/api/admin/gallery/:id/resize', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { + const { id } = request.params + const row = await prisma.galleryImage.findUnique({ where: { id } }) + if (!row) { + return reply.code(404).send({ error: 'Изображение не найдено' }) + } + if (row.isResized) { + return reply.code(409).send({ error: 'Изображение уже обработано' }) + } - const urlParts = row.url.replace(/^\//, '').split('/') - const fileName = urlParts[urlParts.length - 1] - const uuid = path.parse(fileName).name + const urlParts = row.url.replace(/^\//, '').split('/') + const fileName = urlParts[urlParts.length - 1] + const uuid = path.parse(fileName).name - try { const { generateAllSizes, convertOriginalToWebp } = await import('../../lib/image-resize.js') const fullPath = path.join(process.cwd(), urlParts.slice(0, -1).join('/'), fileName) @@ -99,11 +102,8 @@ export async function registerAdminGalleryRoutes(fastify) { }) return { url: newUrl } - } catch (error) { - request.log.error(error, 'Resize failed') - return reply.code(500).send({ error: 'Ошибка обработки изображения' }) - } - }) + }), + ) fastify.delete('/api/admin/gallery/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { const { id } = request.params diff --git a/server/src/routes/api/catalog-slider.js b/server/src/routes/api/catalog-slider.js index 34c4087..ab99d9e 100644 --- a/server/src/routes/api/catalog-slider.js +++ b/server/src/routes/api/catalog-slider.js @@ -1,10 +1,12 @@ +import { asyncHandler } from '../../lib/async-handler.js' import { prisma } from '../../lib/prisma.js' const MAX_SLIDES = 20 export async function registerCatalogSliderRoutes(fastify) { - fastify.get('/api/catalog-slider', async (request, reply) => { - try { + fastify.get( + '/api/catalog-slider', + asyncHandler(async (request, reply) => { const slides = await prisma.catalogSliderSlide.findMany({ orderBy: { sortOrder: 'asc' }, include: { galleryImage: true }, @@ -17,14 +19,13 @@ export async function registerCatalogSliderRoutes(fastify) { textColor: s.textColor, })), } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить слайдер' }) - } - }) + }), + ) - fastify.get('/api/admin/catalog-slider', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.get( + '/api/admin/catalog-slider', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const slides = await prisma.catalogSliderSlide.findMany({ orderBy: { sortOrder: 'asc' }, include: { galleryImage: true }, @@ -38,14 +39,13 @@ export async function registerCatalogSliderRoutes(fastify) { textColor: s.textColor, })), } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить слайдер' }) - } - }) + }), + ) - fastify.put('/api/admin/catalog-slider', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { - try { + fastify.put( + '/api/admin/catalog-slider', + { preHandler: [fastify.verifyAdmin] }, + asyncHandler(async (request, reply) => { const body = request.body ?? {} const rawSlides = body.slides if (!Array.isArray(rawSlides)) { @@ -103,9 +103,6 @@ export async function registerCatalogSliderRoutes(fastify) { textColor: s.textColor, })), } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось обновить слайдер' }) - } - }) + }), + ) } diff --git a/server/src/routes/user-addresses.js b/server/src/routes/user-addresses.js index 54d3659..6ea4b30 100644 --- a/server/src/routes/user-addresses.js +++ b/server/src/routes/user-addresses.js @@ -1,3 +1,4 @@ +import { asyncHandler } from '../lib/async-handler.js' import { prisma } from '../lib/prisma.js' function normalizePhoneLite(input) { @@ -45,22 +46,23 @@ function validateAddressPayload(body, reply) { } export async function registerUserAddressRoutes(fastify) { - fastify.get('/api/me/addresses', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.get( + '/api/me/addresses', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const items = await prisma.shippingAddress.findMany({ where: { userId }, orderBy: [{ isDefault: 'desc' }, { updatedAt: 'desc' }], }) return { items } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить адреса' }) - } - }) + }), + ) - fastify.post('/api/me/addresses', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.post( + '/api/me/addresses', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const validated = validateAddressPayload(request.body, reply) if (!validated) return @@ -79,14 +81,13 @@ export async function registerUserAddressRoutes(fastify) { }) }) return reply.code(201).send({ item: created }) - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось создать адрес' }) - } - }) + }), + ) - fastify.patch('/api/me/addresses/:id', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.patch( + '/api/me/addresses/:id', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } }) @@ -161,14 +162,13 @@ export async function registerUserAddressRoutes(fastify) { }) return { item: updated } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось обновить адрес' }) - } - }) + }), + ) - fastify.delete('/api/me/addresses/:id', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.delete( + '/api/me/addresses/:id', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } }) @@ -176,14 +176,13 @@ export async function registerUserAddressRoutes(fastify) { await prisma.shippingAddress.delete({ where: { id } }) return reply.code(204).send() - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось удалить адрес' }) - } - }) + }), + ) - fastify.post('/api/me/addresses/:id/default', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.post( + '/api/me/addresses/:id/default', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } }) @@ -195,9 +194,6 @@ export async function registerUserAddressRoutes(fastify) { }) return { item: updated } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось установить адрес по умолчанию' }) - } - }) + }), + ) } diff --git a/server/src/routes/user-cart.js b/server/src/routes/user-cart.js index 8a5ba0e..f35dfcd 100644 --- a/server/src/routes/user-cart.js +++ b/server/src/routes/user-cart.js @@ -1,8 +1,11 @@ +import { asyncHandler } from '../lib/async-handler.js' import { prisma } from '../lib/prisma.js' export async function registerUserCartRoutes(fastify) { - fastify.get('/api/me/cart', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.get( + '/api/me/cart', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const items = await prisma.cartItem.findMany({ where: { userId }, @@ -16,14 +19,13 @@ export async function registerUserCartRoutes(fastify) { product: x.product, })), } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить корзину' }) - } - }) + }), + ) - fastify.post('/api/me/cart/items', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.post( + '/api/me/cart/items', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const productId = String(request.body?.productId || '').trim() const qtyRaw = request.body?.qty @@ -46,14 +48,13 @@ export async function registerUserCartRoutes(fastify) { create: { userId, productId, qty: nextQty }, }) return reply.code(201).send({ item }) - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось добавить в корзину' }) - } - }) + }), + ) - fastify.patch('/api/me/cart/items/:id', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.patch( + '/api/me/cart/items/:id', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const qtyRaw = request.body?.qty @@ -74,23 +75,19 @@ export async function registerUserCartRoutes(fastify) { const updated = await prisma.cartItem.update({ where: { id }, data: { qty: nextQty } }) return { item: updated } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось обновить количество' }) - } - }) + }), + ) - fastify.delete('/api/me/cart/items/:id', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.delete( + '/api/me/cart/items/:id', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const existing = await prisma.cartItem.findFirst({ where: { id, userId } }) if (!existing) return reply.code(404).send({ error: 'Позиция корзины не найдена' }) await prisma.cartItem.delete({ where: { id } }) return reply.code(204).send() - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось удалить из корзины' }) - } - }) + }), + ) } diff --git a/server/src/routes/user-orders.js b/server/src/routes/user-orders.js index 2c2da0f..0a68e40 100644 --- a/server/src/routes/user-orders.js +++ b/server/src/routes/user-orders.js @@ -1,4 +1,5 @@ import { NOTIFICATION_EVENTS } from '../../../shared/constants/notification-events.js' +import { asyncHandler } from '../lib/async-handler.js' import { isDeliveryCarrier } from '../lib/delivery-carrier.js' import { prisma } from '../lib/prisma.js' @@ -176,8 +177,10 @@ export async function registerUserOrderRoutes(fastify) { return reply.code(201).send({ orderId: created.id }) }) - fastify.get('/api/me/orders', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.get( + '/api/me/orders', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const orders = await prisma.order.findMany({ where: { userId }, @@ -195,14 +198,13 @@ export async function registerUserOrderRoutes(fastify) { itemsCount: o.items.reduce((s, i) => s + i.qty, 0), })), } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить заказы' }) - } - }) + }), + ) - fastify.get('/api/me/orders/:id', { preHandler: [fastify.authenticate] }, async (request, reply) => { - try { + fastify.get( + '/api/me/orders/:id', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params const order = await prisma.order.findFirst({ @@ -211,11 +213,8 @@ export async function registerUserOrderRoutes(fastify) { }) if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) return { item: order } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось загрузить заказ' }) - } - }) + }), + ) fastify.get( '/api/me/orders/:id/review-eligibility', @@ -260,25 +259,20 @@ export async function registerUserOrderRoutes(fastify) { fastify.post( '/api/me/orders/:id/confirm-received', { preHandler: [fastify.authenticate] }, - async (request, reply) => { - try { - const userId = request.user.sub - const { id } = request.params - const order = await prisma.order.findFirst({ where: { id, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const { id } = request.params + const order = await prisma.order.findFirst({ where: { id, userId } }) + if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) - const okDelivery = order.deliveryType === 'delivery' && order.status === 'SHIPPED' - const okPickup = order.deliveryType === 'pickup' && order.status === 'READY_FOR_PICKUP' - if (!okDelivery && !okPickup) { - return reply.code(409).send({ error: 'Сейчас нельзя подтвердить получение заказа' }) - } - - await prisma.order.update({ where: { id }, data: { status: 'DONE' } }) - return { ok: true, status: 'DONE' } - } catch (err) { - request.log.error(err) - return reply.code(500).send({ error: 'Не удалось подтвердить получение' }) + const okDelivery = order.deliveryType === 'delivery' && order.status === 'SHIPPED' + const okPickup = order.deliveryType === 'pickup' && order.status === 'READY_FOR_PICKUP' + if (!okDelivery && !okPickup) { + return reply.code(409).send({ error: 'Сейчас нельзя подтвердить получение заказа' }) } - }, + + await prisma.order.update({ where: { id }, data: { status: 'DONE' } }) + return { ok: true, status: 'DONE' } + }), ) } From 24b3b4063d7d61bc1ec264df7dad9e4d3d0dc67a Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:41:33 +0500 Subject: [PATCH 16/31] refactor: extract validateGalleryImages helper --- .../__tests__/validate-gallery-images.test.js | 32 ++++++++++++++++ server/src/lib/validate-gallery-images.js | 23 ++++++++++++ server/src/routes/api/admin-products.js | 37 +++++-------------- 3 files changed, 64 insertions(+), 28 deletions(-) create mode 100644 server/src/lib/__tests__/validate-gallery-images.test.js create mode 100644 server/src/lib/validate-gallery-images.js diff --git a/server/src/lib/__tests__/validate-gallery-images.test.js b/server/src/lib/__tests__/validate-gallery-images.test.js new file mode 100644 index 0000000..6818bd6 --- /dev/null +++ b/server/src/lib/__tests__/validate-gallery-images.test.js @@ -0,0 +1,32 @@ +import { describe, it, expect, vi } from 'vitest' +import { validateGalleryImages } from '../validate-gallery-images.js' + +describe('validateGalleryImages', () => { + it('returns null when urls is empty', async () => { + const prisma = { galleryImage: { findMany: vi.fn() } } + const result = await validateGalleryImages(prisma, []) + expect(result).toBeNull() + }) + + it('throws 400 when image not found', async () => { + const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue([]) } } + await expect(validateGalleryImages(prisma, ['/uploads/missing.jpg'])).rejects.toMatchObject({ statusCode: 400 }) + }) + + it('throws 400 when image not yet resized', async () => { + const prisma = { + galleryImage: { findMany: vi.fn().mockResolvedValue([{ url: '/uploads/img.jpg', isResized: false }]) }, + } + await expect(validateGalleryImages(prisma, ['/uploads/img.jpg'])).rejects.toMatchObject({ statusCode: 400 }) + }) + + it('returns existing images when all valid and resized', async () => { + const images = [ + { url: '/uploads/img1.jpg', isResized: true }, + { url: '/uploads/img2.jpg', isResized: true }, + ] + const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue(images) } } + const result = await validateGalleryImages(prisma, ['/uploads/img1.jpg', '/uploads/img2.jpg']) + expect(result).toEqual(images) + }) +}) diff --git a/server/src/lib/validate-gallery-images.js b/server/src/lib/validate-gallery-images.js new file mode 100644 index 0000000..ec49047 --- /dev/null +++ b/server/src/lib/validate-gallery-images.js @@ -0,0 +1,23 @@ +export async function validateGalleryImages(prisma, urls) { + if (!urls || urls.length === 0) return null + + const existing = await prisma.galleryImage.findMany({ + where: { url: { in: urls } }, + select: { url: true, isResized: true }, + }) + + const galleryMap = new Map(existing.map((g) => [g.url, g])) + const notFound = urls.filter((u) => !galleryMap.has(u)) + if (notFound.length > 0) { + throw Object.assign(new Error(`Gallery images not found: ${notFound.join(', ')}`), { statusCode: 400 }) + } + + const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized) + if (notResized.length > 0) { + throw Object.assign(new Error('Some gallery images have not been processed yet. Please try again later.'), { + statusCode: 400, + }) + } + + return existing +} diff --git a/server/src/routes/api/admin-products.js b/server/src/routes/api/admin-products.js index 3992e43..5d8d1e3 100644 --- a/server/src/routes/api/admin-products.js +++ b/server/src/routes/api/admin-products.js @@ -1,4 +1,5 @@ import { prisma } from '../../lib/prisma.js' +import { validateGalleryImages } from '../../lib/validate-gallery-images.js' const CREATE_PRODUCT_SCHEMA = { body: { @@ -87,20 +88,10 @@ export async function registerAdminProductRoutes(fastify) { if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) { const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean) if (urls.length > 0) { - const galleryImages = await prisma.galleryImage.findMany({ - where: { url: { in: urls } }, - select: { url: true, isResized: true }, - }) - const galleryMap = new Map(galleryImages.map((g) => [g.url, g])) - const notFound = urls.filter((u) => !galleryMap.has(u)) - const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized) - if (notFound.length > 0) { - return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' }) - } - if (notResized.length > 0) { - return reply - .code(400) - .send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' }) + try { + await validateGalleryImages(prisma, urls) + } catch (err) { + return reply.code(err.statusCode || 400).send({ error: err.message }) } } } @@ -214,20 +205,10 @@ export async function registerAdminProductRoutes(fastify) { if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) { const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean) if (urls.length > 0) { - const galleryImages = await prisma.galleryImage.findMany({ - where: { url: { in: urls } }, - select: { url: true, isResized: true }, - }) - const galleryMap = new Map(galleryImages.map((g) => [g.url, g])) - const notFound = urls.filter((u) => !galleryMap.has(u)) - const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized) - if (notFound.length > 0) { - return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' }) - } - if (notResized.length > 0) { - return reply - .code(400) - .send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' }) + try { + await validateGalleryImages(prisma, urls) + } catch (err) { + return reply.code(err.statusCode || 400).send({ error: err.message }) } } } From 45627206c037a3288a5721804dc8c2267520b9dd Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:47:16 +0500 Subject: [PATCH 17/31] refactor: extract findUserOrder helper --- .../src/lib/__tests__/find-user-order.test.js | 27 ++ server/src/lib/find-user-order.js | 12 + server/src/routes/user-messages.js | 97 +++--- server/src/routes/user-orders.js | 21 +- server/src/routes/user-payments.js | 285 +++++++++--------- 5 files changed, 246 insertions(+), 196 deletions(-) create mode 100644 server/src/lib/__tests__/find-user-order.test.js create mode 100644 server/src/lib/find-user-order.js diff --git a/server/src/lib/__tests__/find-user-order.test.js b/server/src/lib/__tests__/find-user-order.test.js new file mode 100644 index 0000000..a101edb --- /dev/null +++ b/server/src/lib/__tests__/find-user-order.test.js @@ -0,0 +1,27 @@ +import { describe, it, expect, vi } from 'vitest' +import { findUserOrder } from '../find-user-order.js' + +describe('findUserOrder', () => { + it('returns order when found', async () => { + const mockOrder = { id: '1', userId: 'user1' } + const prisma = { order: { findFirst: vi.fn().mockResolvedValue(mockOrder) } } + const result = await findUserOrder(prisma, '1', 'user1') + expect(result).toEqual(mockOrder) + expect(prisma.order.findFirst).toHaveBeenCalledWith( + expect.objectContaining({ where: { id: '1', userId: 'user1' } }), + ) + }) + + it('throws 404 when order not found', async () => { + const prisma = { order: { findFirst: vi.fn().mockResolvedValue(null) } } + await expect(findUserOrder(prisma, '999', 'user1')).rejects.toMatchObject({ statusCode: 404 }) + }) + + it('passes include option', async () => { + const mockOrder = { id: '1', userId: 'user1', items: [] } + const prisma = { order: { findFirst: vi.fn().mockResolvedValue(mockOrder) } } + const result = await findUserOrder(prisma, '1', 'user1', { items: true }) + expect(result).toEqual(mockOrder) + expect(prisma.order.findFirst).toHaveBeenCalledWith(expect.objectContaining({ include: { items: true } })) + }) +}) diff --git a/server/src/lib/find-user-order.js b/server/src/lib/find-user-order.js new file mode 100644 index 0000000..6c14d09 --- /dev/null +++ b/server/src/lib/find-user-order.js @@ -0,0 +1,12 @@ +export async function findUserOrder(prisma, orderId, userId, include = {}) { + const order = await prisma.order.findFirst({ + where: { id: orderId, userId }, + include, + }) + + if (!order) { + throw Object.assign(new Error('Order not found'), { statusCode: 404 }) + } + + return order +} diff --git a/server/src/routes/user-messages.js b/server/src/routes/user-messages.js index cd446ad..863f821 100644 --- a/server/src/routes/user-messages.js +++ b/server/src/routes/user-messages.js @@ -1,40 +1,48 @@ import { NOTIFICATION_EVENTS } from '../../../shared/constants/notification-events.js' +import { asyncHandler } from '../lib/async-handler.js' +import { findUserOrder } from '../lib/find-user-order.js' import { prisma } from '../lib/prisma.js' export async function registerUserMessageRoutes(fastify) { - fastify.get('/api/me/orders/:id/messages', { preHandler: [fastify.authenticate] }, async (request, reply) => { - const userId = request.user.sub - const { id } = request.params - const order = await prisma.order.findFirst({ where: { id, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) - const items = await prisma.orderMessage.findMany({ - where: { orderId: id }, - orderBy: { createdAt: 'asc' }, - }) - return { items } - }) + fastify.get( + '/api/me/orders/:id/messages', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const { id } = request.params + await findUserOrder(prisma, id, userId) + const items = await prisma.orderMessage.findMany({ + where: { orderId: id }, + orderBy: { createdAt: 'asc' }, + }) + return { items } + }), + ) - fastify.post('/api/me/orders/:id/messages', { preHandler: [fastify.authenticate] }, async (request, reply) => { - const userId = request.user.sub - const { id } = request.params - const order = await prisma.order.findFirst({ where: { id, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) - const text = String(request.body?.text || '').trim() - if (!text) return reply.code(400).send({ error: 'Сообщение пустое' }) - if (text.length > 2000) return reply.code(400).send({ error: 'Сообщение слишком длинное' }) - const msg = await prisma.orderMessage.create({ - data: { orderId: id, authorType: 'user', text }, - }) + fastify.post( + '/api/me/orders/:id/messages', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const { id } = request.params + await findUserOrder(prisma, id, userId) + const text = String(request.body?.text || '').trim() + if (!text) return reply.code(400).send({ error: 'Сообщение пустое' }) + if (text.length > 2000) return reply.code(400).send({ error: 'Сообщение слишком длинное' }) + const msg = await prisma.orderMessage.create({ + data: { orderId: id, authorType: 'user', text }, + }) - request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_MESSAGE_SENT, { - orderId: id, - authorType: 'user', - messageId: msg.id, - preview: text, - }) + request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_MESSAGE_SENT, { + orderId: id, + authorType: 'user', + messageId: msg.id, + preview: text, + }) - return reply.code(201).send({ item: msg }) - }) + return reply.code(201).send({ item: msg }) + }), + ) fastify.get('/api/me/messages/unread-count', { preHandler: [fastify.authenticate] }, async (request) => { const userId = request.user.sub @@ -116,18 +124,21 @@ export async function registerUserMessageRoutes(fastify) { return { items } }) - fastify.post('/api/me/orders/:id/messages/read', { preHandler: [fastify.authenticate] }, async (request, reply) => { - const userId = request.user.sub - const { id } = request.params - const order = await prisma.order.findFirst({ where: { id, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) + fastify.post( + '/api/me/orders/:id/messages/read', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const { id } = request.params + await findUserOrder(prisma, id, userId) - const now = new Date() - await prisma.userOrderMessageReadState.upsert({ - where: { userId_orderId: { userId, orderId: id } }, - create: { userId, orderId: id, lastReadAt: now }, - update: { lastReadAt: now }, - }) - return { ok: true } - }) + const now = new Date() + await prisma.userOrderMessageReadState.upsert({ + where: { userId_orderId: { userId, orderId: id } }, + create: { userId, orderId: id, lastReadAt: now }, + update: { lastReadAt: now }, + }) + return { ok: true } + }), + ) } diff --git a/server/src/routes/user-orders.js b/server/src/routes/user-orders.js index 0a68e40..4d5cc45 100644 --- a/server/src/routes/user-orders.js +++ b/server/src/routes/user-orders.js @@ -1,6 +1,7 @@ import { NOTIFICATION_EVENTS } from '../../../shared/constants/notification-events.js' import { asyncHandler } from '../lib/async-handler.js' import { isDeliveryCarrier } from '../lib/delivery-carrier.js' +import { findUserOrder } from '../lib/find-user-order.js' import { prisma } from '../lib/prisma.js' export async function registerUserOrderRoutes(fastify) { @@ -207,11 +208,10 @@ export async function registerUserOrderRoutes(fastify) { asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params - const order = await prisma.order.findFirst({ - where: { id, userId }, - include: { items: true, messages: { orderBy: { createdAt: 'asc' } } }, + const order = await findUserOrder(prisma, id, userId, { + items: true, + messages: { orderBy: { createdAt: 'asc' } }, }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) return { item: order } }), ) @@ -219,14 +219,10 @@ export async function registerUserOrderRoutes(fastify) { fastify.get( '/api/me/orders/:id/review-eligibility', { preHandler: [fastify.authenticate] }, - async (request, reply) => { + asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params - const order = await prisma.order.findFirst({ - where: { id, userId }, - include: { items: true }, - }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) + const order = await findUserOrder(prisma, id, userId, { items: true }) if (order.status !== 'DONE') { return { canReview: false, items: [] } } @@ -253,7 +249,7 @@ export async function registerUserOrderRoutes(fastify) { hasReview: reviewed.has(x.productId), })), } - }, + }), ) fastify.post( @@ -262,8 +258,7 @@ export async function registerUserOrderRoutes(fastify) { asyncHandler(async (request, reply) => { const userId = request.user.sub const { id } = request.params - const order = await prisma.order.findFirst({ where: { id, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) + const order = await findUserOrder(prisma, id, userId) const okDelivery = order.deliveryType === 'delivery' && order.status === 'SHIPPED' const okPickup = order.deliveryType === 'pickup' && order.status === 'READY_FOR_PICKUP' diff --git a/server/src/routes/user-payments.js b/server/src/routes/user-payments.js index 3f3a59f..22cc260 100644 --- a/server/src/routes/user-payments.js +++ b/server/src/routes/user-payments.js @@ -1,149 +1,154 @@ import { NOTIFICATION_EVENTS } from '../../../shared/constants/notification-events.js' +import { asyncHandler } from '../lib/async-handler.js' +import { findUserOrder } from '../lib/find-user-order.js' import { prisma } from '../lib/prisma.js' import { createPayment, buildReceipt, getPayment } from '../lib/yookassa.js' export async function registerUserPaymentRoutes(fastify) { - fastify.post('/api/me/orders/:id/pay', { preHandler: [fastify.authenticate] }, async (request, reply) => { - const userId = request.user.sub - const userEmail = request.user.email + fastify.post( + '/api/me/orders/:id/pay', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const userEmail = request.user.email - if (!userEmail) { - return reply.code(422).send({ error: 'Для онлайн-оплаты необходим email в профиле' }) - } - - const { id } = request.params - - const order = await prisma.order.findFirst({ - where: { id, userId }, - include: { items: true }, - }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) - - if (order.paymentMethod === 'on_pickup') { - return reply.code(409).send({ - error: 'Для этого заказа оплата при получении — онлайн-оплата недоступна', - }) - } - - if (order.status !== 'PENDING_PAYMENT') { - return reply.code(409).send({ error: 'Сейчас нельзя выполнить оплату для этого заказа' }) - } - - if (!order.deliveryFeeLocked) { - return reply.code(409).send({ - error: 'Стоимость доставки ещё утверждается — оплата станет доступна позже', - }) - } - - const existingPayment = await prisma.payment.findFirst({ - where: { - orderId: id, - status: { in: ['pending', 'waiting_for_capture'] }, - OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }], - }, - orderBy: { createdAt: 'desc' }, - }) - - if (existingPayment && existingPayment.confirmationUrl) { - return { confirmationUrl: existingPayment.confirmationUrl } - } - - const idempotencyKey = `${id}-${Date.now()}` - const clientUrl = (process.env.CLIENT_PUBLIC_URL || 'http://127.0.0.1:5173').replace(/\/$/, '') - const returnUrl = `${clientUrl}/me/orders/${id}?paid=1` - const clientIp = request.ip - - const amount = { - value: (order.totalCents / 100).toFixed(2), - currency: order.currency, - } - - const receipt = buildReceipt({ - orderItems: order.items, - deliveryFeeCents: order.deliveryFeeCents, - userEmail: userEmail, - }) - - let result - try { - result = await createPayment({ - amount, - description: `Оплата заказа №${order.id.slice(-6)}`, - receipt, - confirmation: { type: 'redirect', return_url: returnUrl }, - metadata: { orderId: order.id }, - idempotencyKey, - clientIp, - }) - } catch (err) { - request.log.error({ err, orderId: id }, 'YooKassa createPayment failed') - return reply.code(502).send({ - error: 'Не удалось создать платёж. Платёжный сервис временно недоступен.', - }) - } - - await prisma.payment.create({ - data: { - orderId: order.id, - yookassaPaymentId: result.paymentId, - status: result.status, - amountCents: order.totalCents, - currency: order.currency, - confirmationUrl: result.confirmationUrl, - expiresAt: result.expiresAt ? new Date(result.expiresAt) : null, - }, - }) - - return { confirmationUrl: result.confirmationUrl } - }) - - fastify.get('/api/me/orders/:orderId/payment', { preHandler: [fastify.authenticate] }, async (request, reply) => { - const userId = request.user.sub - const { orderId } = request.params - - const order = await prisma.order.findFirst({ where: { id: orderId, userId } }) - if (!order) return reply.code(404).send({ error: 'Заказ не найден' }) - - const payment = await prisma.payment.findFirst({ - where: { orderId }, - orderBy: { createdAt: 'desc' }, - }) - if (!payment) { - return { status: null, paid: false } - } - - if (payment.status === 'succeeded' || payment.status === 'canceled') { - return { status: payment.status, paid: payment.status === 'succeeded' } - } - - try { - const ykPayment = await getPayment(payment.yookassaPaymentId) - - if (ykPayment.status !== payment.status) { - await prisma.payment.update({ - where: { id: payment.id }, - data: { status: ykPayment.status }, - }) - - if (ykPayment.status === 'succeeded' && order.status === 'PENDING_PAYMENT') { - const updated = await prisma.order.updateMany({ - where: { id: orderId, status: 'PENDING_PAYMENT' }, - data: { status: 'PAID' }, - }) - if (updated.count > 0) { - request.server.eventBus.emit(NOTIFICATION_EVENTS.PAYMENT_STATUS_CHANGED, { - orderId, - userId: order.userId, - paymentStatus: 'paid', - }) - } - } + if (!userEmail) { + return reply.code(422).send({ error: 'Для онлайн-оплаты необходим email в профиле' }) } - return { status: ykPayment.status, paid: ykPayment.paid } - } catch (err) { - request.log.error({ err }, '[user-payments] Operation failed') - return { status: payment.status, paid: payment.status === 'succeeded' } - } - }) + const { id } = request.params + + const order = await findUserOrder(prisma, id, userId, { items: true }) + + if (order.paymentMethod === 'on_pickup') { + return reply.code(409).send({ + error: 'Для этого заказа оплата при получении — онлайн-оплата недоступна', + }) + } + + if (order.status !== 'PENDING_PAYMENT') { + return reply.code(409).send({ error: 'Сейчас нельзя выполнить оплату для этого заказа' }) + } + + if (!order.deliveryFeeLocked) { + return reply.code(409).send({ + error: 'Стоимость доставки ещё утверждается — оплата станет доступна позже', + }) + } + + const existingPayment = await prisma.payment.findFirst({ + where: { + orderId: id, + status: { in: ['pending', 'waiting_for_capture'] }, + OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }], + }, + orderBy: { createdAt: 'desc' }, + }) + + if (existingPayment && existingPayment.confirmationUrl) { + return { confirmationUrl: existingPayment.confirmationUrl } + } + + const idempotencyKey = `${id}-${Date.now()}` + const clientUrl = (process.env.CLIENT_PUBLIC_URL || 'http://127.0.0.1:5173').replace(/\/$/, '') + const returnUrl = `${clientUrl}/me/orders/${id}?paid=1` + const clientIp = request.ip + + const amount = { + value: (order.totalCents / 100).toFixed(2), + currency: order.currency, + } + + const receipt = buildReceipt({ + orderItems: order.items, + deliveryFeeCents: order.deliveryFeeCents, + userEmail: userEmail, + }) + + let result + try { + result = await createPayment({ + amount, + description: `Оплата заказа №${order.id.slice(-6)}`, + receipt, + confirmation: { type: 'redirect', return_url: returnUrl }, + metadata: { orderId: order.id }, + idempotencyKey, + clientIp, + }) + } catch (err) { + request.log.error({ err, orderId: id }, 'YooKassa createPayment failed') + return reply.code(502).send({ + error: 'Не удалось создать платёж. Платёжный сервис временно недоступен.', + }) + } + + await prisma.payment.create({ + data: { + orderId: order.id, + yookassaPaymentId: result.paymentId, + status: result.status, + amountCents: order.totalCents, + currency: order.currency, + confirmationUrl: result.confirmationUrl, + expiresAt: result.expiresAt ? new Date(result.expiresAt) : null, + }, + }) + + return { confirmationUrl: result.confirmationUrl } + }), + ) + + fastify.get( + '/api/me/orders/:orderId/payment', + { preHandler: [fastify.authenticate] }, + asyncHandler(async (request, reply) => { + const userId = request.user.sub + const { orderId } = request.params + + const order = await findUserOrder(prisma, orderId, userId) + + const payment = await prisma.payment.findFirst({ + where: { orderId }, + orderBy: { createdAt: 'desc' }, + }) + if (!payment) { + return { status: null, paid: false } + } + + if (payment.status === 'succeeded' || payment.status === 'canceled') { + return { status: payment.status, paid: payment.status === 'succeeded' } + } + + try { + const ykPayment = await getPayment(payment.yookassaPaymentId) + + if (ykPayment.status !== payment.status) { + await prisma.payment.update({ + where: { id: payment.id }, + data: { status: ykPayment.status }, + }) + + if (ykPayment.status === 'succeeded' && order.status === 'PENDING_PAYMENT') { + const updated = await prisma.order.updateMany({ + where: { id: orderId, status: 'PENDING_PAYMENT' }, + data: { status: 'PAID' }, + }) + if (updated.count > 0) { + request.server.eventBus.emit(NOTIFICATION_EVENTS.PAYMENT_STATUS_CHANGED, { + orderId, + userId: order.userId, + paymentStatus: 'paid', + }) + } + } + } + + return { status: ykPayment.status, paid: ykPayment.paid } + } catch (err) { + request.log.error({ err }, '[user-payments] Operation failed') + return { status: payment.status, paid: payment.status === 'succeeded' } + } + }), + ) } From ed424a3b0b969a79edd1e25490d063354c212002 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:54:49 +0500 Subject: [PATCH 18/31] refactor: extract useCartQuery hook --- client/src/entities/cart/lib/use-cart-query.ts | 14 ++++++++++++++ .../cart/toggle-cart-icon/ui/ToggleCartIcon.tsx | 11 ++++------- client/src/pages/cart/ui/CartPage.tsx | 11 ++++------- client/src/pages/checkout/ui/CheckoutPage.tsx | 8 ++------ 4 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 client/src/entities/cart/lib/use-cart-query.ts diff --git a/client/src/entities/cart/lib/use-cart-query.ts b/client/src/entities/cart/lib/use-cart-query.ts new file mode 100644 index 0000000..614d1e1 --- /dev/null +++ b/client/src/entities/cart/lib/use-cart-query.ts @@ -0,0 +1,14 @@ +import { useQuery } from '@tanstack/react-query' +import { useUnit } from 'effector-react' +import { fetchMyCart } from '../api/cart-api' +import { $user } from '@/shared/model/auth' + +export function useCartQuery() { + const user = useUnit($user) + + return useQuery({ + queryKey: ['me', 'cart'], + queryFn: fetchMyCart, + enabled: Boolean(user), + }) +} diff --git a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx index fe51801..1d13fc4 100644 --- a/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx +++ b/client/src/features/cart/toggle-cart-icon/ui/ToggleCartIcon.tsx @@ -1,10 +1,11 @@ import IconButton from '@mui/material/IconButton' import Tooltip from '@mui/material/Tooltip' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useMutation, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { ShoppingCart } from 'lucide-react' import { useNavigate } from 'react-router-dom' -import { addToCart, fetchMyCart, removeCartItem } from '@/entities/cart/api/cart-api' +import { addToCart, removeCartItem } from '@/entities/cart/api/cart-api' +import { useCartQuery } from '@/entities/cart/lib/use-cart-query' import { $user } from '@/shared/model/auth' import { addNotification } from '@/shared/model/notification' @@ -18,11 +19,7 @@ export function ToggleCartIcon(props: { const qc = useQueryClient() const navigate = useNavigate() - const cartQuery = useQuery({ - queryKey: ['me', 'cart'], - queryFn: fetchMyCart, - enabled: Boolean(user), - }) + const cartQuery = useCartQuery() const existing = cartQuery.data?.items.find((x) => x.product.id === productId) ?? null const inCart = Boolean(existing) diff --git a/client/src/pages/cart/ui/CartPage.tsx b/client/src/pages/cart/ui/CartPage.tsx index 5f8ff40..0b7bc63 100644 --- a/client/src/pages/cart/ui/CartPage.tsx +++ b/client/src/pages/cart/ui/CartPage.tsx @@ -6,11 +6,12 @@ import IconButton from '@mui/material/IconButton' import Stack from '@mui/material/Stack' import Tooltip from '@mui/material/Tooltip' import Typography from '@mui/material/Typography' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useMutation, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { Minus, Plus, Trash2 } from 'lucide-react' import { Link as RouterLink } from 'react-router-dom' -import { fetchMyCart, removeCartItem, setCartQty } from '@/entities/cart/api/cart-api' +import { removeCartItem, setCartQty } from '@/entities/cart/api/cart-api' +import { useCartQuery } from '@/entities/cart/lib/use-cart-query' import { formatPriceRub } from '@/shared/lib/format-price' import { usePageTitle } from '@/shared/lib/use-page-title' import { $user } from '@/shared/model/auth' @@ -20,11 +21,7 @@ export function CartPage() { const user = useUnit($user) const qc = useQueryClient() - const cartQuery = useQuery({ - queryKey: ['me', 'cart'], - queryFn: fetchMyCart, - enabled: Boolean(user), - }) + const cartQuery = useCartQuery() const qtyMut = useMutation({ mutationFn: (params: { id: string; qty: number }) => setCartQty(params.id, params.qty), diff --git a/client/src/pages/checkout/ui/CheckoutPage.tsx b/client/src/pages/checkout/ui/CheckoutPage.tsx index fa0edb2..03eb7ab 100644 --- a/client/src/pages/checkout/ui/CheckoutPage.tsx +++ b/client/src/pages/checkout/ui/CheckoutPage.tsx @@ -16,8 +16,8 @@ import Typography from '@mui/material/Typography' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { Link as RouterLink, useNavigate } from 'react-router-dom' -import { fetchMyCart } from '@/entities/cart/api/cart-api' import { createOrder } from '@/entities/order/api/order-api' +import { useCartQuery } from '@/entities/cart/lib/use-cart-query' import { fetchMyAddresses } from '@/entities/user/api/address-api' import { DELIVERY_CARRIER_OPTIONS, type DeliveryCarrierCode } from '@/shared/constants/delivery-carrier' import { formatPriceRub } from '@/shared/lib/format-price' @@ -34,11 +34,7 @@ export function CheckoutPage() { const [addressId, setAddressId] = useState('') const [comment, setComment] = useState('') - const cartQuery = useQuery({ - queryKey: ['me', 'cart'], - queryFn: fetchMyCart, - enabled: Boolean(user), - }) + const cartQuery = useCartQuery() const addressesQuery = useQuery({ queryKey: ['me', 'addresses'], From b0b2872cf81967f63c4b4c7be51e91ef5947b24d Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 21:54:53 +0500 Subject: [PATCH 19/31] refactor: remove duplicate order status labels, use ORDER_STATUS_DATA as single source --- .../order-detail/ui/OrderDetailContent.tsx | 6 +++--- .../order-payment/ui/OrderPaymentSection.tsx | 4 ++-- .../pages/admin-orders/ui/AdminOrdersPage.tsx | 6 +++--- .../src/pages/me/ui/sections/MessagesPage.tsx | 6 +++--- .../src/pages/me/ui/sections/OrdersPage.tsx | 4 ++-- client/src/shared/lib/order-status-data.ts | 4 ++++ client/src/shared/lib/order-status-labels.ts | 14 -------------- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 8 files changed, 17 insertions(+), 27 deletions(-) delete mode 100644 client/src/shared/lib/order-status-labels.ts diff --git a/client/src/features/order-detail/ui/OrderDetailContent.tsx b/client/src/features/order-detail/ui/OrderDetailContent.tsx index 34cd886..50dbe65 100644 --- a/client/src/features/order-detail/ui/OrderDetailContent.tsx +++ b/client/src/features/order-detail/ui/OrderDetailContent.tsx @@ -19,7 +19,7 @@ import { getAdminNextOrderStatuses } from '@/shared/constants/order' import { formatPriceRub } from '@/shared/lib/format-price' import { invalidateQueryKeys } from '@/shared/lib/invalidate-query-keys' import { parseOrderAddressSnapshot } from '@/shared/lib/order-address-snapshot' -import { orderStatusLabelRu } from '@/shared/lib/order-status-labels' +import { ORDER_STATUS_MAP } from '@/shared/lib/order-status-data' import { $user } from '@/shared/model/auth' import { ChatMessageBubble } from '@/shared/ui/ChatMessageBubble' import { OrderMessageBody } from '@/shared/ui/OrderMessageBody' @@ -66,7 +66,7 @@ export function OrderDetailContent({ detail, orderId }: { detail: AdminOrderDeta return ( - #{detail.id.slice(-8)} · {detail.user.email} · {orderStatusLabelRu(detail.status)} ·{' '} + #{detail.id.slice(-8)} · {detail.user.email} · {ORDER_STATUS_MAP[detail.status] ?? detail.status} ·{' '} {formatPriceRub(detail.totalCents)} @@ -184,7 +184,7 @@ export function OrderDetailContent({ detail, orderId }: { detail: AdminOrderDeta {nextStatuses.map((s) => ( - {orderStatusLabelRu(s)} + {ORDER_STATUS_MAP[s] ?? s} ))} diff --git a/client/src/features/order-payment/ui/OrderPaymentSection.tsx b/client/src/features/order-payment/ui/OrderPaymentSection.tsx index cfacf9b..72b0adb 100644 --- a/client/src/features/order-payment/ui/OrderPaymentSection.tsx +++ b/client/src/features/order-payment/ui/OrderPaymentSection.tsx @@ -1,7 +1,7 @@ import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Typography from '@mui/material/Typography' -import { orderStatusLabelRu } from '@/shared/lib/order-status-labels' +import { ORDER_STATUS_MAP } from '@/shared/lib/order-status-data' type Props = { status: string @@ -43,7 +43,7 @@ export function OrderPaymentSection({ status, deliveryFeeLocked, paymentMethod, <> Вы будете перенаправлены на защищённую платёжную страницу ЮKassa. После оплаты заказ получит статус « - {orderStatusLabelRu('PAID')}». + {ORDER_STATUS_MAP['PAID'] ?? 'PAID'}». + )} + dismissNotification(n.id)}> + + + } > {n.message} diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 08700b180610abc2ec5fbbff7cb49a1c5aa5e07f..1ef69fbda3b67c968ddc7bfdadca507c2a212add 100644 GIT binary patch delta 1794 zcmaJ>O>Y}j6rDFSj%+9JY=MIUbrKa7gwmil{+O`=Y21)dMJ28ag_1={#`f4Ae~icW zIAa^3MC`JmfiApAOR|7=gG4L0HoIm)q--ciRVyJjk-I>kh(7>QcyAosLMD-=yYRdB zocnR+tZaE!wmfSu(yZf)6H_?eUi|vX5Dgzt@DKO^ehY84+-MeFo!_{4{xowL=yFA$ zOq^t9fm)Ocl9Hd~1R)$oC>%nZpNr`7FvEd@Cgnmw#6{|onv`p=m#egg;T-+H)1+bIH_L6Njyo)8=F3Y$9A9?0$C=>R{+|@O8BtlWtd>>?~ zn2TeO0?7)f1%=P^908el>1dGOie5W_T?%$#x8>H>;k=g-fthaw$6!LQ`Kkv6A10Ft zSvi|gOG3TcFSQznZQlZ{%L(9P3O>ekt1Wlr6WCn+3B-q!Rs%lM0UFpB+iL)f4`SZ` zv?=$wtV*A>Y4v(+DeE+;b||<5ckrd=;D-V$9<0O)4R50m;uU1z1F4E%PgWb68Ytxv zX+r3&(yET!Z}fO*k^=sm%R=J#UR*bNPgf4R%zIr;^!K3#A~-#zp_ z3hrU_E^O|dXPnMjf3kLrVO>Kscu3j*1P`CB!Nt~v@sB_=BQc*2o4YxL*!fFhejh-1 zv`6M>k3NUMDRR{M3uBbcM&?W?B}Kq1#b#nisfsQc;d-U>yu!R@Yo1OsAKQ}2kU!YD zl4j0q#B*EHNF65ocaa2p@2Zi@V^H;60nee5~+;F%y86di~J zJLPaV>`$&ij>wT~6m;CT2?uN~= zW%lM9M7JvDEm_81@%CqYfKiLX}pTGFrwo0aG$u48P?7#t)3mkVSClCitTsV~XvqJ?z$G)DvzrEL_y_7Dhssucuo-sH{h)UJkTB50}WYmTbiE|<^#$!!x zX{oNw%+AH;ETjG|V&%XnMR~olt5$6&K#=Ce1ixBHq{PBntXAM70+Dlj-?e>Yy$r}W zL8f%xXcRn6;eq#eJO()%!m7Y>1&37juTJ2n18o0snfCcu zCNRo6F?5qO<9ADMWBY{$Uhcd%`604%3jOJrBVK@rB93@n*GrkE)%#nae>-t8J^yDI zZ4paR&%G$~)HmZ3pc#ael$atk;Tp%6bE;K{W$Qe*iM}80o!9Ac@7q_;AfNm}keaya zb?^{)HX;)IYC?&|E47N5FM=58I#ac#jQSKW^2JLJFf~ zs6@p`#~YezKRTq(UxINW%r_qQhi`B~E66WjV9!vYkrDd8otu#~po|kr#WW)IW}@s+ zo`q2*lsChD%E5Vl!2F1Xp+R}Vw0yJ&2Kc*vhVi>|_(LaPJi$^FJukEDI1A_BET^?9 z#FZ6tx+L-|YMIwlFi&EX#I*I1YsuVMAwGLS;#Npiy*LDqrCVOa`p@%G{Crrwz;Q;l{9<%)qT>i^e From 0bfff541a3c68453a199cfb13c9d7d6a2d321c70 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 23:23:55 +0500 Subject: [PATCH 22/31] fix: make Alert colors scheme-aware using palette tokens for berry/ocean/craft/forest compatibility --- client/src/app/providers/AppProviders.tsx | 154 +++++++++--------- .../NotificationStack/NotificationStack.tsx | 41 +++-- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 3 files changed, 96 insertions(+), 99 deletions(-) diff --git a/client/src/app/providers/AppProviders.tsx b/client/src/app/providers/AppProviders.tsx index 344264a..293f057 100644 --- a/client/src/app/providers/AppProviders.tsx +++ b/client/src/app/providers/AppProviders.tsx @@ -1,6 +1,6 @@ import { type PropsWithChildren, useMemo } from 'react' import CssBaseline from '@mui/material/CssBaseline' -import { ThemeProvider, createTheme } from '@mui/material/styles' +import { alpha, ThemeProvider, createTheme } from '@mui/material/styles' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ThemeControllerProvider, useThemeController } from '@/app/providers/theme-controller' import { SseProvider } from './SseProvider' @@ -223,89 +223,89 @@ function AppThemeInner({ children }: PropsWithChildren) { marginLeft: 8, }, }, - colorSuccess: { - bgcolor: isDark ? 'rgba(102,187,106,0.08)' : '#EDF3EC', - borderColor: isDark ? 'rgba(102,187,106,0.2)' : '#C5DFC2', - color: isDark ? '#A5D6A7' : '#346538', - '& .MuiAlert-icon': { - color: isDark ? '#A5D6A7' : '#346538', - }, - '&.MuiAlert-outlined': { - bgcolor: 'transparent', - borderColor: isDark ? 'rgba(102,187,106,0.3)' : '#C5DFC2', - color: isDark ? '#A5D6A7' : '#346538', - '& .MuiAlert-icon': { - color: isDark ? '#A5D6A7' : '#346538', + colorSuccess: ({ theme }) => { + const isDark = theme.palette.mode === 'dark' + const p = theme.palette.success + return { + bgcolor: isDark ? alpha(p.light, 0.08) : alpha(p.main, 0.08), + borderColor: isDark ? alpha(p.light, 0.2) : alpha(p.main, 0.2), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, + '&.MuiAlert-outlined': { + bgcolor: 'transparent', + borderColor: isDark ? alpha(p.light, 0.3) : alpha(p.main, 0.3), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, }, - }, - '&.MuiAlert-filled': { - bgcolor: isDark ? 'rgba(102,187,106,0.15)' : '#346538', - borderColor: 'transparent', - color: isDark ? '#E8F5E9' : '#FFFFFF', - }, + '&.MuiAlert-filled': { + bgcolor: isDark ? alpha(p.light, 0.15) : p.dark, + borderColor: 'transparent', + color: isDark ? alpha(p.light, 0.9) : '#FFFFFF', + }, + } }, - colorError: { - bgcolor: isDark ? 'rgba(239,83,80,0.08)' : '#FDEBEC', - borderColor: isDark ? 'rgba(239,83,80,0.2)' : '#F5C6C7', - color: isDark ? '#EF9A9A' : '#9F2F2D', - '& .MuiAlert-icon': { - color: isDark ? '#EF9A9A' : '#9F2F2D', - }, - '&.MuiAlert-outlined': { - bgcolor: 'transparent', - borderColor: isDark ? 'rgba(239,83,80,0.3)' : '#F5C6C7', - color: isDark ? '#EF9A9A' : '#9F2F2D', - '& .MuiAlert-icon': { - color: isDark ? '#EF9A9A' : '#9F2F2D', + colorError: ({ theme }) => { + const isDark = theme.palette.mode === 'dark' + const p = theme.palette.error + return { + bgcolor: isDark ? alpha(p.light, 0.08) : alpha(p.main, 0.08), + borderColor: isDark ? alpha(p.light, 0.2) : alpha(p.main, 0.2), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, + '&.MuiAlert-outlined': { + bgcolor: 'transparent', + borderColor: isDark ? alpha(p.light, 0.3) : alpha(p.main, 0.3), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, }, - }, - '&.MuiAlert-filled': { - bgcolor: isDark ? 'rgba(239,83,80,0.15)' : '#9F2F2D', - borderColor: 'transparent', - color: isDark ? '#FFEBEE' : '#FFFFFF', - }, + '&.MuiAlert-filled': { + bgcolor: isDark ? alpha(p.light, 0.15) : p.dark, + borderColor: 'transparent', + color: isDark ? alpha(p.light, 0.9) : '#FFFFFF', + }, + } }, - colorWarning: { - bgcolor: isDark ? 'rgba(255,183,77,0.08)' : '#FBF3DB', - borderColor: isDark ? 'rgba(255,183,77,0.2)' : '#F0DCA0', - color: isDark ? '#FFD54F' : '#956400', - '& .MuiAlert-icon': { - color: isDark ? '#FFD54F' : '#956400', - }, - '&.MuiAlert-outlined': { - bgcolor: 'transparent', - borderColor: isDark ? 'rgba(255,183,77,0.3)' : '#F0DCA0', - color: isDark ? '#FFD54F' : '#956400', - '& .MuiAlert-icon': { - color: isDark ? '#FFD54F' : '#956400', + colorWarning: ({ theme }) => { + const isDark = theme.palette.mode === 'dark' + const p = theme.palette.warning + return { + bgcolor: isDark ? alpha(p.light, 0.08) : alpha(p.main, 0.08), + borderColor: isDark ? alpha(p.light, 0.2) : alpha(p.main, 0.2), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, + '&.MuiAlert-outlined': { + bgcolor: 'transparent', + borderColor: isDark ? alpha(p.light, 0.3) : alpha(p.main, 0.3), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, }, - }, - '&.MuiAlert-filled': { - bgcolor: isDark ? 'rgba(255,183,77,0.15)' : '#956400', - borderColor: 'transparent', - color: isDark ? '#FFF8E1' : '#FFFFFF', - }, + '&.MuiAlert-filled': { + bgcolor: isDark ? alpha(p.light, 0.15) : p.dark, + borderColor: 'transparent', + color: isDark ? alpha(p.light, 0.9) : '#FFFFFF', + }, + } }, - colorInfo: { - bgcolor: isDark ? 'rgba(121,134,203,0.08)' : '#E1F3FE', - borderColor: isDark ? 'rgba(121,134,203,0.2)' : '#B8D8F0', - color: isDark ? '#9FA8DA' : '#1F6C9F', - '& .MuiAlert-icon': { - color: isDark ? '#9FA8DA' : '#1F6C9F', - }, - '&.MuiAlert-outlined': { - bgcolor: 'transparent', - borderColor: isDark ? 'rgba(121,134,203,0.3)' : '#B8D8F0', - color: isDark ? '#9FA8DA' : '#1F6C9F', - '& .MuiAlert-icon': { - color: isDark ? '#9FA8DA' : '#1F6C9F', + colorInfo: ({ theme }) => { + const isDark = theme.palette.mode === 'dark' + const p = theme.palette.info + return { + bgcolor: isDark ? alpha(p.light, 0.08) : alpha(p.main, 0.08), + borderColor: isDark ? alpha(p.light, 0.2) : alpha(p.main, 0.2), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, + '&.MuiAlert-outlined': { + bgcolor: 'transparent', + borderColor: isDark ? alpha(p.light, 0.3) : alpha(p.main, 0.3), + color: isDark ? p.light : p.dark, + '& .MuiAlert-icon': { color: isDark ? p.light : p.dark }, }, - }, - '&.MuiAlert-filled': { - bgcolor: isDark ? 'rgba(121,134,203,0.15)' : '#1F6C9F', - borderColor: 'transparent', - color: isDark ? '#E8EAF6' : '#FFFFFF', - }, + '&.MuiAlert-filled': { + bgcolor: isDark ? alpha(p.light, 0.15) : p.dark, + borderColor: 'transparent', + color: isDark ? alpha(p.light, 0.9) : '#FFFFFF', + }, + } }, }, }, diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index 7ab3c73..bd1fef7 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -13,15 +13,16 @@ export function NotificationStack() { return ( {notifications.map((n) => ( @@ -31,41 +32,36 @@ export function NotificationStack() { autoHideDuration={n.autoHideDuration} onClose={() => dismissNotification(n.id)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} - sx={{ - '& .MuiSnackbarContent-root': { - borderRadius: 12, - border: '1px solid', - borderColor: 'rgba(0,0,0,0.06)', - bgcolor: 'background.paper', - boxShadow: '0 4px 20px rgba(0,0,0,0.08)', - }, - }} + sx={{ position: 'static' }} > dismissNotification(n.id)} sx={{ - bgcolor: 'transparent', - border: 'none', - boxShadow: 'none', - p: 1.5, + width: '100%', + px: 2, + py: 1.5, alignItems: 'center', '& .MuiAlert-icon': { - padding: 0, + py: 0.5, mr: 1.5, display: 'flex', alignItems: 'center', }, '& .MuiAlert-message': { - padding: 0, + py: 0.5, fontSize: '0.875rem', fontWeight: 600, + lineHeight: 1.5, }, '& .MuiAlert-action': { - padding: 0, - mr: 0, - ml: 1, + py: 0.5, + pr: 0, + ml: 1.5, + display: 'flex', + alignItems: 'center', + gap: 0.5, }, }} action={ @@ -79,11 +75,12 @@ export function NotificationStack() { navigate(n.actionPath!) }} sx={{ - fontWeight: 600, + fontWeight: 700, fontSize: '0.8125rem', px: 1.5, py: 0.5, borderRadius: 8, + whiteSpace: 'nowrap', color: 'success.main', '&:hover': { bgcolor: 'action.hover', diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 1ef69fbda3b67c968ddc7bfdadca507c2a212add..4c1a5c9385248278d832d0c77858d529261182bb 100644 GIT binary patch delta 321 zcmZoTAlh(1bb>Tv&_o$$#-PT8tqF_^`?(ny7?}9|82Fd-`)w99aN<`F=V7zwWVN?X z&MnAKHP0(BHZU+Q%rUpj%&RacF*V3dW1N?@cH@re=jJoYO@HmrB%&V9jjY4m&>W~E z8>Az-B0aq_H9H5SBQ^%4!;FK8{|E#B5&lP;1q){LPhY;CQPxJ5*`5(%8y3CX2w5y{ z;n}u5qT}D_AqgUP)daF0fB0Fz`>{KLPZqFaPvNeS^=R_H2M$X2BtqF_^`?>j-GcfY|G4T8G`)w99aN<`FXJNDFWVN?X z&MnAKDbG)?GB7aA&oQ^mEG#rODbCNxVw{(?^g;0SbMqPHroZ-Q65(KAV2A|in7(>F zqa+(hT3Z?MA5&xsjf(5hrr!Qa6C~LzER4ofOyTsJo2xxXH$n2u5jJ!hg z%2HWodq$iVvuxYI$kKprs6CS`E7(wwm6Fqs0QtNuTtHhG`A;zLpWr_M^p-FG^hkdu jb2gAVb4G;Ir%&)_QU-g1k) Date: Wed, 27 May 2026 23:25:02 +0500 Subject: [PATCH 23/31] fix: use native Snackbar positioning for NotificationStack instead of custom Stack wrapper --- .../NotificationStack/NotificationStack.tsx | 29 ++++++++---------- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index bd1fef7..6ff1266 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -1,9 +1,11 @@ import CloseIcon from '@mui/icons-material/Close' -import { Snackbar, Alert, Stack, IconButton, Button } from '@mui/material' +import { Snackbar, Alert, IconButton, Button } from '@mui/material' import { useUnit } from 'effector-react' import { useNavigate } from 'react-router-dom' import { $notifications, dismissNotification as dismissNotificationEvent } from '../../model/notification' +const GAP = 76 + export function NotificationStack() { const notifications = useUnit($notifications) const dismissNotification = useUnit(dismissNotificationEvent) @@ -12,27 +14,18 @@ export function NotificationStack() { if (notifications.length === 0) return null return ( - - {notifications.map((n) => ( + <> + {notifications.map((n, index) => ( dismissNotification(n.id)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} - sx={{ position: 'static' }} + sx={{ + bottom: `${88 + (notifications.length - 1 - index) * GAP}px !important`, + zIndex: 2000 + index, + }} > dismissNotification(n.id)} sx={{ width: '100%', + minWidth: 360, + maxWidth: 440, px: 2, py: 1.5, alignItems: 'center', @@ -100,6 +95,6 @@ export function NotificationStack() { ))} - + ) } diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 4c1a5c9385248278d832d0c77858d529261182bb..4f891b66c8c96a99918c518c5637d39996ab896f 100644 GIT binary patch delta 219 zcmZoTAlh(1bb>Tv(nJ|&#-zrCtqF|p=cx&>*>kem+b8E1Tv&_o$$#-PT8tqF|p=c)0q*>kem+b8E1B7#HT4TW01} z7?hYA Date: Wed, 27 May 2026 23:29:25 +0500 Subject: [PATCH 24/31] fix: match action button + close icon color to primary (price color); add shadow + backdrop blur to Alert --- .../NotificationStack/NotificationStack.tsx | 12 +++++++++--- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index 6ff1266..ad1f978 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -38,6 +38,8 @@ export function NotificationStack() { px: 2, py: 1.5, alignItems: 'center', + boxShadow: '0 4px 16px rgba(0,0,0,0.08)', + backdropFilter: 'blur(8px)', '& .MuiAlert-icon': { py: 0.5, mr: 1.5, @@ -56,7 +58,7 @@ export function NotificationStack() { ml: 1.5, display: 'flex', alignItems: 'center', - gap: 0.5, + gap: 1, }, }} action={ @@ -76,7 +78,7 @@ export function NotificationStack() { py: 0.5, borderRadius: 8, whiteSpace: 'nowrap', - color: 'success.main', + color: 'primary.main', '&:hover': { bgcolor: 'action.hover', }, @@ -85,7 +87,11 @@ export function NotificationStack() { {n.actionLabel} )} - dismissNotification(n.id)}> + dismissNotification(n.id)} + sx={{ color: 'primary.main' }} + > diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 4f891b66c8c96a99918c518c5637d39996ab896f..38bcc87f2ddfe1feee86b74249f1b2329024746d 100644 GIT binary patch delta 256 zcmZoTAlh(1bb>Tv+e8^>#XEqMbeR4l4)XKU}^@^VOmw1 zZk&>n4b-ve)LoDcYvxD%M>Y!<%;ulId_AL@F*enrvds33IBgf%wtTv(nJ|&#-zrCtqF`P`lN-Zj?Vw{(??)0PS=jJoYO@HmrB%&V9kEFw*GBFXT!w94!CDEkZ zB)7~Aq+{-6kPd6+Bm9px3l_}gpT2xOqna@`)%>!|_KY}f7udFek+T8G7<(owRpV^E2{KpWx4=40a!*KwAJ)TL5!g0L!ufRsjIy!c!Cg From 9aea74db9663183b39f3dbaf29b3ca4d3d56fe65 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 27 May 2026 23:35:22 +0500 Subject: [PATCH 25/31] fix: use theme callback in sx to force Alert icon/text color to primary.main; add backdrop-filter + shadow --- .../NotificationStack/NotificationStack.tsx | 13 ++++++------- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index ad1f978..ce278c6 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -31,20 +31,23 @@ export function NotificationStack() { severity={n.type} variant="standard" onClose={() => dismissNotification(n.id)} - sx={{ + sx={(theme) => ({ width: '100%', minWidth: 360, maxWidth: 440, px: 2, py: 1.5, alignItems: 'center', + color: `${theme.palette.primary.main} !important`, boxShadow: '0 4px 16px rgba(0,0,0,0.08)', + WebkitBackdropFilter: 'blur(8px)', backdropFilter: 'blur(8px)', '& .MuiAlert-icon': { py: 0.5, mr: 1.5, display: 'flex', alignItems: 'center', + color: `${theme.palette.primary.main} !important`, }, '& .MuiAlert-message': { py: 0.5, @@ -60,7 +63,7 @@ export function NotificationStack() { alignItems: 'center', gap: 1, }, - }} + })} action={ <> {n.actionLabel && n.actionPath && ( @@ -87,11 +90,7 @@ export function NotificationStack() { {n.actionLabel} )} - dismissNotification(n.id)} - sx={{ color: 'primary.main' }} - > + dismissNotification(n.id)} sx={{ color: 'primary.main' }}> diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 38bcc87f2ddfe1feee86b74249f1b2329024746d..91786af4a7c823835c4549b60a855894844227d2 100644 GIT binary patch delta 219 zcmZoTAlh(1bb>VFu8A_vjJp~Wwk9yXpQk3qX3xoLZ=al7ke`}kY-Da=V3wU@Zkd^t z1LT=n6fw@r+U~G_`nmaxa?@Y?Gl{5&izDgCO-(E_FfcH#$S=#W%qz@J$xqG$>e!+G zd^=Fbe|}?Z3dCiZ?HO@eD7I|_89GH&tGm1~2;LoHCb_AnXTL4pA N0CQUa%d!Ag0RU%GNPhqT delta 219 zcmZoTAlh(1bb>Tv+e8^>#kem+b8E1X=am~6nB?Y|TV|%3 z7Ubp{ml-h5%i6e%clx>cjB?Xo`!k8Chl?WVNG-`UF)%PS1L-iWDor;|$;k%l*mUad zcA$>`{KnW6h{`hCGvc&RWZMSDhyAQzMIdV>8AY}^FdgS-6rDc7pGg_)2u6{%0H(G8 M=C%NqWdW=L00HDj Date: Wed, 27 May 2026 23:43:22 +0500 Subject: [PATCH 26/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationStack/NotificationStack.tsx | 3 ++- server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/shared/ui/NotificationStack/NotificationStack.tsx b/client/src/shared/ui/NotificationStack/NotificationStack.tsx index ce278c6..643828f 100644 --- a/client/src/shared/ui/NotificationStack/NotificationStack.tsx +++ b/client/src/shared/ui/NotificationStack/NotificationStack.tsx @@ -39,9 +39,10 @@ export function NotificationStack() { py: 1.5, alignItems: 'center', color: `${theme.palette.primary.main} !important`, - boxShadow: '0 4px 16px rgba(0,0,0,0.08)', + boxShadow: '0 4px 16px rgba(0,0,0,0.3)', WebkitBackdropFilter: 'blur(8px)', backdropFilter: 'blur(8px)', + backgroundColor: 'rgba(255,255,255,0.7)', '& .MuiAlert-icon': { py: 0.5, mr: 1.5, diff --git a/server/prisma/prisma/dev.db b/server/prisma/prisma/dev.db index 91786af4a7c823835c4549b60a855894844227d2..cfb75a9204b7381ae7fea6c32e4da753815cca47 100644 GIT binary patch delta 256 zcmZoTAlh(1bb>VFg^4oGj29Xcwk9yH>}Oui@3&ddz=>ZyT#C(}lhxinIkzA`wLH%> z#lXOzpd!C4r!*-)+c-ZtmvLU!{%XVN=jJoYO@HmrB%&TJiKL?-yDAT;BMqb@J1x;H zqcp1msAE@23rL4G^AY|>n*|GI^G{#Co>9#hn`%i}W_w1Qwo7f>z{uHvWQ;wN6)RW^ n$b3mgscjBS$N3p0r%&)_QU<$^QK~I~sV#uHEr4ZN0IL81U4B=P delta 256 zcmZoTAlh(1bb>VFu8A_vjJp~Wwk9yH>}U4lU%pw;z=>ZyT#U`0lhxinIkzA`HOJV< z+`zyrJICBIGb;zkGqosUoR_uTVgK}V^BLu)zxHPmQ4beK(vh2*SY}{gU|f-3mSdS$ zn4OZJoCnmgL;pEQhc)vf{v(?O3ug0AU%sAE%@~_%aam@2Mx3^bZQH=e*??q>J(CqH pSPRH}Nk*}44ot`S8O5hh@Mls6yN^+ Date: Thu, 28 May 2026 11:47:53 +0500 Subject: [PATCH 27/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 2786 ++++++++++------- .../__tests__/get-api-error-message.test.ts | 6 +- .../src/shared/lib/get-api-error-message.ts | 4 +- .../src/shared/lib/use-mutation-with-toast.ts | 2 +- 4 files changed, 1649 insertions(+), 1149 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 3efb283..e9abc11 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -75,11 +75,15 @@ }, "node_modules/@adobe/css-tools": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", "dev": true, "license": "MIT" }, "node_modules/@asamuzakjp/css-color": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", "dev": true, "license": "MIT", "dependencies": { @@ -92,11 +96,15 @@ }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC" }, "node_modules/@babel/code-frame": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", @@ -109,6 +117,8 @@ }, "node_modules/@babel/compat-data": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -117,9 +127,10 @@ }, "node_modules/@babel/core": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -145,27 +156,17 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/helpers": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", - "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -174,6 +175,8 @@ }, "node_modules/@babel/generator": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.7", @@ -188,6 +191,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { @@ -203,6 +208,8 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -211,6 +218,8 @@ }, "node_modules/@babel/helper-globals": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -218,6 +227,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.29.7", @@ -229,6 +240,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { @@ -245,6 +258,8 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -252,6 +267,8 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -259,14 +276,32 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/parser": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.7" @@ -280,6 +315,8 @@ }, "node_modules/@babel/runtime": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -287,6 +324,8 @@ }, "node_modules/@babel/template": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", @@ -299,6 +338,8 @@ }, "node_modules/@babel/traverse": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", @@ -315,6 +356,8 @@ }, "node_modules/@babel/types": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", @@ -326,6 +369,8 @@ }, "node_modules/@boundaries/elements": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@boundaries/elements/-/elements-2.0.1.tgz", + "integrity": "sha512-sAWO3D8PFP6pBXdxxW93SQi/KQqqhE2AAHo3AgWfdtJXwO6bfK6/wUN81XnOZk0qRC6vHzUEKhjwVD9dtDWvxg==", "dev": true, "license": "MIT", "dependencies": { @@ -341,6 +386,8 @@ }, "node_modules/@csstools/color-helpers": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", "dev": true, "funding": [ { @@ -359,6 +406,8 @@ }, "node_modules/@csstools/css-calc": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", "dev": true, "funding": [ { @@ -381,6 +430,8 @@ }, "node_modules/@csstools/css-color-parser": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", "dev": true, "funding": [ { @@ -407,6 +458,8 @@ }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", "dev": true, "funding": [ { @@ -419,7 +472,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -429,6 +481,8 @@ }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", "dev": true, "funding": [ { @@ -441,13 +495,14 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } }, "node_modules/@dicebear/adventurer": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-9.4.2.tgz", + "integrity": "sha512-jqYp834ZmGDA9HBBDQAdgF1O2UTCwHF4vVrktXWa2Dppp1JczPL5HnVOWsjtrLmXNn61Wd6OLmBb2e6rhzp3ig==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -458,6 +513,8 @@ }, "node_modules/@dicebear/avataaars": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-9.4.2.tgz", + "integrity": "sha512-3x9jKFkOkFSPmpTbt9xvhiU2E1GX7beCSsX0tXRUShj8x6+5Ks9yBRT1VlkySbnXrZ/GglADGg7vJ/D2uIx1Yw==", "license": "See LICENSE file", "engines": { "node": ">=18.0.0" @@ -468,6 +525,8 @@ }, "node_modules/@dicebear/big-ears": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-9.4.2.tgz", + "integrity": "sha512-mNfz3ppNA7UBq0IO3nXCiV5pFPG7c1DfzRB0foNU2Wo1XXT8FIcSY2BvDlYqorZTOUOz7dHb0vx06hqvG0HP5w==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -478,6 +537,8 @@ }, "node_modules/@dicebear/big-smile": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-9.4.2.tgz", + "integrity": "sha512-hmT5i7rcPPhStjZyg28pbIhdTnnMBzK3RObI0vKCpY30EFrzaPkkdDL6Ck5fAFBdvDIW1EpOJkenyR0XPmhgbQ==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -488,6 +549,8 @@ }, "node_modules/@dicebear/bottts": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-9.4.2.tgz", + "integrity": "sha512-tsx+dII7EFUCVA8URj66G1GqORCCVduCAx4dY2prEY2IeFianVpkntXuFsWZ9BBGx1NZFndvDith5oTwKMQPbQ==", "license": "See LICENSE file", "engines": { "node": ">=18.0.0" @@ -498,8 +561,9 @@ }, "node_modules/@dicebear/core": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-9.4.2.tgz", + "integrity": "sha512-MF0042+Z3s8PGZKZLySfhft28bUa3B1iq0e5NSjCvY8gfMi5aIH/iRJGRJa1N9Jz1BNkxYb4yvJ/N9KO8Z6Y+w==", "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -509,6 +573,8 @@ }, "node_modules/@dicebear/croodles": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-9.4.2.tgz", + "integrity": "sha512-6VoO0JviIf7dKKMBTL/SMXxWhnXHaZuzufX90G0nXxS77ELG1YkGNMaZzawizN4C09Gbya2gJkozqrWiJN/aGw==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -519,6 +585,8 @@ }, "node_modules/@dicebear/fun-emoji": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-9.4.2.tgz", + "integrity": "sha512-kqB6LPkdYCdEU/mwbyz34xLzoNUKL6ARcoo3fr5ASq9D6ZE07qIKybC3xv5+CPz7VmspJ1Q3c/VVWVMDRP7Twg==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -529,6 +597,8 @@ }, "node_modules/@dicebear/identicon": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-9.4.2.tgz", + "integrity": "sha512-JVDSmZsv11mSWqwAktK5x9Bslht2xY3TFUn8xzu6slAYe1Z7hEXZ76eb+UJ6F4qEzdwZ7xPWzAS6Nb0Y3A0pww==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -539,6 +609,8 @@ }, "node_modules/@dicebear/initials": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-9.4.2.tgz", + "integrity": "sha512-yePuIUasmwtl9IrtB6rEzE/zb5fImKP/neW0CdcTC2MwLgMuP1GLHEGRgg1zI8exIh+PMv1YdLGyyUuRTE2Qpw==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -549,6 +621,8 @@ }, "node_modules/@dicebear/lorelei": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-9.4.2.tgz", + "integrity": "sha512-YMv6vnriW6VLFDsreKuOnUFFno6SRe7+7X7R7zPY0rZ+MaHX9V3jcioIG+1PSjIHEDfOLUHpr5vd1JBWv8y7UA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -559,6 +633,8 @@ }, "node_modules/@dicebear/micah": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-9.4.2.tgz", + "integrity": "sha512-e4D3W/OlChSsLo7Llwsy0J18vk0azJqF/uFoY+EKACCNHBc1HGNsqVvu2CTf+OWOA8wTyAK6UkjBN5p01r7D+g==", "license": "(MIT AND CC-BY-4.0)", "engines": { "node": ">=18.0.0" @@ -569,6 +645,8 @@ }, "node_modules/@dicebear/notionists": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-9.4.2.tgz", + "integrity": "sha512-ZCySq+nxcD/x4xyYgytcj2N9uY3gxrL+qpnmOdp2BdA221KacVrxlsUPpIgEMqxS2rMmBQXfxg129Pzn4ycIpA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -579,6 +657,8 @@ }, "node_modules/@dicebear/pixel-art": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-9.4.2.tgz", + "integrity": "sha512-peHf7oKICDgBZ8dUyj+txPnS7VZEWgvKE+xW4mNQqBt6dYZIjmva2shOVHn0b1JU+FDxMx3uIkWVixKdUq4WGg==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -589,6 +669,8 @@ }, "node_modules/@dicebear/rings": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-9.4.2.tgz", + "integrity": "sha512-Pc3ymWrRDQPJFNrbbLt7RJrzGvUuuxUiDkrfLhoVE+B6mZWEL1PC78DPbS1yUWYLErJOpJuM2GSwXmTbVjWf+g==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -599,6 +681,8 @@ }, "node_modules/@dicebear/shapes": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-9.4.2.tgz", + "integrity": "sha512-AFL6jAaiLztvcqyq+ds+lWZu6Vbp3PlGWhJeJRm842jxtiluJpl6r4f6nUXP2fdMz7MNpDzXfLooQK9E04NbUQ==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -609,6 +693,8 @@ }, "node_modules/@dicebear/thumbs": { "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-9.4.2.tgz", + "integrity": "sha512-ccWvDBqbkWS5uzHbsg5L6uML6vBfX7jT3J3jHCQksvz8haHItxTK02w+6e1UavZUsvza4lG5X/XY3eji3siJ4Q==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -617,6 +703,29 @@ "@dicebear/core": "^9.0.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -630,6 +739,8 @@ }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.16.7", @@ -647,6 +758,8 @@ }, "node_modules/@emotion/cache": { "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0", @@ -658,10 +771,14 @@ }, "node_modules/@emotion/hash": { "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", "license": "MIT" }, "node_modules/@emotion/is-prop-valid": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0" @@ -669,12 +786,15 @@ }, "node_modules/@emotion/memoize": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", "license": "MIT" }, "node_modules/@emotion/react": { "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -696,6 +816,8 @@ }, "node_modules/@emotion/serialize": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.2", @@ -707,12 +829,15 @@ }, "node_modules/@emotion/sheet": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", "license": "MIT" }, "node_modules/@emotion/styled": { "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -733,10 +858,14 @@ }, "node_modules/@emotion/unitless": { "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", "license": "MIT" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", "license": "MIT", "peerDependencies": { "react": ">=16.8.0" @@ -744,10 +873,14 @@ }, "node_modules/@emotion/utils": { "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", "license": "MIT" }, "node_modules/@emotion/weak-memoize": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { @@ -1024,6 +1157,8 @@ }, "node_modules/@esbuild/linux-x64": { "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -1192,6 +1327,8 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1209,6 +1346,8 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1220,6 +1359,8 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -1228,6 +1369,8 @@ }, "node_modules/@eslint/config-array": { "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1241,6 +1384,8 @@ }, "node_modules/@eslint/config-helpers": { "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1252,6 +1397,8 @@ }, "node_modules/@eslint/core": { "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1263,6 +1410,8 @@ }, "node_modules/@eslint/eslintrc": { "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { @@ -1285,6 +1434,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { @@ -1296,6 +1447,8 @@ }, "node_modules/@eslint/js": { "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1307,6 +1460,8 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1315,6 +1470,8 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1327,19 +1484,36 @@ }, "node_modules/@floating-ui/core": { "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "license": "MIT", "optional": true, "dependencies": { "@floating-ui/utils": "^0.2.11" } }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, "node_modules/@floating-ui/utils": { "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "license": "MIT", "optional": true }, "node_modules/@humanfs/core": { "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1351,6 +1525,8 @@ }, "node_modules/@humanfs/node": { "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1364,6 +1540,8 @@ }, "node_modules/@humanfs/types": { "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1372,6 +1550,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1384,6 +1564,8 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1396,6 +1578,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1404,6 +1588,8 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1413,6 +1599,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1420,10 +1608,14 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1432,33 +1624,45 @@ }, "node_modules/@mapbox/jsonlint-lines-primitives": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", "engines": { "node": ">= 0.6" } }, "node_modules/@mapbox/point-geometry": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", + "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", "license": "ISC" }, "node_modules/@mapbox/tiny-sdf": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", + "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", "license": "BSD-2-Clause" }, "node_modules/@mapbox/unitbezier": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", "license": "BSD-2-Clause" }, "node_modules/@mapbox/vector-tile": { - "version": "2.0.4", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.5.tgz", + "integrity": "sha512-pXj8m7KTsqZt+1jsE0xIpGvqTSbblfkuEJL/NJmNePMtEwxO8V3XMDo9WMSfDeqHvCtBI9Lmt4mGcGR10zecmw==", "license": "BSD-3-Clause", "dependencies": { "@mapbox/point-geometry": "~1.1.0", "@types/geojson": "^7946.0.16", - "pbf": "^4.0.1" + "pbf": "^4.0.2" } }, "node_modules/@mapbox/whoots-js": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", "license": "ISC", "engines": { "node": ">=6.0.0" @@ -1466,6 +1670,8 @@ }, "node_modules/@maplibre/geojson-vt": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.0.tgz", + "integrity": "sha512-2eIY4gZxeKIVOZVNkAMb+5NgXhgsMQpOveTQAvnp53LYqHGJZDidk7Ew0Tged9PThidpbS+NFTh0g4zivhPDzQ==", "license": "ISC", "dependencies": { "kdbush": "^4.0.2" @@ -1473,6 +1679,8 @@ }, "node_modules/@maplibre/maplibre-gl-style-spec": { "version": "24.8.5", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.8.5.tgz", + "integrity": "sha512-EzEJmMt6thioRH7GI9LWS7ahXTcAhAPGWCe6oTP2Ps4YnsXOOAfeqx854lZaiDnwURfHmcCKV1mr6oo0i23x6w==", "license": "ISC", "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", @@ -1489,7 +1697,9 @@ } }, "node_modules/@maplibre/mlt": { - "version": "1.1.10", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.11.tgz", + "integrity": "sha512-dKvjKdITw9d0y3ndGkSqLUEpWCizMtdq8NB06cHohH/JZ2sJoM7dClR9wzJLUWykjbw9RXDFmhjjNBnNW27mzw==", "license": "(MIT OR Apache-2.0)", "dependencies": { "@mapbox/point-geometry": "^1.1.0" @@ -1497,6 +1707,8 @@ }, "node_modules/@maplibre/vt-pbf": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.0.tgz", + "integrity": "sha512-jIvp8F5hQCcreqOOpEt42TJMUlsrEcpf/kI1T2v85YrQRV6PPXUcEXUg5karKtH6oh47XJZ4kHu56pUkOuqA7w==", "license": "MIT", "dependencies": { "@mapbox/point-geometry": "^1.1.0", @@ -1510,10 +1722,14 @@ }, "node_modules/@maplibre/vt-pbf/node_modules/@maplibre/geojson-vt": { "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-5.0.4.tgz", + "integrity": "sha512-KGg9sma45S+stfH9vPCJk1J0lSDLWZgCT9Y8u8qWZJyjFlP8MNP1WGTxIMYJZjDvVT3PDn05kN1C95Sut1HpgQ==", "license": "ISC" }, "node_modules/@mui/core-downloads-tracker": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-9.0.1.tgz", + "integrity": "sha512-GzamIIhZ1bH77dq7eKaeyRgJdkypsxin4jBFq2EMs4lBWRR0LFO1CSVMsoebn/VvjcNrnrOrjy48MkrkQUK2iw==", "license": "MIT", "funding": { "type": "opencollective", @@ -1551,7 +1767,6 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.1.tgz", "integrity": "sha512-voyCpeUxcSWLN7KPZuq0pGCIt726T9K6kiVM3XUcywZDAlZSarLHaUxJVQpospbjjOzN53hwyjo8s6KoWl6utw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.29.2", "@mui/core-downloads-tracker": "^9.0.1", @@ -1598,6 +1813,8 @@ }, "node_modules/@mui/private-theming": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-9.0.1.tgz", + "integrity": "sha512-pSIGq4Yw749KHEwlkYZWVERgHgwJELP6ODtBNUfV8V4oIb5H+h7IQDFXuk/b2oQccODK1enJAtiEzlgLZmq+8g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2", @@ -1623,6 +1840,8 @@ }, "node_modules/@mui/styled-engine": { "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-9.0.0.tgz", + "integrity": "sha512-9RLGdX4Jg0aQPRuvqh/OLzYSPlgd5zyEw5/1HIRfdavSiOd03WtUaGZH9/w1RoTYuRKwpgy0hpIFaMHIqPVIWg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2", @@ -1655,6 +1874,8 @@ }, "node_modules/@mui/system": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-9.0.1.tgz", + "integrity": "sha512-WvlioaLxk6ewUIOfh0StxUvOPDS1mCfzaulcudsL1brZNXuh0N9FMk7RpH7ImJKjEz412SEy/V/yvqmtxbqxCQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2", @@ -1693,6 +1914,8 @@ }, "node_modules/@mui/types": { "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-9.0.0.tgz", + "integrity": "sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2" @@ -1708,6 +1931,8 @@ }, "node_modules/@mui/utils": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.0.1.tgz", + "integrity": "sha512-f3UO3jNN1pYg5zxqXC81Bvv8hx5ACcYc0387382ZI7M5ono1heIwHYLrKsz85myguWdeVKPRZGmDdynWUBjK2g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2", @@ -1755,6 +1980,8 @@ }, "node_modules/@oxc-project/types": { "version": "0.132.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", + "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", "dev": true, "license": "MIT", "funding": { @@ -1763,11 +1990,15 @@ }, "node_modules/@package-json/types": { "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@package-json/types/-/types-0.0.12.tgz", + "integrity": "sha512-uu43FGU34B5VM9mCNjXCwLaGHYjXdNincqKLaraaCW+7S2+SmiBg1Nv8bPnmschrIfZmfKNY9f3fC376MRrObw==", "dev": true, "license": "MIT" }, "node_modules/@pkgr/core": { "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", "engines": { @@ -1779,6 +2010,8 @@ }, "node_modules/@popperjs/core": { "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", "funding": { "type": "opencollective", @@ -1878,6 +2111,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1895,6 +2131,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1912,6 +2151,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1929,6 +2171,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1940,10 +2185,15 @@ }, "node_modules/@rolldown/binding-linux-x64-gnu": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", + "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1961,6 +2211,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2023,25 +2276,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", - "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, "license": "MIT" }, @@ -2137,6 +2375,9 @@ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2151,6 +2392,9 @@ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2165,6 +2409,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2179,6 +2426,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2193,6 +2443,9 @@ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2207,6 +2460,9 @@ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2221,6 +2477,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2235,6 +2494,9 @@ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2249,6 +2511,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2263,6 +2528,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2277,6 +2545,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2285,10 +2556,15 @@ }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2303,6 +2579,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2395,6 +2674,8 @@ }, "node_modules/@tanstack/query-core": { "version": "5.100.14", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.14.tgz", + "integrity": "sha512-5X41dGpxgeaHISCRW2oYwcSycZeULZzAunaudXT9ov1KOTj9xwt0CH6hbwqP1/z74ZWF7rYFnDpyYH07XFcZew==", "license": "MIT", "funding": { "type": "github", @@ -2403,6 +2684,8 @@ }, "node_modules/@tanstack/react-query": { "version": "5.100.14", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.14.tgz", + "integrity": "sha512-oOr6aRdSFEwWhzxEkD/9ZcItM3+LjBSkeVmadWKwUssAHTsqd/7bOjWrX4AbvEkoEhgAxzN0Xk6H/aYzXiYBAw==", "license": "MIT", "dependencies": { "@tanstack/query-core": "5.100.14" @@ -2417,6 +2700,8 @@ }, "node_modules/@testing-library/dom": { "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", "peer": true, @@ -2434,18 +2719,10 @@ "node": ">=18" } }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "dequal": "^2.0.3" - } - }, "node_modules/@testing-library/jest-dom": { "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", "dev": true, "license": "MIT", "dependencies": { @@ -2462,23 +2739,17 @@ "yarn": ">=1" } }, - "node_modules/@testing-library/jest-dom/node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", "dev": true, "license": "MIT" }, "node_modules/@testing-library/react": { "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, "license": "MIT", "dependencies": { @@ -2519,8 +2790,9 @@ }, "node_modules/@tiptap/core": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.6.tgz", + "integrity": "sha512-MRB3pHz4Oxqmcawh0cQ5iOGdY5xtNYp/1CoK7hdTLzw5K0C6/gTC2VvanB1R4INaB6EpBkxG/GiWkVirDRnuXw==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2531,6 +2803,8 @@ }, "node_modules/@tiptap/extension-blockquote": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.23.6.tgz", + "integrity": "sha512-2RmnqNqTltZ2k1F7IfjoDNs935Uq4rRDR7d98mqkg3OlDktcQIyBpv0t9dTay6H5bkQeZUuS8ogK2S1E8Edjug==", "license": "MIT", "funding": { "type": "github", @@ -2542,6 +2816,8 @@ }, "node_modules/@tiptap/extension-bold": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.23.6.tgz", + "integrity": "sha512-1LMhjnytdbbhWHSoOwnLxZAOQZWPkKyXVCNmaIk0Mhi4tLPUXptG4qKS5sVYTCveE5H6IBPFrbgBFi5dMI6krA==", "license": "MIT", "funding": { "type": "github", @@ -2553,6 +2829,8 @@ }, "node_modules/@tiptap/extension-bubble-menu": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.23.6.tgz", + "integrity": "sha512-Mwkyp9LkDHFbqmWRIkp63FinRxFu3ajC4qSb9t4mnHsb4kAdbNLLsGtbFg+le0SWk4CxGwAOwM7SzeJ+6UGqCA==", "license": "MIT", "optional": true, "dependencies": { @@ -2569,6 +2847,8 @@ }, "node_modules/@tiptap/extension-bullet-list": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.23.6.tgz", + "integrity": "sha512-RMRgfXZykr/13X8UBOwvpgysVOo9KchwqMoEbvqQSj4YFfU56iIn59C8sbxiQ1sKfeltUf0wH4fPc0I4iwKqAA==", "license": "MIT", "funding": { "type": "github", @@ -2580,6 +2860,8 @@ }, "node_modules/@tiptap/extension-code": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.23.6.tgz", + "integrity": "sha512-KG8KXFYyLrtYvT7AZ1WGV61ofx8pDe5g9pH658MERxqQGii+Pyfc6xkz04l7XeBts/7+571UQp/0O7i/z560TA==", "license": "MIT", "funding": { "type": "github", @@ -2591,6 +2873,8 @@ }, "node_modules/@tiptap/extension-code-block": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.23.6.tgz", + "integrity": "sha512-4kccgcn5yHThxrzsIhJny3EwfEZYIk+BjUCL4uIuzOyWvExtGhZ6JMHVCZeMhI8D1/bX1LNkkAKN5DXPzH4lXQ==", "license": "MIT", "funding": { "type": "github", @@ -2603,6 +2887,8 @@ }, "node_modules/@tiptap/extension-document": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.23.6.tgz", + "integrity": "sha512-XDAIgG9KcKumFM9KJWUEUhXPbFIhhl47bfy5GknareWTRKke85rcoj/oxKKO9ihLZr8JfpbXjqnS4SCm5yhYPw==", "license": "MIT", "funding": { "type": "github", @@ -2614,6 +2900,8 @@ }, "node_modules/@tiptap/extension-dropcursor": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.23.6.tgz", + "integrity": "sha512-+XWEoRKf3lXxi7Le1aOM2xU1XHwxICGpXjT3m4QaYqUgIpsq8gQEuso6kVg8DnTD7biKQs6+oIQ0o2b/gTW9WA==", "license": "MIT", "funding": { "type": "github", @@ -2625,6 +2913,8 @@ }, "node_modules/@tiptap/extension-floating-menu": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.23.6.tgz", + "integrity": "sha512-2kjuDcEq69lEcECl75xqY5MyzUSh2zcC5aLrpwP1WwhJz5bxsIFHiaps5AP6h9R4A+ZBj5b2haay2Y1wDUU3VA==", "license": "MIT", "optional": true, "funding": { @@ -2639,6 +2929,8 @@ }, "node_modules/@tiptap/extension-gapcursor": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.23.6.tgz", + "integrity": "sha512-wbKmxXsszxWacEkrHucRpSQbiKjz4fmOebD6OVyL9AcrmlbxNk8vcM3iyh/8cVeRy09XY+morM165t/u7/z4IQ==", "license": "MIT", "funding": { "type": "github", @@ -2650,6 +2942,8 @@ }, "node_modules/@tiptap/extension-hard-break": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.23.6.tgz", + "integrity": "sha512-KeUm+tkUfIVSX9QM9XOIhaay0Fn36sLKUo5NVYjN3uJaxFvaZXZmTlxdO85OTdgF2P5sqh9LomrIgliaFRGk4w==", "license": "MIT", "funding": { "type": "github", @@ -2661,6 +2955,8 @@ }, "node_modules/@tiptap/extension-heading": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.23.6.tgz", + "integrity": "sha512-A/0jPhxnUh9THSZymlu0OGPZe1wdFdwHAXnRCmqvYUCwJjrG7LCC/ahzmcj1tcNzI9hgHyuYPSfev8RXYrNu/w==", "license": "MIT", "funding": { "type": "github", @@ -2672,6 +2968,8 @@ }, "node_modules/@tiptap/extension-horizontal-rule": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.23.6.tgz", + "integrity": "sha512-hEUlz4H+I64r+TH6LCuNCRgO7JTHncXGmx9+WbU69EOfY8O0ZurcgeJc8HeiAKL+r9YuC1e5YHfFxgCaaC0jlg==", "license": "MIT", "funding": { "type": "github", @@ -2684,6 +2982,8 @@ }, "node_modules/@tiptap/extension-italic": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.23.6.tgz", + "integrity": "sha512-wol5KdwCPAvpiYhH9PLlvO8ZnJHwZtIboVevrfOGgBcKlXRA3dedR4OAMXHnUtkkzu9KtliLg1+TYzEx4JZG9Q==", "license": "MIT", "funding": { "type": "github", @@ -2695,6 +2995,8 @@ }, "node_modules/@tiptap/extension-link": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.23.6.tgz", + "integrity": "sha512-KNZz7z7P2/qbQsx5bPAbSPjrKDg1VHsedGlLHJCr8U2VRD5VgmDLkMpkouP1CsDg15qgyUKv/nDib5KgPpLNWA==", "license": "MIT", "dependencies": { "linkifyjs": "^4.3.3" @@ -2710,8 +3012,9 @@ }, "node_modules/@tiptap/extension-list": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.6.tgz", + "integrity": "sha512-z6vj9+Qht2sjdQkyyHcUpsC/yCIZqTrQiyHDhs/HGKrfvoANyAZGpqdNeKf1wSyjIso+27tQuIH5NDfk8ygyNw==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2723,6 +3026,8 @@ }, "node_modules/@tiptap/extension-list-item": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.23.6.tgz", + "integrity": "sha512-3zzyhdkUWcHVpXuvy6KiIwjh29rbH6gEDEqPQqHLrl1XGnO9pnShC7pSHctlCDjmcx3O4n9cd4QMtVBlUerbiA==", "license": "MIT", "funding": { "type": "github", @@ -2734,6 +3039,8 @@ }, "node_modules/@tiptap/extension-list-keymap": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.23.6.tgz", + "integrity": "sha512-x8bPcLViGzg/RAmQM/XtmfqIwQ/Pv9Q8mkd+OgfUiTqjeJqKwVQmiqbLFNa7zw81+H61M+HDU+qGAaQ3vRIMjw==", "license": "MIT", "funding": { "type": "github", @@ -2745,6 +3052,8 @@ }, "node_modules/@tiptap/extension-ordered-list": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.23.6.tgz", + "integrity": "sha512-1m/wWB/ZtXcmG2vNdiUkCqsOgqv5vBjCv/mVaHhF9OvV+zQS8YDjoWE7zEuT/GgELdT77Xq8lHrn4nCDudB3/A==", "license": "MIT", "funding": { "type": "github", @@ -2756,6 +3065,8 @@ }, "node_modules/@tiptap/extension-paragraph": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.23.6.tgz", + "integrity": "sha512-+7m58LUSncodjrIyXks4RZ3tLNYrvgT77wRR4l3HnM5OABY3GDsDTqi7c1t1yI29NVOSk/DUacqy6UwYAj1DGg==", "license": "MIT", "funding": { "type": "github", @@ -2767,6 +3078,8 @@ }, "node_modules/@tiptap/extension-placeholder": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.23.6.tgz", + "integrity": "sha512-8I6b2aevF74aLgymKMxbDxSLxWA2y+2dh0zZDeI8sRZ2m6WHHes+Kyuuwkq1HIPcR+ZLpbec74cmf6lcL/yvqQ==", "license": "MIT", "funding": { "type": "github", @@ -2778,6 +3091,8 @@ }, "node_modules/@tiptap/extension-strike": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.23.6.tgz", + "integrity": "sha512-oF7FEZ37f15aCe5kPgzGDYf/m+hr7VdQ/Ko/Hds/UM9pX7AG1fdtmRrl6wqkRqDM/incZaC/AQR2/Dpo2VCNGQ==", "license": "MIT", "funding": { "type": "github", @@ -2789,6 +3104,8 @@ }, "node_modules/@tiptap/extension-text": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.23.6.tgz", + "integrity": "sha512-ipoC2TkIAIOTiF5ByiGgvQB1DqDyfP90wrUB3mohBcgvp7lQnwHszCDGv8dNnmcUek8uXV/uoLu2VXeVQlxjPA==", "license": "MIT", "funding": { "type": "github", @@ -2800,6 +3117,8 @@ }, "node_modules/@tiptap/extension-underline": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.23.6.tgz", + "integrity": "sha512-P55wGIZGYTVH92Fq0cgI4/O9AhLCaJC3hhxg15RSERP5/YegM9eJHDK/GQ1EE/DvYA+xpYGOV6agKwAUqfA/Iw==", "license": "MIT", "funding": { "type": "github", @@ -2811,8 +3130,9 @@ }, "node_modules/@tiptap/extensions": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.6.tgz", + "integrity": "sha512-X09/Db1teB+ifXzDGVVFmOeQRx7wTAayE9/280spxpsHkHZvJ5bHRvWIzUzviMIjbBz+NPDIKYPK7gMfh9iaig==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2824,8 +3144,9 @@ }, "node_modules/@tiptap/pm": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.6.tgz", + "integrity": "sha512-in5CaMaWlJcH2A1q6GJKFtrodE8WLS3M9tIi/f89jPmIVHJShpodC0KZDNyJkrVBQomYk0DEh86Utm6ASXzQww==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -2847,6 +3168,8 @@ }, "node_modules/@tiptap/react": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.23.6.tgz", + "integrity": "sha512-Tw9KZkYqFMk3vaJAEQKqEYIO/iq3cSJe7OUEGBul4k4GaMQeLItLf5EYhUd0GIPXci1WVVPNntKJsHfX25M37w==", "license": "MIT", "dependencies": { "@types/use-sync-external-store": "^0.0.6", @@ -2872,6 +3195,8 @@ }, "node_modules/@tiptap/starter-kit": { "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.23.6.tgz", + "integrity": "sha512-gykwtGWrnWCmtql1hid3opac/KV8zQvOAnu3bTqIqcHrn1FusbUwKmNzavSbfGvcktHM3hFjb35W48JyVLyu/A==", "license": "MIT", "dependencies": { "@tiptap/core": "^3.23.6", @@ -2917,11 +3242,16 @@ }, "node_modules/@types/aria-query": { "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/chai": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -2931,57 +3261,74 @@ }, "node_modules/@types/deep-eql": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, "node_modules/@types/geojson": { "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, "node_modules/@types/node": { "version": "24.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", + "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } }, "node_modules/@types/parse-json": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, "node_modules/@types/prop-types": { "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", "license": "MIT" }, "node_modules/@types/react": { "version": "19.2.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", + "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } }, "node_modules/@types/react-transition-group": { "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", "license": "MIT", "peerDependencies": { "@types/react": "*" @@ -2989,6 +3336,8 @@ }, "node_modules/@types/supercluster": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", "license": "MIT", "dependencies": { "@types/geojson": "*" @@ -2996,18 +3345,60 @@ }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", "license": "MIT" }, - "node_modules/@typescript-eslint/parser": { - "version": "8.59.4", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.0.tgz", + "integrity": "sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/type-utils": "8.60.0", + "@typescript-eslint/utils": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.60.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.0.tgz", + "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", "debug": "^4.4.3" }, "engines": { @@ -3023,12 +3414,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.0.tgz", + "integrity": "sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.4", - "@typescript-eslint/types": "^8.59.4", + "@typescript-eslint/tsconfig-utils": "^8.60.0", + "@typescript-eslint/types": "^8.60.0", "debug": "^4.4.3" }, "engines": { @@ -3043,12 +3436,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.0.tgz", + "integrity": "sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4" + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3059,7 +3454,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.0.tgz", + "integrity": "sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==", "dev": true, "license": "MIT", "engines": { @@ -3074,13 +3471,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.0.tgz", + "integrity": "sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -3097,7 +3496,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.0.tgz", + "integrity": "sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==", "dev": true, "license": "MIT", "engines": { @@ -3109,14 +3510,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.0.tgz", + "integrity": "sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.4", - "@typescript-eslint/tsconfig-utils": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/project-service": "8.60.0", + "@typescript-eslint/tsconfig-utils": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3136,6 +3539,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { @@ -3144,6 +3549,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -3155,6 +3562,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -3168,15 +3577,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.0.tgz", + "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4" + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3191,11 +3601,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.0.tgz", + "integrity": "sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/types": "8.60.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3208,6 +3620,8 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3323,6 +3737,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3337,6 +3754,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3351,6 +3771,9 @@ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3365,6 +3788,9 @@ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3379,6 +3805,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3393,6 +3822,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3407,6 +3839,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3421,6 +3856,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3429,10 +3867,15 @@ }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3447,6 +3890,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3530,6 +3976,8 @@ }, "node_modules/@vis.gl/react-mapbox": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@vis.gl/react-mapbox/-/react-mapbox-8.1.1.tgz", + "integrity": "sha512-KMDTjtWESXxHS4uqWxjsvgQUHvuL3Z6SdKe68o7Nxma2qUfuyH3x4TCkIqGn3FQTrFvZLWvTnSAbGvtm+Kd13A==", "license": "MIT", "peerDependencies": { "mapbox-gl": ">=3.5.0", @@ -3544,6 +3992,8 @@ }, "node_modules/@vis.gl/react-maplibre": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@vis.gl/react-maplibre/-/react-maplibre-8.1.1.tgz", + "integrity": "sha512-iUOfzJAhFAJwEZp1644tQb7LOTFgi5/GzdaztkhzNgFVuoF2Ez7guvwZjQAKB9CN2TlHTgNuYH8UW85kO7cVhw==", "license": "MIT", "dependencies": { "@maplibre/maplibre-gl-style-spec": "^19.2.1" @@ -3561,6 +4011,8 @@ }, "node_modules/@vis.gl/react-maplibre/node_modules/@maplibre/maplibre-gl-style-spec": { "version": "19.3.3", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz", + "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==", "license": "ISC", "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", @@ -3578,10 +4030,14 @@ }, "node_modules/@vis.gl/react-maplibre/node_modules/json-stringify-pretty-compact": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", + "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==", "license": "MIT" }, "node_modules/@vitejs/plugin-react": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", + "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", "dev": true, "license": "MIT", "dependencies": { @@ -3606,6 +4062,8 @@ }, "node_modules/@vitest/expect": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { @@ -3621,6 +4079,8 @@ }, "node_modules/@vitest/pretty-format": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -3632,6 +4092,8 @@ }, "node_modules/@vitest/runner": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3645,6 +4107,8 @@ }, "node_modules/@vitest/snapshot": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3658,6 +4122,8 @@ }, "node_modules/@vitest/spy": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { @@ -3669,6 +4135,8 @@ }, "node_modules/@vitest/utils": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { @@ -3682,9 +4150,10 @@ }, "node_modules/acorn": { "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3694,6 +4163,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3702,6 +4173,8 @@ }, "node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { "debug": "4" @@ -3712,6 +4185,8 @@ }, "node_modules/ajv": { "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -3727,14 +4202,19 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -3749,11 +4229,25 @@ }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/arr-union": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3761,6 +4255,8 @@ }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "license": "MIT", "dependencies": { @@ -3776,6 +4272,8 @@ }, "node_modules/array-includes": { "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3795,77 +4293,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-includes/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3883,77 +4314,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findlast/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.flat": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { @@ -3969,77 +4333,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flat/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.flatmap": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "license": "MIT", "dependencies": { @@ -4055,77 +4352,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flatmap/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "license": "MIT", "dependencies": { @@ -4139,77 +4369,10 @@ "node": ">= 0.4" } }, - "node_modules/array.prototype.tosorted/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4228,77 +4391,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arraybuffer.prototype.slice/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/assertion-error": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { @@ -4307,6 +4403,8 @@ }, "node_modules/assign-symbols": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4314,11 +4412,15 @@ }, "node_modules/ast-types-flow": { "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true, "license": "MIT" }, "node_modules/async-function": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, "license": "MIT", "engines": { @@ -4327,10 +4429,14 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/available-typed-arrays": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4345,6 +4451,8 @@ }, "node_modules/axe-core": { "version": "4.11.4", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz", + "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==", "dev": true, "license": "MPL-2.0", "engines": { @@ -4353,6 +4461,8 @@ }, "node_modules/axios": { "version": "1.16.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", @@ -4363,6 +4473,8 @@ }, "node_modules/axobject-query": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4371,6 +4483,8 @@ }, "node_modules/babel-plugin-macros": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", @@ -4384,11 +4498,15 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/baseline-browser-mapping": { "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4399,7 +4517,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.14", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -4409,6 +4529,8 @@ }, "node_modules/braces": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -4420,6 +4542,8 @@ }, "node_modules/browserslist": { "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ { @@ -4450,7 +4574,94 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/browserslist/node_modules/caniuse-lite": { + "node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "license": "MIT", + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "license": "MIT", + "dependencies": { + "typewise-core": "^1.2" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { "version": "1.0.30001793", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", @@ -4471,81 +4682,10 @@ ], "license": "CC-BY-4.0" }, - "node_modules/bytewise": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "bytewise-core": "^1.2.2", - "typewise": "^1.0.3" - } - }, - "node_modules/bytewise-core": { - "version": "1.2.3", - "license": "MIT", - "dependencies": { - "typewise-core": "^1.2" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.9", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "get-intrinsic": "^1.3.0", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/chai": { "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", "dependencies": { @@ -4561,6 +4701,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -4576,6 +4718,8 @@ }, "node_modules/check-error": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", "engines": { @@ -4584,6 +4728,8 @@ }, "node_modules/clsx": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -4591,6 +4737,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4602,11 +4750,15 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -4617,6 +4769,8 @@ }, "node_modules/comment-parser": { "version": "1.4.7", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.7.tgz", + "integrity": "sha512-0h+uSNtQGW3D98eQt3jJ8L06Fves8hncB4V/PKdw/Qb8Hnk19VaKuTr55UNRYiSoVa7WwrFls+rh3ux9agmkeQ==", "dev": true, "license": "MIT", "engines": { @@ -4625,15 +4779,21 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, "node_modules/cookie": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "license": "MIT", "engines": { "node": ">=18" @@ -4645,6 +4805,8 @@ }, "node_modules/cosmiconfig": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", @@ -4659,6 +4821,8 @@ }, "node_modules/cosmiconfig/node_modules/yaml": { "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", "license": "ISC", "engines": { "node": ">= 6" @@ -4666,6 +4830,8 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -4679,11 +4845,15 @@ }, "node_modules/css.escape": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true, "license": "MIT" }, "node_modules/cssstyle": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", "dev": true, "license": "MIT", "dependencies": { @@ -4696,15 +4866,21 @@ }, "node_modules/csstype": { "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/data-urls": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "license": "MIT", "dependencies": { @@ -4717,6 +4893,8 @@ }, "node_modules/data-view-buffer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4733,6 +4911,8 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4749,6 +4929,8 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4765,6 +4947,8 @@ }, "node_modules/debug": { "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4780,11 +4964,15 @@ }, "node_modules/decimal.js": { "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, "license": "MIT" }, "node_modules/deep-eql": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", "engines": { @@ -4793,11 +4981,15 @@ }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/define-data-property": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { @@ -4814,6 +5006,8 @@ }, "node_modules/define-properties": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -4830,6 +5024,8 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -4837,6 +5033,8 @@ }, "node_modules/dequal": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, "license": "MIT", "engines": { @@ -4845,6 +5043,8 @@ }, "node_modules/detect-libc": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4853,6 +5053,8 @@ }, "node_modules/doctrine": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4864,11 +5066,16 @@ }, "node_modules/dom-accessibility-api": { "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dom-helpers": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", @@ -4877,6 +5084,8 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -4889,10 +5098,14 @@ }, "node_modules/earcut": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", "license": "ISC" }, "node_modules/effector": { "version": "23.4.4", + "resolved": "https://registry.npmjs.org/effector/-/effector-23.4.4.tgz", + "integrity": "sha512-QkZboRN28K/iwxigDhlJcI3ux3aNbt8kYGGH/GkqWG0OlGeyuBhb7PdM89Iu+ogV8Lmz16xIlwnXR2UNWI6psg==", "funding": [ { "type": "patreon", @@ -4904,13 +5117,14 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=11.0.0" } }, "node_modules/effector-react": { "version": "23.3.0", + "resolved": "https://registry.npmjs.org/effector-react/-/effector-react-23.3.0.tgz", + "integrity": "sha512-QR0+x1EnbiWhO80Yc0GVF+I9xCYoxBm3t+QLB5Wg+1uY1Q1BrSWDmKvJaJJZ/+9BU4RAr25yS5J2EkdWnicu8g==", "funding": [ { "type": "patreon", @@ -4934,17 +5148,23 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.361", + "version": "1.5.363", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.363.tgz", + "integrity": "sha512-VjUKPyWzGnT1fujlkEGC/BvN70Hh70KXtAqcmniXviYlJC/ivcT+BWGPyxWVbJZLfvtKR6dqg1L7T7pgAMBtWA==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, "node_modules/entities": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4956,52 +5176,14 @@ }, "node_modules/error-ex": { "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.2", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.1.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.3.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.5", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers/node_modules/es-abstract": { + "node_modules/es-abstract": { "version": "1.24.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", @@ -5070,13 +5252,63 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -5087,6 +5319,8 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5100,6 +5334,8 @@ }, "node_modules/es-shim-unscopables": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { @@ -5111,6 +5347,8 @@ }, "node_modules/es-to-primitive": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { @@ -5127,10 +5365,11 @@ }, "node_modules/esbuild": { "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -5168,6 +5407,8 @@ }, "node_modules/escalade": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -5176,6 +5417,8 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", "engines": { "node": ">=10" @@ -5190,7 +5433,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5247,9 +5489,10 @@ }, "node_modules/eslint-config-prettier": { "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5262,6 +5505,8 @@ }, "node_modules/eslint-import-context": { "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -5285,6 +5530,8 @@ }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "license": "MIT", "dependencies": { @@ -5295,6 +5542,8 @@ }, "node_modules/eslint-import-resolver-node/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5303,6 +5552,8 @@ }, "node_modules/eslint-import-resolver-typescript": { "version": "4.4.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.4.tgz", + "integrity": "sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==", "dev": true, "license": "ISC", "dependencies": { @@ -5336,6 +5587,8 @@ }, "node_modules/eslint-module-utils": { "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { @@ -5352,6 +5605,8 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5360,6 +5615,8 @@ }, "node_modules/eslint-plugin-boundaries": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-boundaries/-/eslint-plugin-boundaries-6.0.2.tgz", + "integrity": "sha512-wSHgiYeMEbziP91lH0UQ9oslgF2djG1x+LV9z/qO19ggMKZaCB8pKIGePHAY91eLF4EAgpsxQk8MRSFGRPfPzw==", "dev": true, "license": "MIT", "dependencies": { @@ -5379,9 +5636,10 @@ }, "node_modules/eslint-plugin-import-x": { "version": "4.16.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.2.tgz", + "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@package-json/types": "^0.0.12", "@typescript-eslint/types": "^8.56.0", @@ -5416,6 +5674,8 @@ }, "node_modules/eslint-plugin-import-x/node_modules/balanced-match": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { @@ -5424,6 +5684,8 @@ }, "node_modules/eslint-plugin-import-x/node_modules/brace-expansion": { "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -5435,6 +5697,8 @@ }, "node_modules/eslint-plugin-import-x/node_modules/minimatch": { "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -5449,6 +5713,8 @@ }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5487,6 +5753,8 @@ }, "node_modules/eslint-plugin-prettier": { "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, "license": "MIT", "dependencies": { @@ -5516,6 +5784,8 @@ }, "node_modules/eslint-plugin-react": { "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -5547,6 +5817,8 @@ }, "node_modules/eslint-plugin-react-hooks": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, "license": "MIT", "dependencies": { @@ -5565,6 +5837,8 @@ }, "node_modules/eslint-plugin-react-refresh": { "version": "0.5.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz", + "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5573,6 +5847,8 @@ }, "node_modules/eslint-plugin-react/node_modules/is-core-module": { "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -5587,6 +5863,8 @@ }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5609,6 +5887,8 @@ }, "node_modules/eslint-plugin-react/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -5617,6 +5897,8 @@ }, "node_modules/eslint-scope": { "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5632,6 +5914,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5643,6 +5927,8 @@ }, "node_modules/espree": { "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5659,6 +5945,8 @@ }, "node_modules/esquery": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5670,6 +5958,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5681,6 +5971,8 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -5689,6 +5981,8 @@ }, "node_modules/estree-walker": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -5697,6 +5991,8 @@ }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -5705,6 +6001,8 @@ }, "node_modules/expect-type": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5713,6 +6011,8 @@ }, "node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" @@ -5723,16 +6023,22 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true, "license": "Apache-2.0" }, "node_modules/fast-equals": { "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -5740,16 +6046,22 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/file-entry-cache": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5761,6 +6073,8 @@ }, "node_modules/fill-range": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { @@ -5772,10 +6086,14 @@ }, "node_modules/find-root": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { @@ -5791,6 +6109,8 @@ }, "node_modules/flat-cache": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { @@ -5803,11 +6123,15 @@ }, "node_modules/flatted": { "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -5826,6 +6150,8 @@ }, "node_modules/for-each": { "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", "dependencies": { @@ -5840,6 +6166,8 @@ }, "node_modules/form-data": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -5869,6 +6197,8 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5876,6 +6206,8 @@ }, "node_modules/function.prototype.name": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5895,6 +6227,8 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "license": "MIT", "funding": { @@ -5903,6 +6237,8 @@ }, "node_modules/generator-function": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, "license": "MIT", "engines": { @@ -5911,6 +6247,8 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { @@ -5919,6 +6257,8 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -5941,6 +6281,8 @@ }, "node_modules/get-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -5952,6 +6294,8 @@ }, "node_modules/get-symbol-description": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { @@ -5968,6 +6312,8 @@ }, "node_modules/get-tsconfig": { "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", "dev": true, "license": "MIT", "dependencies": { @@ -5979,6 +6325,8 @@ }, "node_modules/get-value": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5986,10 +6334,14 @@ }, "node_modules/gl-matrix": { "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", "license": "MIT" }, "node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { @@ -6001,6 +6353,8 @@ }, "node_modules/globals": { "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "dev": true, "license": "MIT", "engines": { @@ -6012,6 +6366,8 @@ }, "node_modules/globalthis": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6027,6 +6383,8 @@ }, "node_modules/gopd": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6037,6 +6395,8 @@ }, "node_modules/handlebars": { "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6057,6 +6417,8 @@ }, "node_modules/handlebars/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6065,6 +6427,8 @@ }, "node_modules/has-bigints": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", "engines": { @@ -6076,6 +6440,8 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -6084,6 +6450,8 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { @@ -6095,6 +6463,8 @@ }, "node_modules/has-proto": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6109,6 +6479,8 @@ }, "node_modules/has-symbols": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6119,6 +6491,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -6132,6 +6506,8 @@ }, "node_modules/hasown": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -6142,11 +6518,15 @@ }, "node_modules/hermes-estree": { "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "dev": true, "license": "MIT" }, "node_modules/hermes-parser": { "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "dev": true, "license": "MIT", "dependencies": { @@ -6155,6 +6535,8 @@ }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "license": "BSD-3-Clause", "dependencies": { "react-is": "^16.7.0" @@ -6162,10 +6544,14 @@ }, "node_modules/hoist-non-react-statics/node_modules/react-is": { "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6177,6 +6563,8 @@ }, "node_modules/http-proxy-agent": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { @@ -6189,6 +6577,8 @@ }, "node_modules/http-proxy-agent/node_modules/agent-base": { "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", "engines": { @@ -6197,6 +6587,8 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { "agent-base": "6", @@ -6208,6 +6600,8 @@ }, "node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { @@ -6219,6 +6613,8 @@ }, "node_modules/ignore": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -6227,6 +6623,8 @@ }, "node_modules/import-fresh": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -6241,6 +6639,8 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { @@ -6249,6 +6649,8 @@ }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", "engines": { @@ -6257,6 +6659,8 @@ }, "node_modules/internal-slot": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { @@ -6270,6 +6674,8 @@ }, "node_modules/is-array-buffer": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { @@ -6286,10 +6692,14 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, "node_modules/is-async-function": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6308,6 +6718,8 @@ }, "node_modules/is-bigint": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6322,6 +6734,8 @@ }, "node_modules/is-boolean-object": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { @@ -6337,6 +6751,8 @@ }, "node_modules/is-bun-module": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6345,6 +6761,8 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", "engines": { @@ -6356,6 +6774,8 @@ }, "node_modules/is-core-module": { "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -6369,6 +6789,8 @@ }, "node_modules/is-data-view": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { @@ -6385,6 +6807,8 @@ }, "node_modules/is-date-object": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { @@ -6400,6 +6824,8 @@ }, "node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6407,6 +6833,8 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { @@ -6415,6 +6843,8 @@ }, "node_modules/is-finalizationregistry": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { @@ -6429,6 +6859,8 @@ }, "node_modules/is-generator-function": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { @@ -6447,6 +6879,8 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { @@ -6458,6 +6892,8 @@ }, "node_modules/is-map": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", "engines": { @@ -6469,6 +6905,8 @@ }, "node_modules/is-negative-zero": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", "engines": { @@ -6480,6 +6918,8 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { @@ -6488,6 +6928,8 @@ }, "node_modules/is-number-object": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { @@ -6503,6 +6945,8 @@ }, "node_modules/is-plain-object": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "license": "MIT", "dependencies": { "isobject": "^3.0.1" @@ -6513,11 +6957,15 @@ }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, "license": "MIT" }, "node_modules/is-regex": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { @@ -6535,6 +6983,8 @@ }, "node_modules/is-set": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", "engines": { @@ -6546,6 +6996,8 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { @@ -6560,6 +7012,8 @@ }, "node_modules/is-string": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "dependencies": { @@ -6575,6 +7029,8 @@ }, "node_modules/is-symbol": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6591,6 +7047,8 @@ }, "node_modules/is-typed-array": { "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6605,6 +7063,8 @@ }, "node_modules/is-weakmap": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { @@ -6616,6 +7076,8 @@ }, "node_modules/is-weakref": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { @@ -6630,6 +7092,8 @@ }, "node_modules/is-weakset": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6645,16 +7109,22 @@ }, "node_modules/isarray": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6662,6 +7132,8 @@ }, "node_modules/iterator.prototype": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "license": "MIT", "dependencies": { @@ -6678,10 +7150,14 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -6733,6 +7209,8 @@ }, "node_modules/jsdom/node_modules/agent-base": { "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", "engines": { @@ -6741,6 +7219,8 @@ }, "node_modules/jsdom/node_modules/https-proxy-agent": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { @@ -6753,6 +7233,8 @@ }, "node_modules/jsesc": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -6763,29 +7245,41 @@ }, "node_modules/json-buffer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json-stringify-pretty-compact": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { @@ -6797,6 +7291,8 @@ }, "node_modules/jsx-ast-utils": { "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6811,10 +7307,14 @@ }, "node_modules/kdbush": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz", + "integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==", "license": "ISC" }, "node_modules/keyv": { "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -6823,11 +7323,15 @@ }, "node_modules/language-subtag-registry": { "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", "dev": true, "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "license": "MIT", "dependencies": { @@ -6839,6 +7343,8 @@ }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6851,6 +7357,8 @@ }, "node_modules/lightningcss": { "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -6990,6 +7498,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7011,6 +7522,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7026,10 +7540,15 @@ }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7051,6 +7570,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7108,14 +7630,20 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, "node_modules/linkifyjs": { "version": "4.3.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.3.tgz", + "integrity": "sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==", "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -7130,11 +7658,15 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -7145,11 +7677,15 @@ }, "node_modules/loupe": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, "node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { @@ -7158,6 +7694,8 @@ }, "node_modules/lucide-react": { "version": "1.16.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz", + "integrity": "sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -7165,14 +7703,19 @@ }, "node_modules/lz-string": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } }, "node_modules/magic-string": { "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7181,8 +7724,9 @@ }, "node_modules/maplibre-gl": { "version": "5.24.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.24.0.tgz", + "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", @@ -7214,6 +7758,8 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -7221,6 +7767,8 @@ }, "node_modules/micromatch": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -7233,6 +7781,8 @@ }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7240,6 +7790,8 @@ }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -7250,6 +7802,8 @@ }, "node_modules/min-indent": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "license": "MIT", "engines": { @@ -7258,6 +7812,8 @@ }, "node_modules/minimatch": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -7269,6 +7825,8 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7276,14 +7834,20 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/murmurhash-js": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==", "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -7301,6 +7865,8 @@ }, "node_modules/napi-postinstall": { "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, "license": "MIT", "bin": { @@ -7315,16 +7881,22 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/neo-async": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, "license": "MIT" }, "node_modules/node-exports-info": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", "dev": true, "license": "MIT", "dependencies": { @@ -7342,6 +7914,8 @@ }, "node_modules/node-exports-info/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -7350,6 +7924,8 @@ }, "node_modules/node-releases": { "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", "dev": true, "license": "MIT", "engines": { @@ -7358,11 +7934,15 @@ }, "node_modules/nwsapi": { "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", "dev": true, "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7370,6 +7950,8 @@ }, "node_modules/object-inspect": { "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -7381,6 +7963,8 @@ }, "node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "engines": { @@ -7389,6 +7973,8 @@ }, "node_modules/object.assign": { "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { @@ -7408,6 +7994,8 @@ }, "node_modules/object.entries": { "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { @@ -7422,6 +8010,8 @@ }, "node_modules/object.fromentries": { "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7437,77 +8027,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.fromentries/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.values": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -7525,6 +8048,8 @@ }, "node_modules/optionator": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -7541,10 +8066,14 @@ }, "node_modules/orderedmap": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", "license": "MIT" }, "node_modules/own-keys": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { @@ -7561,6 +8090,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7575,6 +8106,8 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -7589,6 +8122,8 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -7599,6 +8134,8 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -7615,6 +8152,8 @@ }, "node_modules/parse5": { "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { @@ -7626,6 +8165,8 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -7634,6 +8175,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -7642,10 +8185,14 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "license": "MIT", "engines": { "node": ">=8" @@ -7653,11 +8200,15 @@ }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -7666,6 +8217,8 @@ }, "node_modules/pbf": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.2.tgz", + "integrity": "sha512-J0ajxARhZfpUEebxYs1vhMGMuLSXtBe1e+fFPDrf2uA2hgo+UshKfNUWOz92HJNz6/NFEXseQPddnHkTreWRqg==", "license": "BSD-3-Clause", "dependencies": { "resolve-protobuf-schema": "^2.1.0" @@ -7676,10 +8229,14 @@ }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -7691,6 +8248,8 @@ }, "node_modules/possible-typed-array-names": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { @@ -7699,6 +8258,8 @@ }, "node_modules/postcss": { "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -7726,10 +8287,14 @@ }, "node_modules/potpack": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz", + "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==", "license": "ISC" }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -7738,9 +8303,10 @@ }, "node_modules/prettier": { "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -7753,6 +8319,8 @@ }, "node_modules/prettier-linter-helpers": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -7764,8 +8332,11 @@ }, "node_modules/pretty-format": { "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -7777,8 +8348,11 @@ }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -7788,11 +8362,16 @@ }, "node_modules/pretty-format/node_modules/react-is": { "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/prop-types": { "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -7802,10 +8381,14 @@ }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, "node_modules/prosemirror-changeset": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.1.tgz", + "integrity": "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==", "license": "MIT", "dependencies": { "prosemirror-transform": "^1.0.0" @@ -7813,6 +8396,8 @@ }, "node_modules/prosemirror-commands": { "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", "license": "MIT", "dependencies": { "prosemirror-model": "^1.0.0", @@ -7822,6 +8407,8 @@ }, "node_modules/prosemirror-dropcursor": { "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", "license": "MIT", "dependencies": { "prosemirror-state": "^1.0.0", @@ -7831,6 +8418,8 @@ }, "node_modules/prosemirror-gapcursor": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz", + "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==", "license": "MIT", "dependencies": { "prosemirror-keymap": "^1.0.0", @@ -7841,6 +8430,8 @@ }, "node_modules/prosemirror-history": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", + "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", "license": "MIT", "dependencies": { "prosemirror-state": "^1.2.2", @@ -7851,6 +8442,8 @@ }, "node_modules/prosemirror-keymap": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", "license": "MIT", "dependencies": { "prosemirror-state": "^1.0.0", @@ -7859,6 +8452,8 @@ }, "node_modules/prosemirror-model": { "version": "1.25.7", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.7.tgz", + "integrity": "sha512-A79aN8QEFUwI6cax8Yq4Rpcx1TJZ3Kagn+ii7qLo4/V8H3mMiHrhFyhTyHHvpSnOgMPpWiDGSwM3etwrxE50ug==", "license": "MIT", "dependencies": { "orderedmap": "^2.0.0" @@ -7866,6 +8461,8 @@ }, "node_modules/prosemirror-schema-list": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", "license": "MIT", "dependencies": { "prosemirror-model": "^1.0.0", @@ -7875,6 +8472,8 @@ }, "node_modules/prosemirror-state": { "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", + "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", "license": "MIT", "dependencies": { "prosemirror-model": "^1.0.0", @@ -7884,6 +8483,8 @@ }, "node_modules/prosemirror-tables": { "version": "1.8.5", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", + "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", "license": "MIT", "dependencies": { "prosemirror-keymap": "^1.2.3", @@ -7895,6 +8496,8 @@ }, "node_modules/prosemirror-transform": { "version": "1.12.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.0.tgz", + "integrity": "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==", "license": "MIT", "dependencies": { "prosemirror-model": "^1.21.0" @@ -7902,6 +8505,8 @@ }, "node_modules/prosemirror-view": { "version": "1.41.8", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz", + "integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==", "license": "MIT", "dependencies": { "prosemirror-model": "^1.20.0", @@ -7911,10 +8516,14 @@ }, "node_modules/protocol-buffers-schema": { "version": "3.6.1", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", + "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==", "license": "MIT" }, "node_modules/proxy-from-env": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { "node": ">=10" @@ -7922,6 +8531,8 @@ }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -7930,20 +8541,24 @@ }, "node_modules/quickselect": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", "license": "ISC" }, "node_modules/react": { "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -7953,6 +8568,8 @@ }, "node_modules/react-hook-form": { "version": "7.76.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.1.tgz", + "integrity": "sha512-rYM7tPiWlu3nZchkR/ex7piyzui2vFPyaLnXnI/RnblB/L4qfMmyses8llJVtF1NpE9WBBsJlGtcSZzPCXW1qQ==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -7967,10 +8584,14 @@ }, "node_modules/react-is": { "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", "license": "MIT" }, "node_modules/react-map-gl": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-8.1.1.tgz", + "integrity": "sha512-aSqFAFoxvY7wxbGI93Dz0E41171mkAb3GcNbnkFIotmu88OFw495os6mIDZSi7irYNT/PZEIOEHUxhun4ToGuQ==", "license": "MIT", "dependencies": { "@vis.gl/react-mapbox": "8.1.1", @@ -7993,6 +8614,8 @@ }, "node_modules/react-router": { "version": "7.15.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz", + "integrity": "sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -8013,6 +8636,8 @@ }, "node_modules/react-router-dom": { "version": "7.15.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.15.1.tgz", + "integrity": "sha512-AzF62gjY6U9rkMq4RfP/r2EVtQ7DMfNMjyOp/flLTCrtRylLiK4wT4pSq6O8rOXZ2eXdZYJPEYe+ifomiv+Igg==", "license": "MIT", "dependencies": { "react-router": "7.15.1" @@ -8027,6 +8652,8 @@ }, "node_modules/react-transition-group": { "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", @@ -8041,6 +8668,8 @@ }, "node_modules/redent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "license": "MIT", "dependencies": { @@ -8053,6 +8682,8 @@ }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { @@ -8072,77 +8703,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reflect.getprototypeof/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { @@ -8162,6 +8726,8 @@ }, "node_modules/resolve": { "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8181,6 +8747,8 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "license": "MIT", "engines": { "node": ">=4" @@ -8188,6 +8756,8 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -8196,13 +8766,68 @@ }, "node_modules/resolve-protobuf-schema": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", "license": "MIT", "dependencies": { "protocol-buffers-schema": "^3.3.1" } }, + "node_modules/rolldown": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", + "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.132.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.2", + "@rolldown/binding-darwin-arm64": "1.0.2", + "@rolldown/binding-darwin-x64": "1.0.2", + "@rolldown/binding-freebsd-x64": "1.0.2", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", + "@rolldown/binding-linux-arm64-gnu": "1.0.2", + "@rolldown/binding-linux-arm64-musl": "1.0.2", + "@rolldown/binding-linux-ppc64-gnu": "1.0.2", + "@rolldown/binding-linux-s390x-gnu": "1.0.2", + "@rolldown/binding-linux-x64-gnu": "1.0.2", + "@rolldown/binding-linux-x64-musl": "1.0.2", + "@rolldown/binding-openharmony-arm64": "1.0.2", + "@rolldown/binding-wasm32-wasi": "1.0.2", + "@rolldown/binding-win32-arm64-msvc": "1.0.2", + "@rolldown/binding-win32-x64-msvc": "1.0.2" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", + "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/rollup": { "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", "dev": true, "license": "MIT", "dependencies": { @@ -8246,24 +8871,34 @@ }, "node_modules/rollup/node_modules/@types/estree": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/rope-sequence": { "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", "license": "MIT" }, "node_modules/rrweb-cssom": { "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", "dev": true, "license": "MIT" }, "node_modules/rw": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", "license": "BSD-3-Clause" }, "node_modules/safe-array-concat": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", "dev": true, "license": "MIT", "dependencies": { @@ -8282,6 +8917,8 @@ }, "node_modules/safe-push-apply": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { @@ -8297,6 +8934,8 @@ }, "node_modules/safe-regex-test": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { @@ -8313,11 +8952,15 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "license": "ISC", "dependencies": { @@ -8329,10 +8972,14 @@ }, "node_modules/scheduler": { "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/semver": { "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "dev": true, "license": "ISC", "bin": { @@ -8344,10 +8991,14 @@ }, "node_modules/set-cookie-parser": { "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, "node_modules/set-function-length": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { @@ -8364,6 +9015,8 @@ }, "node_modules/set-function-name": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8378,6 +9031,8 @@ }, "node_modules/set-proto": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { @@ -8391,6 +9046,8 @@ }, "node_modules/set-value": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", @@ -8404,6 +9061,8 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -8415,6 +9074,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -8423,6 +9084,8 @@ }, "node_modules/side-channel": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { @@ -8441,6 +9104,8 @@ }, "node_modules/side-channel-list": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { @@ -8456,6 +9121,8 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -8473,6 +9140,8 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -8491,11 +9160,15 @@ }, "node_modules/siginfo": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/sort-asc": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", + "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8503,6 +9176,8 @@ }, "node_modules/sort-desc": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", + "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8510,6 +9185,8 @@ }, "node_modules/sort-object": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", + "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", "license": "MIT", "dependencies": { "bytewise": "^1.1.0", @@ -8525,6 +9202,8 @@ }, "node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -8532,6 +9211,8 @@ }, "node_modules/source-map-js": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -8540,6 +9221,8 @@ }, "node_modules/split-string": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "license": "MIT", "dependencies": { "extend-shallow": "^3.0.0" @@ -8550,6 +9233,8 @@ }, "node_modules/split-string/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", @@ -8561,6 +9246,8 @@ }, "node_modules/split-string/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" @@ -8571,6 +9258,8 @@ }, "node_modules/stable-hash-x": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", "dev": true, "license": "MIT", "engines": { @@ -8579,16 +9268,22 @@ }, "node_modules/stackback": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8601,6 +9296,8 @@ }, "node_modules/string.prototype.includes": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -8612,77 +9309,10 @@ "node": ">= 0.4" } }, - "node_modules/string.prototype.includes/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.matchall": { "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "license": "MIT", "dependencies": { @@ -8707,77 +9337,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.matchall/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.repeat": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "license": "MIT", "dependencies": { @@ -8785,77 +9348,10 @@ "es-abstract": "^1.17.5" } }, - "node_modules/string.prototype.repeat/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.trim": { "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { @@ -8874,77 +9370,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trim/node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.trimend": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8962,6 +9391,8 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { @@ -8978,6 +9409,8 @@ }, "node_modules/strip-indent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8989,6 +9422,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -9000,6 +9435,8 @@ }, "node_modules/strip-literal": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", "dev": true, "license": "MIT", "dependencies": { @@ -9011,15 +9448,21 @@ }, "node_modules/strip-literal/node_modules/js-tokens": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "dev": true, "license": "MIT" }, "node_modules/stylis": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", "license": "MIT" }, "node_modules/supercluster": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", "license": "ISC", "dependencies": { "kdbush": "^4.0.2" @@ -9027,6 +9470,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -9038,6 +9483,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9047,7 +9494,9 @@ } }, "node_modules/swiper": { - "version": "12.1.4", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.2.0.tgz", + "integrity": "sha512-K8uXsBZU6ME97Ia3xbBge8IRCnR1lOmIILzvY/jGVic7dSTQ530s3uO8RvXbPUtkkXLWIwmZLRPbtDxRWVAFdg==", "funding": [ { "type": "custom", @@ -9065,11 +9514,15 @@ }, "node_modules/symbol-tree": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, "license": "MIT" }, "node_modules/synckit": { "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9084,16 +9537,22 @@ }, "node_modules/tinybench": { "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { @@ -9109,6 +9568,8 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -9125,9 +9586,10 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9137,6 +9599,8 @@ }, "node_modules/tinypool": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -9145,10 +9609,14 @@ }, "node_modules/tinyqueue": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", "license": "ISC" }, "node_modules/tinyrainbow": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -9157,6 +9625,8 @@ }, "node_modules/tinyspy": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", "engines": { @@ -9165,6 +9635,8 @@ }, "node_modules/tldts": { "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9176,11 +9648,15 @@ }, "node_modules/tldts-core": { "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9192,6 +9668,8 @@ }, "node_modules/tough-cookie": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9203,6 +9681,8 @@ }, "node_modules/tr46": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "dev": true, "license": "MIT", "dependencies": { @@ -9214,6 +9694,8 @@ }, "node_modules/ts-api-utils": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -9233,6 +9715,8 @@ }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -9244,6 +9728,8 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", "dependencies": { @@ -9257,6 +9743,8 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { @@ -9275,6 +9763,8 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9295,6 +9785,8 @@ }, "node_modules/typed-array-length": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { @@ -9318,7 +9810,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9328,14 +9819,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.4", + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.0.tgz", + "integrity": "sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.4", - "@typescript-eslint/parser": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4" + "@typescript-eslint/eslint-plugin": "8.60.0", + "@typescript-eslint/parser": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9349,47 +9842,10 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz", - "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/type-utils": "8.59.4", - "@typescript-eslint/utils": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.59.4", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/typescript-eslint/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/typewise": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", "license": "MIT", "dependencies": { "typewise-core": "^1.2.0" @@ -9397,10 +9853,14 @@ }, "node_modules/typewise-core": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==", "license": "MIT" }, "node_modules/uglify-js": { "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, @@ -9413,6 +9873,8 @@ }, "node_modules/unbox-primitive": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { @@ -9430,11 +9892,15 @@ }, "node_modules/undici-types": { "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" }, "node_modules/union-value": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "license": "MIT", "dependencies": { "arr-union": "^3.1.0", @@ -9448,6 +9914,8 @@ }, "node_modules/unrs-resolver": { "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -9484,6 +9952,8 @@ }, "node_modules/update-browserslist-db": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -9513,6 +9983,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -9521,6 +9993,8 @@ }, "node_modules/use-sync-external-store": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -9528,9 +10002,10 @@ }, "node_modules/vite": { "version": "8.0.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz", + "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -9605,6 +10080,8 @@ }, "node_modules/vite-node": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { @@ -9626,6 +10103,8 @@ }, "node_modules/vite-node/node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -9642,9 +10121,10 @@ }, "node_modules/vite-node/node_modules/picomatch": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9654,6 +10134,8 @@ }, "node_modules/vite-node/node_modules/vite": { "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "dev": true, "license": "MIT", "dependencies": { @@ -9727,6 +10209,8 @@ }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -9736,40 +10220,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite/node_modules/rolldown": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.132.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.2", - "@rolldown/binding-darwin-arm64": "1.0.2", - "@rolldown/binding-darwin-x64": "1.0.2", - "@rolldown/binding-freebsd-x64": "1.0.2", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", - "@rolldown/binding-linux-arm64-gnu": "1.0.2", - "@rolldown/binding-linux-arm64-musl": "1.0.2", - "@rolldown/binding-linux-ppc64-gnu": "1.0.2", - "@rolldown/binding-linux-s390x-gnu": "1.0.2", - "@rolldown/binding-linux-x64-gnu": "1.0.2", - "@rolldown/binding-linux-x64-musl": "1.0.2", - "@rolldown/binding-openharmony-arm64": "1.0.2", - "@rolldown/binding-wasm32-wasi": "1.0.2", - "@rolldown/binding-win32-arm64-msvc": "1.0.2", - "@rolldown/binding-win32-x64-msvc": "1.0.2" - } - }, "node_modules/vitest": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { @@ -9841,6 +10295,8 @@ }, "node_modules/vitest/node_modules/@vitest/mocker": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9866,6 +10322,8 @@ }, "node_modules/vitest/node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -9882,9 +10340,10 @@ }, "node_modules/vitest/node_modules/picomatch": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9894,9 +10353,10 @@ }, "node_modules/vitest/node_modules/vite": { "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -9968,10 +10428,14 @@ }, "node_modules/w3c-keyname": { "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { @@ -9983,6 +10447,8 @@ }, "node_modules/webidl-conversions": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -9991,6 +10457,9 @@ }, "node_modules/whatwg-encoding": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", "dev": true, "license": "MIT", "dependencies": { @@ -10002,6 +10471,8 @@ }, "node_modules/whatwg-mimetype": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "license": "MIT", "engines": { @@ -10010,6 +10481,8 @@ }, "node_modules/whatwg-url": { "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "dev": true, "license": "MIT", "dependencies": { @@ -10022,6 +10495,8 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { @@ -10036,6 +10511,8 @@ }, "node_modules/which-boxed-primitive": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, "license": "MIT", "dependencies": { @@ -10054,6 +10531,8 @@ }, "node_modules/which-builtin-type": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -10080,6 +10559,8 @@ }, "node_modules/which-collection": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { @@ -10096,12 +10577,14 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.20", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", + "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", @@ -10117,6 +10600,8 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -10132,6 +10617,8 @@ }, "node_modules/word-wrap": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -10140,11 +10627,15 @@ }, "node_modules/wordwrap": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true, "license": "MIT" }, "node_modules/ws": { "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { @@ -10165,6 +10656,8 @@ }, "node_modules/xml-name-validator": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -10173,16 +10666,22 @@ }, "node_modules/xmlchars": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT" }, "node_modules/yallist": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { @@ -10198,13 +10697,14 @@ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-validation-error": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", "dev": true, "license": "MIT", "engines": { diff --git a/client/src/shared/lib/__tests__/get-api-error-message.test.ts b/client/src/shared/lib/__tests__/get-api-error-message.test.ts index 08e1660..96ea9c8 100644 --- a/client/src/shared/lib/__tests__/get-api-error-message.test.ts +++ b/client/src/shared/lib/__tests__/get-api-error-message.test.ts @@ -24,9 +24,9 @@ describe('getApiErrorMessage', () => { expect(getApiErrorMessage(new Error('Something broke'))).toBe('Something broke') }) - it('returns unknown error for falsy input', () => { - expect(getApiErrorMessage(null)).toBe('Произошла неизвестная ошибка') - expect(getApiErrorMessage(undefined)).toBe('Произошла неизвестная ошибка') + it('returns null for falsy input (no error)', () => { + expect(getApiErrorMessage(null)).toBeNull() + expect(getApiErrorMessage(undefined)).toBeNull() }) it('returns unknown error for random object', () => { diff --git a/client/src/shared/lib/get-api-error-message.ts b/client/src/shared/lib/get-api-error-message.ts index 519ab32..5a2510d 100644 --- a/client/src/shared/lib/get-api-error-message.ts +++ b/client/src/shared/lib/get-api-error-message.ts @@ -1,7 +1,7 @@ import { isAxiosError } from 'axios' -export function getApiErrorMessage(error: unknown): string { - if (!error) return 'Произошла неизвестная ошибка' +export function getApiErrorMessage(error: unknown): string | null { + if (!error) return null if (isAxiosError(error)) { if (error.response?.data?.error && typeof error.response.data.error === 'string') { diff --git a/client/src/shared/lib/use-mutation-with-toast.ts b/client/src/shared/lib/use-mutation-with-toast.ts index 44b7c30..9f2774f 100644 --- a/client/src/shared/lib/use-mutation-with-toast.ts +++ b/client/src/shared/lib/use-mutation-with-toast.ts @@ -35,7 +35,7 @@ export function useMutationWithToast { - addNotification({ type: 'error', message: getApiErrorMessage(error) }) + addNotification({ type: 'error', message: getApiErrorMessage(error) || 'Произошла неизвестная ошибка' }) onError?.(error, variables, onMutateResult, mutationContext) }, }) From 2889cd95452e0e302fe4f8981bb9cee4b29aa08c Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 28 May 2026 11:48:35 +0500 Subject: [PATCH 28/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 180 ++++++++------------------------------- 1 file changed, 37 insertions(+), 143 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index e9abc11..225fc6a 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -131,6 +131,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -472,6 +473,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -495,6 +497,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -564,6 +567,7 @@ "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-9.4.2.tgz", "integrity": "sha512-MF0042+Z3s8PGZKZLySfhft28bUa3B1iq0e5NSjCvY8gfMi5aIH/iRJGRJa1N9Jz1BNkxYb4yvJ/N9KO8Z6Y+w==", "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -703,29 +707,6 @@ "@dicebear/core": "^9.0.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -795,6 +776,7 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -838,6 +820,7 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1492,17 +1475,6 @@ "@floating-ui/utils": "^0.2.11" } }, - "node_modules/@floating-ui/dom": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", - "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "@floating-ui/core": "^1.7.5", - "@floating-ui/utils": "^0.2.11" - } - }, "node_modules/@floating-ui/utils": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", @@ -1767,6 +1739,7 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.1.tgz", "integrity": "sha512-voyCpeUxcSWLN7KPZuq0pGCIt726T9K6kiVM3XUcywZDAlZSarLHaUxJVQpospbjjOzN53hwyjo8s6KoWl6utw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.29.2", "@mui/core-downloads-tracker": "^9.0.1", @@ -2111,9 +2084,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2131,9 +2101,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2151,9 +2118,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2171,9 +2135,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2191,9 +2152,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2211,9 +2169,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2375,9 +2330,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2392,9 +2344,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2409,9 +2358,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2426,9 +2372,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2443,9 +2386,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2460,9 +2400,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2477,9 +2414,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2494,9 +2428,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2511,9 +2442,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2528,9 +2456,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2545,9 +2470,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2562,9 +2484,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2579,9 +2498,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2793,6 +2709,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.6.tgz", "integrity": "sha512-MRB3pHz4Oxqmcawh0cQ5iOGdY5xtNYp/1CoK7hdTLzw5K0C6/gTC2VvanB1R4INaB6EpBkxG/GiWkVirDRnuXw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3015,6 +2932,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.6.tgz", "integrity": "sha512-z6vj9+Qht2sjdQkyyHcUpsC/yCIZqTrQiyHDhs/HGKrfvoANyAZGpqdNeKf1wSyjIso+27tQuIH5NDfk8ygyNw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3133,6 +3051,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.6.tgz", "integrity": "sha512-X09/Db1teB+ifXzDGVVFmOeQRx7wTAayE9/280spxpsHkHZvJ5bHRvWIzUzviMIjbBz+NPDIKYPK7gMfh9iaig==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3147,6 +3066,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.6.tgz", "integrity": "sha512-in5CaMaWlJcH2A1q6GJKFtrodE8WLS3M9tIi/f89jPmIVHJShpodC0KZDNyJkrVBQomYk0DEh86Utm6ASXzQww==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -3245,8 +3165,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/chai": { "version": "5.2.3", @@ -3291,6 +3210,7 @@ "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -3312,6 +3232,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3321,6 +3242,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3394,6 +3316,7 @@ "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/types": "8.60.0", @@ -3582,6 +3505,7 @@ "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.60.0", @@ -3737,9 +3661,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3754,9 +3675,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3771,9 +3689,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3788,9 +3703,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3805,9 +3717,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3822,9 +3731,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3839,9 +3745,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3856,9 +3759,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3873,9 +3773,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3890,9 +3787,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4154,6 +4048,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4206,7 +4101,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -4560,6 +4454,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -5069,8 +4964,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -5117,6 +5011,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=11.0.0" } @@ -5370,6 +5265,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -5433,6 +5329,7 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5493,6 +5390,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5640,6 +5538,7 @@ "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@package-json/types": "^0.0.12", "@typescript-eslint/types": "^8.56.0", @@ -7498,9 +7397,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7522,9 +7418,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7546,9 +7439,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7570,9 +7460,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -7707,7 +7594,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -7727,6 +7613,7 @@ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.24.0.tgz", "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", @@ -8307,6 +8194,7 @@ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8336,7 +8224,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -8352,7 +8239,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -8365,8 +8251,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/prop-types": { "version": "15.8.1", @@ -8550,6 +8435,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8559,6 +8445,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9590,6 +9477,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -9810,6 +9698,7 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10006,6 +9895,7 @@ "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -10125,6 +10015,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -10344,6 +10235,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -10357,6 +10249,7 @@ "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -10697,6 +10590,7 @@ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From f15f331de5e04a42f23cf9bd695968320b6bdb2c Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 28 May 2026 12:10:24 +0500 Subject: [PATCH 29/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 81 ++++++++++--------- client/src/app/layout/MainLayout.tsx | 30 ++++++- .../src/entities/product/ui/ProductCard.tsx | 5 +- .../ui/__tests__/AddToCartButton.test.tsx | 7 +- .../ui/__tests__/ToggleCartIcon.test.tsx | 7 +- client/src/pages/checkout/ui/CheckoutPage.tsx | 6 ++ client/src/pages/home/ui/ProductFilters.tsx | 1 - client/src/shared/config/index.ts | 6 +- .../use-mutation-with-toast.test.tsx | 7 +- client/src/shared/lib/use-page-title.ts | 12 +-- client/src/shared/ui/DemoBanner.tsx | 23 ++++++ client/src/vite-env.d.ts | 1 + .../widgets/reviews-block/ui/ReviewsBlock.tsx | 4 +- 13 files changed, 136 insertions(+), 54 deletions(-) create mode 100644 client/src/shared/ui/DemoBanner.tsx diff --git a/client/package-lock.json b/client/package-lock.json index 225fc6a..b6eb005 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -131,7 +131,6 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -473,7 +472,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -497,7 +495,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -567,7 +564,6 @@ "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-9.4.2.tgz", "integrity": "sha512-MF0042+Z3s8PGZKZLySfhft28bUa3B1iq0e5NSjCvY8gfMi5aIH/iRJGRJa1N9Jz1BNkxYb4yvJ/N9KO8Z6Y+w==", "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -707,6 +703,29 @@ "@dicebear/core": "^9.0.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -776,7 +795,6 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -820,7 +838,6 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1475,6 +1492,17 @@ "@floating-ui/utils": "^0.2.11" } }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, "node_modules/@floating-ui/utils": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", @@ -1739,7 +1767,6 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.1.tgz", "integrity": "sha512-voyCpeUxcSWLN7KPZuq0pGCIt726T9K6kiVM3XUcywZDAlZSarLHaUxJVQpospbjjOzN53hwyjo8s6KoWl6utw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.29.2", "@mui/core-downloads-tracker": "^9.0.1", @@ -2709,7 +2736,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.6.tgz", "integrity": "sha512-MRB3pHz4Oxqmcawh0cQ5iOGdY5xtNYp/1CoK7hdTLzw5K0C6/gTC2VvanB1R4INaB6EpBkxG/GiWkVirDRnuXw==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2932,7 +2958,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.6.tgz", "integrity": "sha512-z6vj9+Qht2sjdQkyyHcUpsC/yCIZqTrQiyHDhs/HGKrfvoANyAZGpqdNeKf1wSyjIso+27tQuIH5NDfk8ygyNw==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3051,7 +3076,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.6.tgz", "integrity": "sha512-X09/Db1teB+ifXzDGVVFmOeQRx7wTAayE9/280spxpsHkHZvJ5bHRvWIzUzviMIjbBz+NPDIKYPK7gMfh9iaig==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3066,7 +3090,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.6.tgz", "integrity": "sha512-in5CaMaWlJcH2A1q6GJKFtrodE8WLS3M9tIi/f89jPmIVHJShpodC0KZDNyJkrVBQomYk0DEh86Utm6ASXzQww==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -3165,7 +3188,8 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/chai": { "version": "5.2.3", @@ -3210,7 +3234,6 @@ "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -3232,7 +3255,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3242,7 +3264,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3316,7 +3337,6 @@ "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/types": "8.60.0", @@ -3505,7 +3525,6 @@ "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.60.0", @@ -4048,7 +4067,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4101,6 +4119,7 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -4454,7 +4473,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -4964,7 +4982,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -5011,7 +5030,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=11.0.0" } @@ -5265,7 +5283,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -5329,7 +5346,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5390,7 +5406,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5538,7 +5553,6 @@ "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@package-json/types": "^0.0.12", "@typescript-eslint/types": "^8.56.0", @@ -7594,6 +7608,7 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -7613,7 +7628,6 @@ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.24.0.tgz", "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", @@ -8194,7 +8208,6 @@ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8224,6 +8237,7 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -8239,6 +8253,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -8251,7 +8266,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/prop-types": { "version": "15.8.1", @@ -8435,7 +8451,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -8445,7 +8460,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9477,7 +9491,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9698,7 +9711,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9895,7 +9907,6 @@ "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -10015,7 +10026,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -10235,7 +10245,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -10249,7 +10258,6 @@ "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -10590,7 +10598,6 @@ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/client/src/app/layout/MainLayout.tsx b/client/src/app/layout/MainLayout.tsx index 13d1881..3faa34b 100644 --- a/client/src/app/layout/MainLayout.tsx +++ b/client/src/app/layout/MainLayout.tsx @@ -11,6 +11,7 @@ import { AppHeader } from '@/app/layout/AppHeader' import vkLogoSrc from '@/shared/assets/vk-logo.svg' import { STORE_EMAIL, STORE_NAME, STORE_PHONE, VK_URL } from '@/shared/config' import { CookieConsentBanner } from '@/shared/ui/CookieConsentBanner' +import { DemoBanner } from '@/shared/ui/DemoBanner' import { ScrollOnNavigate } from '@/shared/ui/ScrollOnNavigate' import { ScrollToTop } from '@/shared/ui/ScrollToTop' @@ -22,6 +23,7 @@ export function MainLayout({ children }: PropsWithChildren) { + @@ -42,7 +44,12 @@ export function MainLayout({ children }: PropsWithChildren) { - + {STORE_NAME} @@ -50,7 +57,12 @@ export function MainLayout({ children }: PropsWithChildren) { - + Покупателям @@ -66,7 +78,12 @@ export function MainLayout({ children }: PropsWithChildren) { - + Контакты @@ -95,7 +112,12 @@ export function MainLayout({ children }: PropsWithChildren) { - + Юридическая информация diff --git a/client/src/entities/product/ui/ProductCard.tsx b/client/src/entities/product/ui/ProductCard.tsx index 72c32eb..265397b 100644 --- a/client/src/entities/product/ui/ProductCard.tsx +++ b/client/src/entities/product/ui/ProductCard.tsx @@ -78,7 +78,10 @@ const ProductCardInner = ({ product, mediaHeight = 390, actions }: Props) => { > {imageUrls.length ? ( - + { fireEvent.click(screen.getByRole('button', { name: /в корзину/i })) await vi.waitFor(() => { - expect(spy).toHaveBeenCalledWith({ type: 'success', message: 'Товар добавлен в корзину', actionLabel: 'Перейти в корзину', actionPath: '/cart' }) + expect(spy).toHaveBeenCalledWith({ + type: 'success', + message: 'Товар добавлен в корзину', + actionLabel: 'Перейти в корзину', + actionPath: '/cart', + }) }) }) }) diff --git a/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx b/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx index aa4205c..0a4b908 100644 --- a/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx +++ b/client/src/features/cart/toggle-cart-icon/ui/__tests__/ToggleCartIcon.test.tsx @@ -38,7 +38,12 @@ describe('ToggleCartIcon', () => { fireEvent.click(screen.getByRole('button', { name: /в корзину/i })) await vi.waitFor(() => { - expect(spy).toHaveBeenCalledWith({ type: 'success', message: 'Товар добавлен в корзину', actionLabel: 'Перейти в корзину', actionPath: '/cart' }) + expect(spy).toHaveBeenCalledWith({ + type: 'success', + message: 'Товар добавлен в корзину', + actionLabel: 'Перейти в корзину', + actionPath: '/cart', + }) }) }) diff --git a/client/src/pages/checkout/ui/CheckoutPage.tsx b/client/src/pages/checkout/ui/CheckoutPage.tsx index 03eb7ab..c31b31d 100644 --- a/client/src/pages/checkout/ui/CheckoutPage.tsx +++ b/client/src/pages/checkout/ui/CheckoutPage.tsx @@ -23,6 +23,7 @@ import { DELIVERY_CARRIER_OPTIONS, type DeliveryCarrierCode } from '@/shared/con import { formatPriceRub } from '@/shared/lib/format-price' import { getApiErrorMessage } from '@/shared/lib/get-api-error-message' import { $user } from '@/shared/model/auth' +import { IS_DEMO_MODE } from '@/shared/config' export function CheckoutPage() { const user = useUnit($user) @@ -81,6 +82,11 @@ export function CheckoutPage() { return ( + {IS_DEMO_MODE && ( + + Оформление заказа недоступно в демо-режиме. Заказ не будет создан. + + )} Оформление заказа diff --git a/client/src/pages/home/ui/ProductFilters.tsx b/client/src/pages/home/ui/ProductFilters.tsx index b0014bc..0bae600 100644 --- a/client/src/pages/home/ui/ProductFilters.tsx +++ b/client/src/pages/home/ui/ProductFilters.tsx @@ -181,7 +181,6 @@ export function ProductFilters({ - diff --git a/client/src/shared/config/index.ts b/client/src/shared/config/index.ts index 95c402a..1c35776 100644 --- a/client/src/shared/config/index.ts +++ b/client/src/shared/config/index.ts @@ -21,5 +21,7 @@ export const VK_URL = import.meta.env.VITE_VK_URL ?? 'https://vk.com/club1583958 export const STORE_OP_NAME = 'Комарова Лариса Николаевна' export const STORE_OP_TYPE = 'Самозанятый' export const STORE_OP_INN = '591878584346' -export const STORE_OP_ADDR = - '618900, Россия, Пермский край, Лысьвенский муниципальный округ, Лысьва, улица Мира, 34' +export const STORE_OP_ADDR = '618900, Россия, Пермский край, Лысьвенский муниципальный округ, Лысьва, улица Мира, 34' + +/** Демо-режим: баннеры «скоро открытие», предупреждения в чекауте. Включается через VITE_DEMO_MODE=true. */ +export const IS_DEMO_MODE = import.meta.env.VITE_DEMO_MODE === 'true' diff --git a/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx index 7cddc99..ee29139 100644 --- a/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx +++ b/client/src/shared/lib/__tests__/use-mutation-with-toast.test.tsx @@ -48,7 +48,12 @@ describe('useMutationWithToast', () => { }) it('calls user-provided onSuccess callback', async () => { - const onSuccess: (data: { ok: boolean }, variables: void, onMutateResult: unknown, mutationContext: unknown) => void = vi.fn() + const onSuccess: ( + data: { ok: boolean }, + variables: void, + onMutateResult: unknown, + mutationContext: unknown, + ) => void = vi.fn() const mutationFn = (): Promise<{ ok: boolean }> => Promise.resolve({ ok: true }) const { result } = renderHook(() => useMutationWithToast({ mutationFn, onSuccess, successMessage: 'OK' }), { wrapper: createWrapper(), diff --git a/client/src/shared/lib/use-page-title.ts b/client/src/shared/lib/use-page-title.ts index e968072..6f0b251 100644 --- a/client/src/shared/lib/use-page-title.ts +++ b/client/src/shared/lib/use-page-title.ts @@ -3,12 +3,12 @@ import { useLocation } from 'react-router-dom' const BASE_TITLE = 'Любимый Креатив — Изделия ручной работы' -let currentTitle: string = BASE_TITLE +let didPageTitleSet = false export function usePageTitle(title: string | null) { useEffect(() => { - currentTitle = title ? `${title} — Любимый Креатив` : BASE_TITLE - document.title = currentTitle + didPageTitleSet = true + document.title = title ? `${title} — Любимый Креатив` : BASE_TITLE }, [title]) } @@ -16,7 +16,9 @@ export function usePageTitleReset() { const location = useLocation() useEffect(() => { - document.title = BASE_TITLE - currentTitle = BASE_TITLE + if (!didPageTitleSet) { + document.title = BASE_TITLE + } + didPageTitleSet = false }, [location.pathname]) } diff --git a/client/src/shared/ui/DemoBanner.tsx b/client/src/shared/ui/DemoBanner.tsx new file mode 100644 index 0000000..72e8509 --- /dev/null +++ b/client/src/shared/ui/DemoBanner.tsx @@ -0,0 +1,23 @@ +import Alert from '@mui/material/Alert' +import Box from '@mui/material/Box' +import { IS_DEMO_MODE } from '@/shared/config' + +export function DemoBanner() { + if (!IS_DEMO_MODE) return null + + return ( + + + Сайт работает в демо-режиме. Заказы не оформляются. Скоро открытие! + + + ) +} diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts index 327f37b..693e4a3 100644 --- a/client/src/vite-env.d.ts +++ b/client/src/vite-env.d.ts @@ -7,6 +7,7 @@ interface ImportMetaEnv { readonly VITE_STORE_EMAIL?: string readonly VITE_STORE_PHONE?: string readonly VITE_STORE_SOCIAL_NOTE?: string + readonly VITE_DEMO_MODE?: string } interface ImportMeta { diff --git a/client/src/widgets/reviews-block/ui/ReviewsBlock.tsx b/client/src/widgets/reviews-block/ui/ReviewsBlock.tsx index 0311e36..a26f5e4 100644 --- a/client/src/widgets/reviews-block/ui/ReviewsBlock.tsx +++ b/client/src/widgets/reviews-block/ui/ReviewsBlock.tsx @@ -32,7 +32,9 @@ export function ReviewsBlock() { return ( - Отзывы + + Отзывы + Последние отзывы о товарах From 966731d3e176f5378205ef1ca8f5352a68ce56a3 Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 28 May 2026 12:10:55 +0500 Subject: [PATCH 30/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 81 ++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index b6eb005..225fc6a 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -131,6 +131,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -472,6 +473,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -495,6 +497,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -564,6 +567,7 @@ "resolved": "https://registry.npmjs.org/@dicebear/core/-/core-9.4.2.tgz", "integrity": "sha512-MF0042+Z3s8PGZKZLySfhft28bUa3B1iq0e5NSjCvY8gfMi5aIH/iRJGRJa1N9Jz1BNkxYb4yvJ/N9KO8Z6Y+w==", "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -703,29 +707,6 @@ "@dicebear/core": "^9.0.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -795,6 +776,7 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -838,6 +820,7 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1492,17 +1475,6 @@ "@floating-ui/utils": "^0.2.11" } }, - "node_modules/@floating-ui/dom": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", - "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "@floating-ui/core": "^1.7.5", - "@floating-ui/utils": "^0.2.11" - } - }, "node_modules/@floating-ui/utils": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", @@ -1767,6 +1739,7 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.1.tgz", "integrity": "sha512-voyCpeUxcSWLN7KPZuq0pGCIt726T9K6kiVM3XUcywZDAlZSarLHaUxJVQpospbjjOzN53hwyjo8s6KoWl6utw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.29.2", "@mui/core-downloads-tracker": "^9.0.1", @@ -2736,6 +2709,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.6.tgz", "integrity": "sha512-MRB3pHz4Oxqmcawh0cQ5iOGdY5xtNYp/1CoK7hdTLzw5K0C6/gTC2VvanB1R4INaB6EpBkxG/GiWkVirDRnuXw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2958,6 +2932,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.6.tgz", "integrity": "sha512-z6vj9+Qht2sjdQkyyHcUpsC/yCIZqTrQiyHDhs/HGKrfvoANyAZGpqdNeKf1wSyjIso+27tQuIH5NDfk8ygyNw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3076,6 +3051,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.6.tgz", "integrity": "sha512-X09/Db1teB+ifXzDGVVFmOeQRx7wTAayE9/280spxpsHkHZvJ5bHRvWIzUzviMIjbBz+NPDIKYPK7gMfh9iaig==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3090,6 +3066,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.6.tgz", "integrity": "sha512-in5CaMaWlJcH2A1q6GJKFtrodE8WLS3M9tIi/f89jPmIVHJShpodC0KZDNyJkrVBQomYk0DEh86Utm6ASXzQww==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -3188,8 +3165,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/chai": { "version": "5.2.3", @@ -3234,6 +3210,7 @@ "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -3255,6 +3232,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3264,6 +3242,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3337,6 +3316,7 @@ "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/types": "8.60.0", @@ -3525,6 +3505,7 @@ "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.60.0", @@ -4067,6 +4048,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4119,7 +4101,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -4473,6 +4454,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -4982,8 +4964,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -5030,6 +5011,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=11.0.0" } @@ -5283,6 +5265,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -5346,6 +5329,7 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5406,6 +5390,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5553,6 +5538,7 @@ "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@package-json/types": "^0.0.12", "@typescript-eslint/types": "^8.56.0", @@ -7608,7 +7594,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -7628,6 +7613,7 @@ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.24.0.tgz", "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", @@ -8208,6 +8194,7 @@ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8237,7 +8224,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -8253,7 +8239,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -8266,8 +8251,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/prop-types": { "version": "15.8.1", @@ -8451,6 +8435,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8460,6 +8445,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9491,6 +9477,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -9711,6 +9698,7 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9907,6 +9895,7 @@ "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -10026,6 +10015,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -10245,6 +10235,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -10258,6 +10249,7 @@ "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -10598,6 +10590,7 @@ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From 7000fbffa7bdea7999b0738514b99c0d796e46c5 Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 28 May 2026 21:20:35 +0500 Subject: [PATCH 31/31] =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order-detail/ui/OrderDetailContent.tsx | 59 ++- .../ui/__tests__/OrderDetailContent.test.tsx | 181 +++++++ .../pages/admin-orders/ui/AdminOrdersPage.tsx | 49 +- .../ui/__tests__/AdminOrdersPage.test.tsx | 125 +++++ .../pages/admin-slider/ui/AdminSliderPage.tsx | 17 +- .../order-requires-price-approval.test.ts | 44 ++ .../lib/order-requires-price-approval.ts | 11 + .../2026-05-28-admin-orders-improvements.md | 446 ++++++++++++++++++ ...-05-28-admin-orders-improvements-design.md | 114 +++++ server/prisma/prisma/dev.db | Bin 352256 -> 352256 bytes 10 files changed, 993 insertions(+), 53 deletions(-) create mode 100644 client/src/features/order-detail/ui/__tests__/OrderDetailContent.test.tsx create mode 100644 client/src/pages/admin-orders/ui/__tests__/AdminOrdersPage.test.tsx create mode 100644 client/src/shared/lib/__tests__/order-requires-price-approval.test.ts create mode 100644 client/src/shared/lib/order-requires-price-approval.ts create mode 100644 docs/superpowers/plans/2026-05-28-admin-orders-improvements.md create mode 100644 docs/superpowers/specs/2026-05-28-admin-orders-improvements-design.md diff --git a/client/src/features/order-detail/ui/OrderDetailContent.tsx b/client/src/features/order-detail/ui/OrderDetailContent.tsx index 50dbe65..357cfc1 100644 --- a/client/src/features/order-detail/ui/OrderDetailContent.tsx +++ b/client/src/features/order-detail/ui/OrderDetailContent.tsx @@ -1,17 +1,13 @@ import { useMemo, useState } from 'react' -import { Link as RouterLink } from 'react-router-dom' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' -import FormControl from '@mui/material/FormControl' -import InputLabel from '@mui/material/InputLabel' import Link from '@mui/material/Link' -import MenuItem from '@mui/material/MenuItem' -import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { useMutation, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' +import { Link as RouterLink } from 'react-router-dom' import { postAdminOrderMessage, setAdminOrderStatus } from '@/entities/order/api/admin-order-api' import type { AdminOrderDetailResponse } from '@/entities/order/api/admin-order-api' import { deliveryCarrierLabelRu } from '@/shared/constants/delivery-carrier' @@ -165,31 +161,34 @@ export function OrderDetailContent({ detail, orderId }: { detail: AdminOrderDeta )} - - - Сменить статус - - - + + + Быстрый переход статуса + + {statusMut.isError && Не удалось сменить статус} + {nextStatuses.length === 0 ? ( + + Статус финальный, смена недоступна + + ) : ( + + {nextStatuses.map((nextStatus) => { + const isCancelled = nextStatus === 'CANCELLED' + return ( + + ) + })} + + )} + diff --git a/client/src/features/order-detail/ui/__tests__/OrderDetailContent.test.tsx b/client/src/features/order-detail/ui/__tests__/OrderDetailContent.test.tsx new file mode 100644 index 0000000..b47f2a4 --- /dev/null +++ b/client/src/features/order-detail/ui/__tests__/OrderDetailContent.test.tsx @@ -0,0 +1,181 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { render, screen, waitFor } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { useUnit } from 'effector-react' +import { MemoryRouter } from 'react-router-dom' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { setAdminOrderStatus } from '@/entities/order/api/admin-order-api' +import type { AdminOrderDetailResponse } from '@/entities/order/api/admin-order-api' +import { ORDER_STATUS_MAP } from '@/shared/lib/order-status-data' +import { OrderDetailContent } from '../OrderDetailContent' + +vi.mock('@/entities/order/api/admin-order-api', () => ({ + setAdminOrderStatus: vi.fn(), + postAdminOrderMessage: vi.fn(), +})) + +vi.mock('effector-react', () => ({ + useUnit: vi.fn(), +})) + +vi.mock('@/shared/ui/RichTextMessageEditor.lazy', () => ({ + RichTextMessageEditor: ({ + value, + onChange, + }: { + value: string + onChange: (next: string) => void + placeholder?: string + disabled?: boolean + }) =>