From d81abd6efd3883420067cca13cc68650f27fa96e Mon Sep 17 00:00:00 2001 From: chenhang Date: Tue, 23 Jun 2026 10:33:20 +0800 Subject: [PATCH 1/5] feat(chat): support ai photo viewing --- next.config.ts | 20 +++----- src/app/chat/chat-screen.tsx | 18 ++++++- src/app/chat/components/chat-input-bar.tsx | 21 -------- .../chat/components/chat-input-text-field.tsx | 2 +- .../chat-quota-exhausted-banner.tsx | 18 +++++-- src/core/net/chat-websocket.ts | 28 +++++++++++ src/data/dto/chat/chat_message.ts | 1 + src/data/repositories/chat_repository.ts | 2 + src/data/schemas/chat/chat_message.ts | 5 +- src/data/storage/chat/local_chat_db.ts | 1 + src/data/storage/chat/local_message.ts | 4 ++ src/stores/chat/chat-events.ts | 8 +++ src/stores/chat/chat-machine.actors.ts | 12 +++++ src/stores/chat/chat-machine.helpers.ts | 13 +++++ src/stores/chat/chat-machine.ts | 50 +++++++++++++++++++ src/stores/chat/chat-state.ts | 2 +- 16 files changed, 160 insertions(+), 45 deletions(-) diff --git a/next.config.ts b/next.config.ts index cf915a5f..c4ede2aa 100644 --- a/next.config.ts +++ b/next.config.ts @@ -11,15 +11,6 @@ import { withSerwist } from "@serwist/turbopack"; * - 脚本侧:scripts/deploy/_deploy_lib.sh 同步 .next/ + public/ * - 服务器启动:`cd && next start -H 0.0.0.0 -p 3000` * 或用 PM2:`pm2 start "next start" --name cozsweet` - * - * PWA 集成:`@serwist/turbopack` 在 build 阶段用 esbuild 编译 `src/app/sw.ts` 源文件。 - * - Turbopack 原生支持 —— 不再需要 `--webpack` flag - * - SW 通过 Serwist Route Handler(src/app/serwist/[[...slug]]/route.ts)在 `/serwist/sw.js` 服务 - * - 客户端注册走 ``(替代旧的 ) - * - * 历史: - * - 之前用 @ducanh2912/next-pwa(webpack-only),被迫用 `--webpack` 退 Turbopack - * - 切到 @serwist/turbopack 后拿回 Turbopack 的 dev/build 性能 */ const nextConfig: NextConfig = { experimental: { @@ -27,10 +18,6 @@ const nextConfig: NextConfig = { staticGenerationRetryCount: 0, }, images: { - // Facebook OAuth 登录后,`picture.type(large)` 返回 - // platform-lookaside.fbsbx.com/platform/profilepic/?asid=...&hash=... - // 该 URL 是**下载链接**而非可缓存图片,next/image 优化器需要显式 allowlist。 - // graph.facebook.com 兜底:Graph 偶尔返回直链头像 / OG 图。 remotePatterns: [ { protocol: "https", @@ -40,8 +27,13 @@ const nextConfig: NextConfig = { protocol: "https", hostname: "graph.facebook.com", }, + { + protocol: "https", + hostname: "**.supabase.co", + pathname: "/storage/v1/object/public/**", + }, ], }, }; -export default withSerwist(nextConfig); \ No newline at end of file +export default withSerwist(nextConfig); diff --git a/src/app/chat/chat-screen.tsx b/src/app/chat/chat-screen.tsx index ce88b7ab..55a72158 100644 --- a/src/app/chat/chat-screen.tsx +++ b/src/app/chat/chat-screen.tsx @@ -54,7 +54,10 @@ export function ChatScreen() { !isGuest && state.paywallTriggered && state.paywallReason === "daily_limit"; - const showExhaustedBanner = showGuestQuotaBanner || showDailyLimitBanner; + const showPhotoPaywallBanner = + state.paywallTriggered && state.paywallReason === "photo_paywall"; + const showExhaustedBanner = + showGuestQuotaBanner || showDailyLimitBanner || showPhotoPaywallBanner; const externalBrowserPromptShownRef = useRef(false); @@ -152,7 +155,18 @@ export function ChatScreen() { /> {showExhaustedBanner ? ( - + ) : ( )} diff --git a/src/app/chat/components/chat-input-bar.tsx b/src/app/chat/components/chat-input-bar.tsx index 2a4f7085..119bb30a 100644 --- a/src/app/chat/components/chat-input-bar.tsx +++ b/src/app/chat/components/chat-input-bar.tsx @@ -1,25 +1,4 @@ "use client"; -/** - * ChatInputBar 输入栏 - * - * 原始 Dart: lib/ui/chat/widgets/chat_input_bar.dart(121 行) - * - * 状态: - * - input:受控文本 - * - isFocused:是否聚焦(控制外层 pink-bg / box-shadow / padding-top) - * - hasContent:是否有 trim 内容(决定发送按钮是否启用) - * - * 容器层次(与 Dart 一致): - * - 外层 `.bar`:focused 时 `padding-top: md` + 粉色背景 + 阴影 - * - 内层 `.row`:白底 + `border-radius: 32` + focused 时 accent 边框 - * - Row:[ChatInputTextField (Expanded), ChatSendButton] - * - * 行为: - * - send 后清空 input + 保持 textarea 焦点(与 Dart `_focusNode.requestFocus()` 一致) - * - * 注意:Dart 源里的 `ImageUploadButton` 已被注释(`// const ImageUploadButton()`), - * `ChatMoreButton` / `FunctionButtonBar` 不存在于 Dart 源;本组件仅保留与 Dart 一致的部分。 - */ import { useRef, useState } from "react"; import { useChatDispatch } from "@/stores/chat/chat-context"; diff --git a/src/app/chat/components/chat-input-text-field.tsx b/src/app/chat/components/chat-input-text-field.tsx index 9525a19b..7700b48f 100644 --- a/src/app/chat/components/chat-input-text-field.tsx +++ b/src/app/chat/components/chat-input-text-field.tsx @@ -44,7 +44,7 @@ export const ChatInputTextField = forwardRef< onChange, onSubmit, onFocusChange, - placeholder = "|Say anything that’s on your mind ^U^…", + placeholder = "Say anything that’s on your mind ^U^…", disabled = false, autoFocus = false, }, diff --git a/src/app/chat/components/chat-quota-exhausted-banner.tsx b/src/app/chat/components/chat-quota-exhausted-banner.tsx index 14e380a2..08c3069f 100644 --- a/src/app/chat/components/chat-quota-exhausted-banner.tsx +++ b/src/app/chat/components/chat-quota-exhausted-banner.tsx @@ -27,6 +27,8 @@ import { ROUTES } from "@/router/routes"; import styles from "./chat-quota-exhausted-banner.module.css"; export interface ChatQuotaExhaustedBannerProps { + title?: string; + ctaLabel?: string; /** * 自定义点击回调(不传则默认 router.push(ROUTES.subscription)) * - 测试时可传 mock @@ -36,9 +38,12 @@ export interface ChatQuotaExhaustedBannerProps { } export function ChatQuotaExhaustedBanner({ + title = "The limit for free chat times\nhas been reached today", + ctaLabel = "Unlock your membership to continue", onUnlock, }: ChatQuotaExhaustedBannerProps) { const router = useRouter(); + const titleLines = title.split("\n"); const handleClick = () => { if (onUnlock) { @@ -56,17 +61,20 @@ export function ChatQuotaExhaustedBanner({ data-testid="chat-quota-exhausted-banner" >

- The limit for free chat times -
- has been reached today + {titleLines.map((line, index) => ( + + {line} + {index < titleLines.length - 1 ?
: null} +
+ ))}

); diff --git a/src/core/net/chat-websocket.ts b/src/core/net/chat-websocket.ts index 74b31482..30a591b0 100644 --- a/src/core/net/chat-websocket.ts +++ b/src/core/net/chat-websocket.ts @@ -29,6 +29,13 @@ export interface IntimacyPayload { relationshipStage?: string; } +export interface PaywallStatusPayload { + paywallTriggered: boolean; + showUpgrade: boolean; + imageType: string | null; + imageUrl: string | null; +} + export class ChatWebSocket { private ws: WebSocket | null = null; private reconnectTimer: ReturnType | null = null; @@ -38,6 +45,8 @@ export class ChatWebSocket { onTyping: ((isTyping: boolean) => void) | null = null; onSentence: ((payload: SentencePayload) => void) | null = null; onVoiceReady: ((index: number, audioUrl: string) => void) | null = null; + onImage: ((imageUrl: string) => void) | null = null; + onPaywallStatus: ((payload: PaywallStatusPayload) => void) | null = null; onIntimacyUpdate: ((payload: IntimacyPayload) => void) | null = null; onMoodUpdate: ((mood: string) => void) | null = null; onError: ((errorMessage: string) => void) | null = null; @@ -104,6 +113,12 @@ export class ChatWebSocket { relationshipStage?: string; mood?: string; error?: string; + data?: { + imageUrl?: string | null; + paywallTriggered?: boolean; + showUpgrade?: boolean; + imageType?: string | null; + }; }; try { payload = JSON.parse(data); @@ -128,6 +143,19 @@ export class ChatWebSocket { case "voice_ready": this.onVoiceReady?.(payload.index ?? 0, payload.audioUrl ?? ""); break; + case "image": { + const imageUrl = payload.data?.imageUrl; + if (imageUrl) this.onImage?.(imageUrl); + break; + } + case "paywall_status": + this.onPaywallStatus?.({ + paywallTriggered: payload.data?.paywallTriggered ?? false, + showUpgrade: payload.data?.showUpgrade ?? false, + imageType: payload.data?.imageType ?? null, + imageUrl: payload.data?.imageUrl ?? null, + }); + break; case "intimacy_update": this.onIntimacyUpdate?.({ intimacyChange: payload.intimacyChange, diff --git a/src/data/dto/chat/chat_message.ts b/src/data/dto/chat/chat_message.ts index 085844e5..9285b3eb 100644 --- a/src/data/dto/chat/chat_message.ts +++ b/src/data/dto/chat/chat_message.ts @@ -12,6 +12,7 @@ export class ChatMessage { declare readonly content: string; declare readonly id: string; declare readonly createdAt: string; + declare readonly imageUrl: string | null; declare readonly isPrivate: boolean | null; declare readonly privateLocked: boolean | null; declare readonly privateHint: string | null; diff --git a/src/data/repositories/chat_repository.ts b/src/data/repositories/chat_repository.ts index a7146450..8b42c8be 100644 --- a/src/data/repositories/chat_repository.ts +++ b/src/data/repositories/chat_repository.ts @@ -124,6 +124,7 @@ export class ChatRepository implements IChatRepository { role: message.role, content: message.content, createdAt: message.createdAt, + imageUrl: message.imageUrl, sessionId: "", }); } @@ -135,6 +136,7 @@ export class ChatRepository implements IChatRepository { role: local.role, content: local.content, createdAt: local.createdAt, + imageUrl: local.imageUrl, }); } diff --git a/src/data/schemas/chat/chat_message.ts b/src/data/schemas/chat/chat_message.ts index 24d64353..030b97d6 100644 --- a/src/data/schemas/chat/chat_message.ts +++ b/src/data/schemas/chat/chat_message.ts @@ -11,13 +11,16 @@ export const ChatMessageSchema = z id: z.string().default(""), createdAt: z.string().default(""), created_at: z.string().optional(), + imageUrl: z.string().nullable().default(null), + image_url: z.string().nullable().optional(), isPrivate: z.boolean().nullable().default(null), privateLocked: z.boolean().nullable().default(null), privateHint: z.string().nullable().default(null), }) - .transform(({ created_at, ...data }) => ({ + .transform(({ created_at, image_url, ...data }) => ({ ...data, createdAt: data.createdAt || created_at || "", + imageUrl: data.imageUrl || image_url || null, })); export type ChatMessageInput = z.input; diff --git a/src/data/storage/chat/local_chat_db.ts b/src/data/storage/chat/local_chat_db.ts index 53edcdea..3b78ced5 100644 --- a/src/data/storage/chat/local_chat_db.ts +++ b/src/data/storage/chat/local_chat_db.ts @@ -21,6 +21,7 @@ export interface LocalMessageRow { role: string; content: string; createdAt: string; + imageUrl?: string | null; sessionId: string; } diff --git a/src/data/storage/chat/local_message.ts b/src/data/storage/chat/local_message.ts index 72f1e5d7..d5b0dc04 100644 --- a/src/data/storage/chat/local_message.ts +++ b/src/data/storage/chat/local_message.ts @@ -22,6 +22,7 @@ export const LocalMessageSchema = z.object({ role: z.string(), content: z.string(), createdAt: z.string().default(""), + imageUrl: z.string().nullable().default(null), sessionId: z.string().default(""), }); @@ -33,6 +34,7 @@ export class LocalMessage { declare readonly role: string; declare readonly content: string; declare readonly createdAt: string; + declare readonly imageUrl: string | null; declare readonly sessionId: string; private constructor(input: LocalMessageInput) { @@ -60,6 +62,7 @@ export class LocalMessage { role: this.role, content: this.content, createdAt: this.createdAt, + imageUrl: this.imageUrl, sessionId: this.sessionId, }; } @@ -71,6 +74,7 @@ export class LocalMessage { role: row.role, content: row.content, createdAt: row.createdAt, + imageUrl: row.imageUrl ?? null, sessionId: row.sessionId, }); } diff --git a/src/stores/chat/chat-events.ts b/src/stores/chat/chat-events.ts index 066bb270..a7723e32 100644 --- a/src/stores/chat/chat-events.ts +++ b/src/stores/chat/chat-events.ts @@ -26,6 +26,14 @@ export type ChatEvent = | { type: "ChatSendMessage"; content: string } | { type: "ChatSendImage"; imageBase64: string } | { type: "ChatLoadMoreHistory" } + | { type: "ChatImageReceived"; imageUrl: string } + | { + type: "ChatPaywallStatusReceived"; + paywallTriggered: boolean; + showUpgrade: boolean; + imageType: string | null; + imageUrl: string | null; + } // WebSocket / AI 推句(由 chat 机器内部 actor 派回 —— "机器自驱动") | { type: "ChatAISentenceReceived"; diff --git a/src/stores/chat/chat-machine.actors.ts b/src/stores/chat/chat-machine.actors.ts index a70e119f..03ecce1d 100644 --- a/src/stores/chat/chat-machine.actors.ts +++ b/src/stores/chat/chat-machine.actors.ts @@ -151,6 +151,18 @@ export const chatWebSocketActor = fromCallback( done: p.done, }); }; + ws.onImage = (imageUrl) => { + sendBack({ type: "ChatImageReceived", imageUrl }); + }; + ws.onPaywallStatus = (p) => { + sendBack({ + type: "ChatPaywallStatusReceived", + paywallTriggered: p.paywallTriggered, + showUpgrade: p.showUpgrade, + imageType: p.imageType, + imageUrl: p.imageUrl, + }); + }; ws.onError = (msg) => { log.error("[chat-machine] WS error", { errorMessage: msg }); sendBack({ type: "ChatWebSocketError", errorMessage: msg }); diff --git a/src/stores/chat/chat-machine.helpers.ts b/src/stores/chat/chat-machine.helpers.ts index 9b1565c5..e0648532 100644 --- a/src/stores/chat/chat-machine.helpers.ts +++ b/src/stores/chat/chat-machine.helpers.ts @@ -56,12 +56,14 @@ export function localMessagesToUi( content: string; role: string; createdAt: string; + imageUrl?: string | null; }>, ): UiMessage[] { return records.map((m) => ({ content: m.content, isFromAI: m.role === "assistant", date: messageDateFromCreatedAt(m.createdAt), + ...(m.imageUrl ? { imageUrl: m.imageUrl } : {}), })); } @@ -81,6 +83,7 @@ export function sendResponseToUiMessage(response: ChatSendResponse): UiMessage { content: response.reply, isFromAI: true, date: todayString(new Date(response.timestamp)), + ...(response.imageUrl ? { imageUrl: response.imageUrl } : {}), }; } @@ -120,6 +123,16 @@ export function applyHttpSendOutput( }; } + if (response.showUpgrade) { + return { + messages: [...context.messages, reply], + isReplyingAI: false, + paywallTriggered: true, + paywallReason: "photo_paywall", + paywallDetail: null, + }; + } + return { messages: [...context.messages, reply], isReplyingAI: false, diff --git a/src/stores/chat/chat-machine.ts b/src/stores/chat/chat-machine.ts index 3768a476..833a1ec8 100644 --- a/src/stores/chat/chat-machine.ts +++ b/src/stores/chat/chat-machine.ts @@ -261,6 +261,54 @@ export const chatMachine = setup({ return { messages, isReplyingAI: false }; }), + appendAIImage: assign(({ context, event }) => { + if (event.type !== "ChatImageReceived") return {}; + const messages = [...context.messages]; + const last = messages[messages.length - 1]; + + if (last?.isFromAI && !last.imageUrl) { + messages[messages.length - 1] = { + ...last, + imageUrl: event.imageUrl, + }; + } else { + messages.push({ + content: "", + isFromAI: true, + date: todayString(), + imageUrl: event.imageUrl, + }); + } + + log.debug("[chat-machine] appendAIImage", { + messagesCount: messages.length, + hasMergedIntoLastMessage: Boolean(last?.isFromAI && !last.imageUrl), + }); + + return { + messages, + paywallTriggered: false, + paywallReason: null, + paywallDetail: null, + }; + }), + + applyPaywallStatus: assign(({ event }) => { + if (event.type !== "ChatPaywallStatusReceived") return {}; + if (!event.showUpgrade) { + return { + paywallTriggered: false, + paywallReason: null, + paywallDetail: null, + }; + } + return { + paywallTriggered: true, + paywallReason: "photo_paywall", + paywallDetail: null, + }; + }), + incrementQuotaExceeded: assign(({ context }) => ({ quotaExceededTrigger: context.quotaExceededTrigger + 1, })), @@ -546,6 +594,8 @@ export const chatMachine = setup({ actions: "startUserSession", }, ChatAISentenceReceived: { actions: "appendOrUpdateAISentence" }, + ChatImageReceived: { actions: "appendAIImage" }, + ChatPaywallStatusReceived: { actions: "applyPaywallStatus" }, ChatWebSocketError: { actions: "appendSocketErrorMessage" }, ChatWebSocketConnected: { actions: "setWsConnected" }, }, diff --git a/src/stores/chat/chat-state.ts b/src/stores/chat/chat-state.ts index 7c28ed90..e48d5024 100644 --- a/src/stores/chat/chat-state.ts +++ b/src/stores/chat/chat-state.ts @@ -25,7 +25,7 @@ export interface ChatState { guestTotalQuota: number; quotaExceededTrigger: number; paywallTriggered: boolean; - paywallReason: "daily_limit" | null; + paywallReason: "daily_limit" | "photo_paywall" | null; paywallDetail: { usedToday: number; limit: number } | null; isLoadingMore: boolean; hasMore: boolean; From 6bcc070ba1c703da78837e44eff8ef85b841f530 Mon Sep 17 00:00:00 2001 From: chenhang Date: Tue, 23 Jun 2026 11:20:48 +0800 Subject: [PATCH 2/5] refactor(chat): rely on server message limits --- src/app/chat/chat-screen.tsx | 12 +- .../chat-quota-exhausted-banner.tsx | 4 +- src/data/dto/chat/guest_chat_quota.ts | 82 --------- src/data/dto/chat/index.ts | 1 - src/data/schemas/chat/guest_chat_quota.ts | 13 -- src/data/schemas/chat/index.ts | 1 - src/data/services/index.ts | 2 - .../chat/__tests__/chat_storage.test.ts | 62 ------- src/data/storage/chat/chat_storage.ts | 76 +-------- src/data/storage/chat/ichat_storage.ts | 28 --- src/data/storage/chat/index.ts | 1 - src/data/storage/index.ts | 1 - src/data/storage/storage_keys.ts | 2 - src/stores/chat/chat-context.tsx | 11 -- src/stores/chat/chat-events.ts | 3 +- src/stores/chat/chat-machine.actors.ts | 16 +- src/stores/chat/chat-machine.helpers.ts | 46 +---- src/stores/chat/chat-machine.ts | 159 ++++-------------- src/stores/chat/chat-state.ts | 15 -- 19 files changed, 46 insertions(+), 489 deletions(-) delete mode 100644 src/data/dto/chat/guest_chat_quota.ts delete mode 100644 src/data/schemas/chat/guest_chat_quota.ts delete mode 100644 src/data/storage/chat/__tests__/chat_storage.test.ts delete mode 100644 src/data/storage/chat/ichat_storage.ts diff --git a/src/app/chat/chat-screen.tsx b/src/app/chat/chat-screen.tsx index 55a72158..a1064c40 100644 --- a/src/app/chat/chat-screen.tsx +++ b/src/app/chat/chat-screen.tsx @@ -42,22 +42,14 @@ export function ChatScreen() { // isGuest 派生(chat-screen 是唯一知道这个值的地方 —— chat 机器无 isGuest 字段) const isGuest = deriveIsGuest(authState.loginStatus); - // 游客配额耗尽 → 显示 Unlock CTA banner(替代 ChatInputBar) - // 三重条件:游客 + 配额加载完 + 用户被配额 guard 拦截过至少一次 - // - quotaLoaded 避免一进 /chat 就跳 banner(loadQuota 还在 in-flight) - // - quotaExceededTrigger 而非 guestTotalQuota / guestRemainingQuota —— - // trigger 由 chat 机器的 guard 在 ChatSendMessage / ChatSendImage 被拦截时 +1, - // 是 "用户被配额拒绝过" 的权威信号(避免依赖 quota 数值本身的边界判断) - const showGuestQuotaBanner = - isGuest && state.quotaLoaded && state.quotaExceededTrigger > 0; + // 消息数量限制由后端统一返回 blocked/daily_limit,前端不再处理本地额度。 const showDailyLimitBanner = - !isGuest && state.paywallTriggered && state.paywallReason === "daily_limit"; const showPhotoPaywallBanner = state.paywallTriggered && state.paywallReason === "photo_paywall"; const showExhaustedBanner = - showGuestQuotaBanner || showDailyLimitBanner || showPhotoPaywallBanner; + showDailyLimitBanner || showPhotoPaywallBanner; const externalBrowserPromptShownRef = useRef(false); diff --git a/src/app/chat/components/chat-quota-exhausted-banner.tsx b/src/app/chat/components/chat-quota-exhausted-banner.tsx index 08c3069f..5196d93c 100644 --- a/src/app/chat/components/chat-quota-exhausted-banner.tsx +++ b/src/app/chat/components/chat-quota-exhausted-banner.tsx @@ -3,9 +3,7 @@ * ChatQuotaExhaustedBanner 游客配额耗尽横幅 * * 何时显示: - * - isGuest === true(仅游客业务事实"非游客无配额上限") - * - quotaLoaded === true(避免一进 /chat 就跳 banner) - * - guestTotalQuota <= 0(用 total 而非 remaining —— 配额刚减为 0 不立即跳) + * - 后端返回 blocked=true && blockReason="daily_limit" * * 视觉规格(与设计稿对齐): * - 粉→品红渐变背景(与 splash 渐变一致) diff --git a/src/data/dto/chat/guest_chat_quota.ts b/src/data/dto/chat/guest_chat_quota.ts deleted file mode 100644 index 820b6caf..00000000 --- a/src/data/dto/chat/guest_chat_quota.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * 游客每日聊天配额数据 DTO - */ -import { - GuestChatQuotaSchema, - type GuestChatQuotaInput, - type GuestChatQuotaData, -} from "@/data/schemas/chat/guest_chat_quota"; -import { AppEnvUtil } from "@/utils"; - -export class GuestChatQuota { - // 静态常量 - static readonly maxQuotaPerDay = 30; - static readonly maxQuotaPerDayTest = 4; - - static readonly defaultTotalQuota = 50; - static readonly defaultTotalQuotaTest = 5; - static readonly quotaExhausted = 0; - - declare readonly remaining: number; - declare readonly date: string; - - private constructor(input: GuestChatQuotaInput) { - const data = GuestChatQuotaSchema.parse(input); - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: GuestChatQuotaInput): GuestChatQuota { - return new GuestChatQuota(input); - } - - static fromJson(json: unknown): GuestChatQuota { - return GuestChatQuota.from(json as GuestChatQuotaInput); - } - - /** - * 配额耗尽状态值 - */ - static get exhausted(): number { - return GuestChatQuota.quotaExhausted; - } - - /** - * 获取当前环境的每日最大配额 - */ - static get threshold(): number { - return AppEnvUtil.isProduction() - ? GuestChatQuota.maxQuotaPerDay - : GuestChatQuota.maxQuotaPerDayTest; - } - - /** - * 获取当前环境的总配额默认值 - */ - static get totalQuotaDefault(): number { - return AppEnvUtil.isProduction() - ? GuestChatQuota.defaultTotalQuota - : GuestChatQuota.defaultTotalQuotaTest; - } - - /** - * 创建初始配额实例 - */ - static initial(todayString: string): GuestChatQuota { - return new GuestChatQuota({ - remaining: GuestChatQuota.threshold, - date: todayString, - }); - } - - /** - * 是否需要重置(跨天) - */ - needsReset(todayString: string): boolean { - return this.date !== todayString; - } - - toJson(): GuestChatQuotaData { - return GuestChatQuotaSchema.parse(this); - } -} diff --git a/src/data/dto/chat/index.ts b/src/data/dto/chat/index.ts index 2d11b76e..6c3678dd 100644 --- a/src/data/dto/chat/index.ts +++ b/src/data/dto/chat/index.ts @@ -8,7 +8,6 @@ export * from "./chat_message"; export * from "./chat_send_response"; export * from "./chat_sync_data"; export * from "./chat_sync_request"; -export * from "./guest_chat_quota"; export * from "./image_upload_response"; export * from "./send_message_request"; export * from "./stt_data"; diff --git a/src/data/schemas/chat/guest_chat_quota.ts b/src/data/schemas/chat/guest_chat_quota.ts deleted file mode 100644 index 0d6c4450..00000000 --- a/src/data/schemas/chat/guest_chat_quota.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 游客每日聊天配额数据 - * 原始 Dart: GuestChatQuota (lib/data/models/chat/guest_chat_quota.dart) - */ -import { z } from "zod"; - -export const GuestChatQuotaSchema = z.object({ - remaining: z.number(), - date: z.string(), -}); - -export type GuestChatQuotaInput = z.input; -export type GuestChatQuotaData = z.output; diff --git a/src/data/schemas/chat/index.ts b/src/data/schemas/chat/index.ts index 90049d31..a7d86ba3 100644 --- a/src/data/schemas/chat/index.ts +++ b/src/data/schemas/chat/index.ts @@ -7,7 +7,6 @@ export * from "./chat_message"; export * from "./chat_send_response"; export * from "./chat_sync_data"; export * from "./chat_sync_request"; -export * from "./guest_chat_quota"; export * from "./image_upload_response"; export * from "./send_message_request"; export * from "./stt_data"; diff --git a/src/data/services/index.ts b/src/data/services/index.ts index 36f36e18..f085a552 100644 --- a/src/data/services/index.ts +++ b/src/data/services/index.ts @@ -35,7 +35,6 @@ export * from "../dto/chat/chat_message"; export * from "../dto/chat/chat_send_response"; export * from "../dto/chat/chat_sync_data"; export * from "../dto/chat/chat_sync_request"; -export * from "../dto/chat/guest_chat_quota"; export * from "../dto/chat/image_upload_response"; export * from "../dto/chat/send_message_request"; export * from "../dto/chat/stt_data"; @@ -69,7 +68,6 @@ export * from "../schemas/chat/chat_message"; export * from "../schemas/chat/chat_send_response"; export * from "../schemas/chat/chat_sync_data"; export * from "../schemas/chat/chat_sync_request"; -export * from "../schemas/chat/guest_chat_quota"; export * from "../schemas/chat/image_upload_response"; export * from "../schemas/chat/send_message_request"; export * from "../schemas/chat/stt_data"; diff --git a/src/data/storage/chat/__tests__/chat_storage.test.ts b/src/data/storage/chat/__tests__/chat_storage.test.ts deleted file mode 100644 index b3207491..00000000 --- a/src/data/storage/chat/__tests__/chat_storage.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { beforeEach, describe, expect, it } from "vitest"; -import { createStorage } from "unstorage"; -import memoryDriver from "unstorage/drivers/memory"; - -import { GuestChatQuota } from "@/data/dto/chat/guest_chat_quota"; -import { StorageKeys } from "@/data/storage/storage_keys"; -import { todayString, SpAsyncUtil } from "@/utils"; - -import { ChatStorage } from "../chat_storage"; - -describe("ChatStorage guest quota", () => { - beforeEach(() => { - SpAsyncUtil.setStorage(createStorage({ driver: memoryDriver() })); - ChatStorage._resetForTests(); - }); - - it("keeps an existing daily quota for the current day", async () => { - const storage = ChatStorage.getInstance(); - await storage.setGuestDailyChatQuota(2, todayString()); - - const result = await storage.getGuestDailyChatQuota(); - - expect(result.success).toBe(true); - expect(result.success ? result.data : null).toEqual({ - remaining: 2, - date: todayString(), - }); - }); - - it("resets daily quota only when the stored date is not today", async () => { - const storage = ChatStorage.getInstance(); - await storage.setGuestDailyChatQuota(1, "2000-01-01"); - - const result = await storage.getGuestDailyChatQuota(); - - expect(result.success).toBe(true); - expect(result.success ? result.data : null).toEqual({ - remaining: GuestChatQuota.threshold, - date: todayString(), - }); - }); - - it("does not overwrite invalid daily quota data with the default value", async () => { - await SpAsyncUtil.setString(StorageKeys.guestChatQuota, "{not-json"); - - const result = await ChatStorage.getInstance().getGuestDailyChatQuota(); - const stored = await SpAsyncUtil.getString(StorageKeys.guestChatQuota); - - expect(result.success).toBe(false); - expect(stored.success ? stored.data : null).toBe("{not-json"); - }); - - it("does not overwrite invalid total quota data with the default value", async () => { - await SpAsyncUtil.setString(StorageKeys.guestTotalQuotaRemaining, "{not-json"); - - const result = await ChatStorage.getInstance().getGuestTotalQuota(); - const stored = await SpAsyncUtil.getString(StorageKeys.guestTotalQuotaRemaining); - - expect(result.success).toBe(false); - expect(stored.success ? stored.data : null).toBe("{not-json"); - }); -}); diff --git a/src/data/storage/chat/chat_storage.ts b/src/data/storage/chat/chat_storage.ts index 2e0f7aa5..892ab934 100644 --- a/src/data/storage/chat/chat_storage.ts +++ b/src/data/storage/chat/chat_storage.ts @@ -1,17 +1,6 @@ "use client"; -import { - GuestChatQuotaSchema, - type GuestChatQuotaData, -} from "@/data/schemas/chat/guest_chat_quota"; -import { GuestChatQuota as GuestChatQuotaDto } from "@/data/dto/chat/guest_chat_quota"; -import { z } from "zod"; - -import { type Result as ResultT, Result, todayString, SpAsyncUtil } from "@/utils"; -import { StorageKeys } from "../storage_keys"; -import type { IChatStorage } from "./ichat_storage"; - -export class ChatStorage implements IChatStorage { +export class ChatStorage { private static _instance: ChatStorage | null = null; static getInstance(): ChatStorage { @@ -24,65 +13,6 @@ export class ChatStorage implements IChatStorage { ChatStorage._instance = null; } - // ---- guest daily chat quota ---- - - async getGuestDailyChatQuota(): Promise> { - const existing = await SpAsyncUtil.getJson( - StorageKeys.guestChatQuota, - GuestChatQuotaSchema, - ); - if (Result.isErr(existing)) return existing; - - const today = todayString(); - if (existing.data != null) { - const quota = GuestChatQuotaDto.from(existing.data); - if (!quota.needsReset(today)) return existing; - } - - const initResult = await this.setGuestDailyChatQuota( - GuestChatQuotaDto.threshold, - today, - ); - if (Result.isErr(initResult)) return existing; - - return { - success: true, - data: { remaining: GuestChatQuotaDto.threshold, date: today }, - }; - } - - setGuestDailyChatQuota(remaining: number, date: string): Promise> { - const value: GuestChatQuotaData = { remaining, date }; - return SpAsyncUtil.setJson(StorageKeys.guestChatQuota, value, GuestChatQuotaSchema); - } - - clearGuestDailyChatQuota(): Promise> { - return SpAsyncUtil.remove(StorageKeys.guestChatQuota); - } - - // ---- guest total quota ---- - - async getGuestTotalQuota(): Promise> { - const existing = await SpAsyncUtil.getJson( - StorageKeys.guestTotalQuotaRemaining, - z.number(), - ); - if (Result.isErr(existing)) return existing; - if (existing.data != null) return existing; - - const initResult = await this.setGuestTotalQuota( - GuestChatQuotaDto.totalQuotaDefault, - ); - if (Result.isErr(initResult)) return existing; - - return { success: true, data: GuestChatQuotaDto.totalQuotaDefault }; - } - - setGuestTotalQuota(remaining: number): Promise> { - return SpAsyncUtil.setJson(StorageKeys.guestTotalQuotaRemaining, remaining, z.number()); - } - - clearGuestTotalQuota(): Promise> { - return SpAsyncUtil.remove(StorageKeys.guestTotalQuotaRemaining); - } + // 本地游客消息数量额度逻辑已停用: + // 游客 / 非游客的消息数量限制统一由后端接口返回 blocked/daily_limit。 } diff --git a/src/data/storage/chat/ichat_storage.ts b/src/data/storage/chat/ichat_storage.ts deleted file mode 100644 index 4d743595..00000000 --- a/src/data/storage/chat/ichat_storage.ts +++ /dev/null @@ -1,28 +0,0 @@ -"use client"; - -/** - * IChatStorage 接口 - * - * 对齐 Dart 端 `IChatStorage`(lib/data/services/storage/chat/ichat_storage.dart): - * - 游客每日聊天配额 + 游客总配额 两个独立字段的 CRUD - * - * 注:`GuestChatQuota` 模型见 `src/data/dto/chat/guest_chat_quota.ts`, - * 数据形态 `{ remaining: number, date: string }`。 - * 跨天判断逻辑(`needsReset`)保留在 `GuestChatQuota` 类上。 - */ - -import type { Result } from "@/utils"; -import type { GuestChatQuotaData } from "@/data/schemas/chat/guest_chat_quota"; - -export interface IChatStorage { - getGuestDailyChatQuota(): Promise>; - setGuestDailyChatQuota( - remaining: number, - date: string, - ): Promise>; - clearGuestDailyChatQuota(): Promise>; - - getGuestTotalQuota(): Promise>; - setGuestTotalQuota(remaining: number): Promise>; - clearGuestTotalQuota(): Promise>; -} diff --git a/src/data/storage/chat/index.ts b/src/data/storage/chat/index.ts index f278bc90..b1510796 100644 --- a/src/data/storage/chat/index.ts +++ b/src/data/storage/chat/index.ts @@ -3,7 +3,6 @@ */ export * from "./chat_storage"; -export * from "./ichat_storage"; export * from "./local_chat_db"; export * from "./local_chat_storage"; export * from "./local_message"; diff --git a/src/data/storage/index.ts b/src/data/storage/index.ts index 5047502f..8e1b3a70 100644 --- a/src/data/storage/index.ts +++ b/src/data/storage/index.ts @@ -14,7 +14,6 @@ export * from "./app/app_storage"; export * from "./auth/auth_storage"; export * from "./auth/iauth_storage"; export * from "./chat/chat_storage"; -export * from "./chat/ichat_storage"; export * from "./chat/local_chat_db"; export * from "./chat/local_chat_storage"; export * from "./chat/local_message"; diff --git a/src/data/storage/storage_keys.ts b/src/data/storage/storage_keys.ts index d0c83f65..372b23de 100644 --- a/src/data/storage/storage_keys.ts +++ b/src/data/storage/storage_keys.ts @@ -21,8 +21,6 @@ export const StorageKeys = { // chat chatHistory: "chat_history", - guestChatQuota: "guest_chat_quota", - guestTotalQuotaRemaining: "guest_total_quota_remaining", // pwa / app info lastPwaDialogShown: "last_pwa_dialog_shown", diff --git a/src/stores/chat/chat-context.tsx b/src/stores/chat/chat-context.tsx index 3a52bfb8..0d8aa4e8 100644 --- a/src/stores/chat/chat-context.tsx +++ b/src/stores/chat/chat-context.tsx @@ -21,19 +21,12 @@ import type { ChatEvent, ChatState as MachineContext } from "./chat-machine"; interface ChatState { messages: MachineContext["messages"]; isReplyingAI: boolean; - /** 游客剩余配额(次/天)—— 业务展示用,鉴权判断由 chat-screen 派生 loginStatus */ - guestRemainingQuota: number; - /** 游客总配额 */ - guestTotalQuota: number; - quotaExceededTrigger: number; paywallTriggered: boolean; paywallReason: MachineContext["paywallReason"]; paywallDetail: MachineContext["paywallDetail"]; isLoadingMore: boolean; hasMore: boolean; historyOffset: number; - /** 游客配额加载完成标志(仅 guestSession 期间) —— UI 可用此显示 loading */ - quotaLoaded: boolean; /** history 初始加载完成标志(local → network → save 跑完) —— UI 可用此显示 loading */ historyLoaded: boolean; } @@ -53,16 +46,12 @@ export function ChatProvider({ children }: ChatProviderProps) { () => ({ messages: state.context.messages, isReplyingAI: state.context.isReplyingAI, - guestRemainingQuota: state.context.guestRemainingQuota, - guestTotalQuota: state.context.guestTotalQuota, - quotaExceededTrigger: state.context.quotaExceededTrigger, paywallTriggered: state.context.paywallTriggered, paywallReason: state.context.paywallReason, paywallDetail: state.context.paywallDetail, isLoadingMore: state.context.isLoadingMore, hasMore: state.context.hasMore, historyOffset: state.context.historyOffset, - quotaLoaded: state.context.quotaLoaded, historyLoaded: state.context.historyLoaded, }), [state], diff --git a/src/stores/chat/chat-events.ts b/src/stores/chat/chat-events.ts index a7723e32..6977abd3 100644 --- a/src/stores/chat/chat-events.ts +++ b/src/stores/chat/chat-events.ts @@ -43,5 +43,4 @@ export type ChatEvent = done: boolean; } | { type: "ChatWebSocketError"; errorMessage: string } - | { type: "ChatWebSocketConnected"; userId: string } - | { type: "ChatQuotaExceeded" }; + | { type: "ChatWebSocketConnected"; userId: string }; diff --git a/src/stores/chat/chat-machine.actors.ts b/src/stores/chat/chat-machine.actors.ts index 03ecce1d..4676a14c 100644 --- a/src/stores/chat/chat-machine.actors.ts +++ b/src/stores/chat/chat-machine.actors.ts @@ -13,7 +13,6 @@ import { chatRepo, localMessagesToUi, readAndSyncHistory, - readGuestQuota, sendResponseToUiMessage, } from "./chat-machine.helpers"; import type { ChatEvent } from "./chat-events"; @@ -42,20 +41,7 @@ export function getActiveChatWebSocket(): ChatWebSocket | null { return activeChatWebSocket; } -// ============================================================ -// Init 任务 1:拉游客配额(fromPromise,纯 local) -// ============================================================ -/** - * 拉游客日配 + 总配(仅 guestSession 期间 invoke) - * - 失败返 `{ remaining: 0, total: 0 }`(不抛,让 UI 还是能进 ready) - * - onDone 在 state machine 里赋 guestRemainingQuota + guestTotalQuota + 设 quotaLoaded: true - */ -export const loadQuotaActor = fromPromise<{ - remaining: number; - total: number; -}>(async () => { - return readGuestQuota(); -}); +// 本地游客消息额度 actor 已停用:消息数量限制统一交由后端 blocked/daily_limit 响应处理。 // ============================================================ // Init 任务 2:拉 history 3 步流(fromPromise,返回最终结果) diff --git a/src/stores/chat/chat-machine.helpers.ts b/src/stores/chat/chat-machine.helpers.ts index e0648532..1a73dfca 100644 --- a/src/stores/chat/chat-machine.helpers.ts +++ b/src/stores/chat/chat-machine.helpers.ts @@ -5,10 +5,7 @@ * - 翻页大小常量 * - 仓库注入(接口类型 → 单例) * - DTO ↔ UiMessage 映射(纯函数 —— 可单测) - * - Result → number 映射(纯函数 —— 可单测) - * - 2 个独立 init 任务的数据加载: - * - `readGuestQuota()` —— 游客日配 + 总配(仅游客有意义,纯 ChatStorage) - * - `readAndSyncHistory()` —— local → network → save network to local 3 步 + * - `readAndSyncHistory()` —— local → network → save network to local 3 步 * * 设计目标: * - helpers 无 XState 依赖(可独立 import / 测试) @@ -23,7 +20,6 @@ import type { UiMessage } from "@/data/dto/chat"; import { chatRepository } from "@/data/repositories/chat_repository"; import type { IChatRepository } from "@/data/repositories/interfaces"; -import { ChatStorage } from "@/data/storage/chat/chat_storage"; import { ChatSendResponse } from "@/data/dto/chat/chat_send_response"; import { todayString, Result, Logger } from "@/utils"; @@ -142,44 +138,8 @@ export function applyHttpSendOutput( }; } -// ============================================================ -// Result → number 映射 -// ============================================================ -/** 日配额 Result → number(纯函数) */ -export function mapQuotaResult( - r: Result<{ remaining: number } | null>, - fallback: number, -): number { - if (r.success && r.data != null) return r.data.remaining; - return fallback; -} - -/** 总配额 Result → number(纯函数) */ -export function mapTotalQuotaResult( - r: Result, - fallback: number, -): number { - if (r.success && r.data != null) return r.data; - return fallback; -} - -export async function readGuestQuota(): Promise<{ - remaining: number; - total: number; -}> { - const chatStorage = ChatStorage.getInstance(); - const [dailyResult, totalResult] = await Promise.all([ - chatStorage.getGuestDailyChatQuota(), - chatStorage.getGuestTotalQuota(), - ]); - return { - remaining: mapQuotaResult( - dailyResult as Result<{ remaining: number } | null>, - 0, - ), - total: mapTotalQuotaResult(totalResult as Result, 0), - }; -} +// 本地游客消息额度读取 / 映射逻辑已停用: +// 消息数量限制统一由后端接口返回 blocked/daily_limit,前端不再读取 ChatStorage quota。 // ============================================================ // Init 任务 2:history 3 步流(local → network → save)—— `loadHistoryActor` 调 diff --git a/src/stores/chat/chat-machine.ts b/src/stores/chat/chat-machine.ts index 833a1ec8..a95f9964 100644 --- a/src/stores/chat/chat-machine.ts +++ b/src/stores/chat/chat-machine.ts @@ -15,36 +15,33 @@ * - `nonVipUserSession`(parent):非 VIP 用户会话 —— 不 invoke WS * - `vipUserSession`(parent):VIP 用户会话 —— invoke WS(持久) * - * init 双任务(核心重构): - * - guestSession.initializing:loadQuota + loadHistory 并行(`invoke: [...]` 数组) + * init 任务: + * - guestSession.initializing:loadHistory * - nonVipUserSession.initializing:loadHistory * - vipUserSession.initializing:loadHistory + parent-level chatWebSocket 并行 * - 每个任务都是独立 actor,不互相等待(除非 `always` barrier) * * 消息发送路径(业务事实): - * - guestSession:走 HTTP,并先检查本地游客配额 + * - guestSession:走 HTTP,消息数量限制以后端 `blocked` 响应为准 * - nonVipUserSession:走 HTTP,让后端返回 daily_limit blocked * - vipUserSession + WS 已连:走 WS,不受每日免费次数限制 * - `ChatWebSocketConnected` 事件 → `wsConnected = true` * - `vipUserSession.exit` action → `wsConnected = false`(WS actor cleanup 时也会跑 exit) * * 配额: - * - 游客:保留本地配额 guard,命中后不发送消息 - * - 注册非 VIP:以后端 `blocked=true && blockReason="daily_limit"` 为准 - * - `appendUserMessage` 减 `context.wsConnected ? q : Math.max(0, q-1)` —— WS 已连时不递减 + * - 前端不再处理本地消息额度;游客 / 注册用户均以后端响应为准。 + * - 后端返回 `blocked=true && blockReason="daily_limit"` 时展示会员引导。 * */ import { setup, assign } from "xstate"; -import { ChatStorage } from "@/data/storage/chat/chat_storage"; import { todayString, Logger } from "@/utils"; import { ChatState, initialState } from "./chat-state"; import type { ChatEvent } from "./chat-events"; import { applyHttpSendOutput } from "./chat-machine.helpers"; import { - loadQuotaActor, loadHistoryActor, sendMessageHttpActor, sendMessageWsActor, @@ -68,7 +65,6 @@ export const chatMachine = setup({ events: {} as ChatEvent, }, actors: { - loadQuota: loadQuotaActor, loadHistory: loadHistoryActor, sendMessageHttp: sendMessageHttpActor, sendMessageWs: sendMessageWsActor, @@ -91,25 +87,11 @@ export const chatMachine = setup({ appendGuestUserMessage: assign(({ context, event }) => { if (event.type !== "ChatSendMessage") return {}; - // 游客消息发送成功前先乐观扣减本地日配额 + 总配额。 - const newRemaining = Math.max(0, context.guestRemainingQuota - 1); - const newTotal = Math.max(0, context.guestTotalQuota - 1); - - // 持久化两个额度( fire-and-forget,不 await —— assign 是 sync) - // daily quota 需要 today 字符串(让 ChatStorage 跨天判断 reset) const today = todayString(); - ChatStorage.getInstance().setGuestDailyChatQuota(newRemaining, today); - - ChatStorage.getInstance().setGuestTotalQuota(newTotal); - log.debug("[chat-machine] appendGuestUserMessage", { contentLength: event.content.length, contentPreview: event.content.slice(0, 50), - quotaMode: "guest http (decrement)", - oldRemaining: context.guestRemainingQuota, - newRemaining, - oldTotal: context.guestTotalQuota, - newTotal, + quotaMode: "server controlled", isReplyingAI: true, }); @@ -123,8 +105,6 @@ export const chatMachine = setup({ }, ], isReplyingAI: true, - guestRemainingQuota: newRemaining, - guestTotalQuota: newTotal, paywallTriggered: false, paywallReason: null, paywallDetail: null, @@ -160,22 +140,11 @@ export const chatMachine = setup({ appendGuestUserImage: assign(({ context, event }) => { if (event.type !== "ChatSendImage") return {}; - // 同 appendGuestUserMessage:游客两个额度同步减 - const newRemaining = Math.max(0, context.guestRemainingQuota - 1); - const newTotal = Math.max(0, context.guestTotalQuota - 1); - - const today = todayString(); - void ChatStorage.getInstance().setGuestDailyChatQuota(newRemaining, today); - void ChatStorage.getInstance().setGuestTotalQuota(newTotal); - + const today = todayString(); log.debug("[chat-machine] appendGuestUserImage", { oldMessagesCount: context.messages.length, - quotaMode: "guest http (decrement)", - oldRemaining: context.guestRemainingQuota, - newRemaining, - oldTotal: context.guestTotalQuota, - newTotal, + quotaMode: "server controlled", }); return { messages: [ @@ -188,8 +157,6 @@ export const chatMachine = setup({ }, ], isReplyingAI: true, - guestRemainingQuota: newRemaining, - guestTotalQuota: newTotal, paywallTriggered: false, paywallReason: null, paywallDetail: null, @@ -309,10 +276,6 @@ export const chatMachine = setup({ }; }), - incrementQuotaExceeded: assign(({ context }) => ({ - quotaExceededTrigger: context.quotaExceededTrigger + 1, - })), - setWsConnected: assign({ wsConnected: true }), clearWsConnected: assign({ wsConnected: false }), }, @@ -356,94 +319,44 @@ export const chatMachine = setup({ initial: "initializing", states: { initializing: { - // "always" barrier:两个任务都完成才进 ready + // 本地游客额度逻辑已停用:只等待历史加载完成。 always: [ { target: "ready", - guard: ({ context }) => context.quotaLoaded && context.historyLoaded, + guard: ({ context }) => context.historyLoaded, }, ], - invoke: [ - // 任务 1:加载配额(fromPromise,返结果 + onDone 设 flag) - { - id: "loadQuota", - src: "loadQuota", - onDone: { - actions: assign(({ event }) => ({ - guestRemainingQuota: event.output.remaining, - guestTotalQuota: event.output.total, - quotaLoaded: true, - })), - }, - onError: { - // 失败也标 loaded,不卡 init(游客可能 quota 服务不可用,让 UI 进 ready) - actions: assign({ - quotaLoaded: true, - }), - }, + invoke: { + id: "loadHistory", + src: "loadHistory", + onDone: { + actions: assign(({ event }) => ({ + messages: event.output.messages, + hasMore: event.output.hasMore, + historyOffset: event.output.newOffset, + historyLoaded: true, + })), }, - // 任务 2:拉 history(fromPromise,返回最终 network messages) - { - id: "loadHistory", - src: "loadHistory", - onDone: { - actions: assign(({ event }) => ({ - messages: event.output.messages, - hasMore: event.output.hasMore, - historyOffset: event.output.newOffset, - historyLoaded: true, - })), - }, - onError: { - // 失败也标 loaded,不卡 init(让 UI 还是能进 ready,屏幕可能空) - actions: assign({ - historyLoaded: true, - }), - }, + onError: { + // 失败也标 loaded,不卡 init(让 UI 还是能进 ready,屏幕可能空) + actions: assign({ + historyLoaded: true, + }), }, - ], + }, }, ready: { on: { - // 配额检查 + 发送消息(3 条 guard,按顺序匹配) - // 1. 总配额(guestTotalQuota)不足 → 触发 quota exceeded dialog,不发送 - // 2. 每日配额(guestRemainingQuota)不足 → 同上 - // 3. 两个配额都 OK + 内容非空 → 发送 + 减配额 - ChatSendMessage: [ - // 1. 总配额 不足(guestTotalQuota <= 0) → 触发 quota exceeded dialog - { - guard: ({ context }) => context.guestTotalQuota <= 0, - actions: "incrementQuotaExceeded", - }, - // 2. 每日配额 不足(guestRemainingQuota <= 0) → 触发 quota exceeded dialog - { - guard: ({ context }) => context.guestRemainingQuota <= 0, - actions: "incrementQuotaExceeded", - }, - // 3. 两个配额都 OK + 内容非空 → 发送(只用 appendUserMessage 自己的日志) - { - actions: "appendGuestUserMessage", - guard: ({ event }) => event.content.trim().length > 0, - target: "sending", - }, - ], - // 配额检查 + 发送图片(同样 3 条 guard,不检查 "内容空") - ChatSendImage: [ - { - guard: ({ context }) => context.guestTotalQuota <= 0, - actions: "incrementQuotaExceeded", - }, - { - guard: ({ context }) => context.guestRemainingQuota <= 0, - actions: "incrementQuotaExceeded", - }, - { - actions: "appendGuestUserImage", - target: "sending", - }, - ], + ChatSendMessage: { + actions: "appendGuestUserMessage", + guard: ({ event }) => event.content.trim().length > 0, + target: "sending", + }, + ChatSendImage: { + actions: "appendGuestUserImage", + target: "sending", + }, // 删除 ChatLoadMoreHistory / WS handlers —— 游客无服务端 history,也不连接 WS - ChatQuotaExceeded: { actions: "incrementQuotaExceeded" }, }, }, sending: { @@ -524,7 +437,6 @@ export const chatMachine = setup({ ChatLoadMoreHistory: { target: "loadingMore", }, - ChatQuotaExceeded: { actions: "incrementQuotaExceeded" }, }, }, sendingViaHttp: { @@ -665,7 +577,6 @@ export const chatMachine = setup({ ChatLoadMoreHistory: { target: "loadingMore", }, - ChatQuotaExceeded: { actions: "incrementQuotaExceeded" }, // 注:ChatAISentenceReceived / ChatWebSocketError / ChatWebSocketConnected // 已上提到 vipUserSession.on,子级不再声明 }, diff --git a/src/stores/chat/chat-state.ts b/src/stores/chat/chat-state.ts index e48d5024..b579ac8f 100644 --- a/src/stores/chat/chat-state.ts +++ b/src/stores/chat/chat-state.ts @@ -18,23 +18,12 @@ export interface ChatState { * - 非 VIP / 游客:固定 false,走 HTTP */ wsConnected: boolean; - /** 游客剩余配额(次/天)—— 仅游客业务展示用 - */ - guestRemainingQuota: number; - /** 游客总配额(仅游客展示用) */ - guestTotalQuota: number; - quotaExceededTrigger: number; paywallTriggered: boolean; paywallReason: "daily_limit" | "photo_paywall" | null; paywallDetail: { usedToday: number; limit: number } | null; isLoadingMore: boolean; hasMore: boolean; historyOffset: number; - /** 游客配额加载完成标志(仅 guestSession 期间) —— default false - * - guestSession.initializing 走 always barrier:`quotaLoaded && historyLoaded` 才进 ready - * - user sessions 永不为 true(不调 loadQuota)—— OK,不影响 barrier - */ - quotaLoaded: boolean; /** history 加载完成标志(initial load —— local → network → save 跑完) * - guestSession.initializing / user sessions initializing 走 always barrier * - 不被 `loadMoreHistoryActor` 设置(翻页是另一码事) @@ -46,15 +35,11 @@ export const initialState: ChatState = { messages: [], isReplyingAI: false, wsConnected: false, - guestRemainingQuota: 0, - guestTotalQuota: 0, - quotaExceededTrigger: 0, paywallTriggered: false, paywallReason: null, paywallDetail: null, isLoadingMore: false, hasMore: true, historyOffset: 0, - quotaLoaded: false, historyLoaded: false, }; From e21f2502a5ab9eaf329fc7ef89075013cdadac90 Mon Sep 17 00:00:00 2001 From: chenhang Date: Tue, 23 Jun 2026 11:42:33 +0800 Subject: [PATCH 3/5] feat(observability): add sentry monitoring --- .gitignore | 3 + next.config.ts | 14 +- package.json | 1 + pnpm-lock.yaml | 1311 ++++++++++++++++++++++++++++++++- sentry.edge.config.ts | 24 + sentry.server.config.ts | 23 + src/instrumentation-client.ts | 33 + src/instrumentation.ts | 13 + 8 files changed, 1400 insertions(+), 22 deletions(-) create mode 100644 sentry.edge.config.ts create mode 100644 sentry.server.config.ts create mode 100644 src/instrumentation-client.ts create mode 100644 src/instrumentation.ts diff --git a/.gitignore b/.gitignore index 756e1f64..fd12008c 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ implementation_plan.md # PWA build artifacts (regenerated each build, hashes change) public/sw.js public/workbox-*.js + +# Sentry Config File +.env.sentry-build-plugin diff --git a/next.config.ts b/next.config.ts index c4ede2aa..e14cdbda 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,3 +1,4 @@ +import { withSentryConfig } from "@sentry/nextjs"; import type { NextConfig } from "next"; import { withSerwist } from "@serwist/turbopack"; @@ -36,4 +37,15 @@ const nextConfig: NextConfig = { }, }; -export default withSerwist(nextConfig); +export default withSentryConfig(withSerwist(nextConfig), { + org: process.env.SENTRY_ORG ?? "shenzhen-banlv-zhidao-technolo", + project: process.env.SENTRY_PROJECT ?? "javascript-nextjs", + silent: !process.env.CI, + widenClientFileUpload: true, + webpack: { + automaticVercelMonitors: true, + treeshake: { + removeDebugLogging: true, + }, + }, +}); diff --git a/package.json b/package.json index 1ef85886..29c510fd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@fingerprintjs/fingerprintjs": "^5.2.0", + "@sentry/nextjs": "^10.59.0", "@stripe/react-stripe-js": "^6.6.0", "@stripe/stripe-js": "^9.8.0", "@xstate/react": "^5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ebe88d73..fa346b20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@fingerprintjs/fingerprintjs': specifier: ^5.2.0 version: 5.2.0 + '@sentry/nextjs': + specifier: ^10.59.0 + version: 10.59.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))(webpack@5.107.2(esbuild@0.25.12)) '@stripe/react-stripe-js': specifier: ^6.6.0 version: 6.6.0(@stripe/stripe-js@9.8.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -34,10 +37,10 @@ importers: version: 1.18.0(react@19.2.4) next: specifier: 16.2.7 - version: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next-auth: specifier: ^4.24.14 - version: 4.24.14(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 4.24.14(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) ofetch: specifier: ^1.5.1 version: 1.5.1 @@ -68,7 +71,7 @@ importers: devDependencies: '@serwist/turbopack': specifier: ^9.0.0 - version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) '@tailwindcss/postcss': specifier: ^4 version: 4.3.0 @@ -113,7 +116,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.1.8 - version: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) packages: @@ -121,6 +124,17 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@apm-js-collab/code-transformer-bundler-plugins@0.5.0': + resolution: {integrity: sha512-YxLBY5nGlurL7QeJLq6e5g0ouBpAp0pwgyA/5rHXEXwhiPLn9ZHbT+Y2LlP90GT872cSocfjWRYu/fnpuBudNQ==} + engines: {node: '>=18.0.0'} + + '@apm-js-collab/code-transformer@0.15.0': + resolution: {integrity: sha512-XmXYVs8CzJ1Aj79noVbn2weUO/XWtRyURpGqx7aU7DOXlUQhR0WKOQNF0okh7PCeY37vxf7kU3v57OAkEPm3ww==} + hasBin: true + + '@apm-js-collab/tracing-hooks@0.10.0': + resolution: {integrity: sha512-2/Z3NTewJTruUkmsSnBC5bJlLNUd9keuD1OLlTEpim4FyLhm6m2Rnfv+wrFdUvFfhmH8CRdiDZBqBrn+wyaGuA==} + '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -738,6 +752,42 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@opentelemetry/api-logs@0.214.0': + resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/core@2.8.0': + resolution: {integrity: sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/instrumentation@0.214.0': + resolution: {integrity: sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/resources@2.8.0': + resolution: {integrity: sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@2.8.0': + resolution: {integrity: sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.41.1': + resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} + engines: {node: '>=14'} + '@oxc-project/types@0.133.0': resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} @@ -848,9 +898,317 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@rollup/plugin-commonjs@28.0.1': + resolution: {integrity: sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.4.0': + resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + cpu: [x64] + os: [win32] + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@sentry/babel-plugin-component-annotate@5.3.0': + resolution: {integrity: sha512-p4q8gn8wcFqZGP/s2MnJCAAd8fTikaU6A0mM97RDHQgStcrYiaS0Sc5zUNfb1V+UOLPuvdEdL6MwyxfzjYJQTA==} + engines: {node: '>= 18'} + + '@sentry/browser-utils@10.59.0': + resolution: {integrity: sha512-DpJIrNi0Hsj/YONTZ8km1wv7ue2NzrTmFKJ3lRW8Q2nS/mrMeP3LCvjreLtKheTouB4go58NxM68AEFbXk4rPg==} + engines: {node: '>=18'} + + '@sentry/browser@10.59.0': + resolution: {integrity: sha512-d0o0oc78KNWCZ6yq9gREf9BPXWza/Wj9W+nCm0CvPD5k2IbouD/eJsm2Mb+d53YfEm12L+SePfgOx01KbbVx4A==} + engines: {node: '>=18'} + + '@sentry/bundler-plugin-core@5.3.0': + resolution: {integrity: sha512-L5T60sWdAI3qWwdg3Ptwek/0TY59PERrxyqp4XMUkroayQvGd9r5dIW9Q1kSeXX9iJ442nXbFZKAOyCKV4Z13Q==} + engines: {node: '>= 18'} + + '@sentry/cli-darwin@2.58.6': + resolution: {integrity: sha512-udAVvcyfNa0R+95GvPz/+43/N3TC0TYKdkQ7D7jhPSzbcMc7l2fxRNN5yB3UpCA5fWFnW4toeaqwDBhb/Wh3LA==} + engines: {node: '>=10'} + os: [darwin] + + '@sentry/cli-linux-arm64@2.58.6': + resolution: {integrity: sha512-q8mEcNNmeXMy5i+jWT30TVpH7LcP4HD21CD5XRSPAd/a912HF6EpK0ybf/1USO14WOhoXbAGi9txwaWabSe33g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux, freebsd, android] + + '@sentry/cli-linux-arm@2.58.6': + resolution: {integrity: sha512-pD0LAt5PcUzAinBwvDqc66x9+2CabHEv486yP0gRjWO7SakbaxmfVq/EXd8VLq/Tzi39LAu422UYK1lpW3MILw==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux, freebsd, android] + + '@sentry/cli-linux-i686@2.58.6': + resolution: {integrity: sha512-q8vNJi1eOV/4vxAFWBsEwLHoSYapaZHIf4j76KJGJXFKTkEbsjCOOsKbwUIBTQQhRgV4DFWh3ryfsPS/que4Kg==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [linux, freebsd, android] + + '@sentry/cli-linux-x64@2.58.6': + resolution: {integrity: sha512-DZu956Mhi3ZRjTBe1WdbGV46ldVbA8d2rgp/fh51GsI25zjBHah4wZnPTSzpc+YqxU6pJpg579B/r3jrIK530Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux, freebsd, android] + + '@sentry/cli-win32-arm64@2.58.6': + resolution: {integrity: sha512-nj0Ff/kmAB73EPDhR8B4O9r+NUHK5GkPCkGWC+kXVemqAJWL5jcJ5KdxG0l/S0z6RoEoltID8/43/B+TaMlT7A==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@sentry/cli-win32-i686@2.58.6': + resolution: {integrity: sha512-WNZiDzPbgsEMQWq4avsQ391v/xWKJDIWWWo9GYl+N/w5qcYKkoDW7wQG7T9FasI6ENn68phChTOAPXXxbfAdOg==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [win32] + + '@sentry/cli-win32-x64@2.58.6': + resolution: {integrity: sha512-R35WJ17oF4D2eqI1DR2sQQqr0fjRTt5xoP16WrTu91XM2lndRMFsnjh+/GttbxapLCBNlrjzia99MJ0PZHZpgA==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@sentry/cli@2.58.6': + resolution: {integrity: sha512-baBcNPLLfUi9WuL+Tpri9BFaAdvugZIKelC5X0tt0Zdy+K0K+PCVSrnNmwMWU/HyaF/SEv6b6UHnXIdqanBlcg==} + engines: {node: '>= 10'} + hasBin: true + + '@sentry/conventions@0.12.0': + resolution: {integrity: sha512-z1JQrl/1SLY+8wpzvork6vl+fpsg/oCCxM7HWWhUnI/R+OGNyoIzieQuggX3uUMY7NBtp8UWCQx6FeFazzOF9g==} + engines: {node: '>=14'} + + '@sentry/core@10.59.0': + resolution: {integrity: sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ==} + engines: {node: '>=18'} + + '@sentry/feedback@10.59.0': + resolution: {integrity: sha512-Sa/06LlG/mYR4z8/JlxOwvkcOHJnaMW6JyTMKNsgEoR1SHZULIpirjUuHIp4P+7R1mqX/KGTj8I7SQ3adA0TxQ==} + engines: {node: '>=18'} + + '@sentry/nextjs@10.59.0': + resolution: {integrity: sha512-McZJWks3IbhEi/Cp/02FHJHiln4w/SDsQvjPe8xC0ySz68IMeaPOC1S9T8Mj4/kdbVUP0/LHBe3K5fDWJulzcg==} + engines: {node: '>=18'} + peerDependencies: + next: ^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0 + + '@sentry/node-core@10.59.0': + resolution: {integrity: sha512-qFbepzntYhDleNG9ZCZWCSoAJK0Nsx+UJxsuiygaaAf1rJMj95RVckLyslhY86pyDLVATNMmWm2elm6etgKaJw==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1' + '@opentelemetry/instrumentation': '>=0.57.1 <1' + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/core': + optional: true + '@opentelemetry/exporter-trace-otlp-http': + optional: true + '@opentelemetry/instrumentation': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + + '@sentry/node@10.59.0': + resolution: {integrity: sha512-qzqbP6OVoMijlDBUxWtbvVF5j73+vyzGFi+yFIslhVvzBj97TFkIeP3TpBLsmu/0L5ZvxpQCCEmzJ677tFkq/g==} + engines: {node: '>=18'} + + '@sentry/opentelemetry@10.59.0': + resolution: {integrity: sha512-wV9/HR9btrNhSkJC2S0urqsD9pE4K0f6AmdfTK3qhH505mLoyV4ekTG66hdDR9xD2zOYCm58CNzaK+336zu3Gg==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + + '@sentry/react@10.59.0': + resolution: {integrity: sha512-B3MmXooGLnTu0gyL8hxElCu1+WVEXjIGoDPvGqn5qMHZNSmB2oPTAt1/UutuxAc6EWu2UKIHnyPowNeY2MPH3g==} + engines: {node: '>=18'} + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + + '@sentry/replay-canvas@10.59.0': + resolution: {integrity: sha512-bJkqvxQiat27P7+hUYC/m545Ct/uVxZCjh+PeCFdRcuHnZZ92e6Z7XPLf0LqAR6tR1U7wDUa4V5ugrMIEz+vpQ==} + engines: {node: '>=18'} + + '@sentry/replay@10.59.0': + resolution: {integrity: sha512-fpHL25JErsSfTyusuyZ3Q5JmRZeWYWynJO3PNiQH6A/58EqaCp8U5y8LCJ+CSPaeuBMka3S3Qn6U4eXcvkDMRA==} + engines: {node: '>=18'} + + '@sentry/server-utils@10.59.0': + resolution: {integrity: sha512-mR3fWaU7uGxIstRba6YO+/6V3qIa7432F7/U8EWHry+dY4C9DWAVG90E2GCzeD2MwLSP0tB25i8p1TWTGiQgVg==} + engines: {node: '>=18'} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + vite: + optional: true + + '@sentry/vercel-edge@10.59.0': + resolution: {integrity: sha512-4iVIZemakPvF8xlRAD7rlYtUlIloCvFHl3s2WGwO4vCa6vs1HtqggOdsDzW/zj6CoZ7kTu7+e7/Rw0EXYsWYrQ==} + engines: {node: '>=18'} + + '@sentry/webpack-plugin@5.3.0': + resolution: {integrity: sha512-i3OQUrS0FZlXLgq57RIKDp+vHHzuvYKPCKewAPXULWKMsBXFGhP6veGRQ+6To/pmZkkXjEX5ofVNDy9C3jEPKQ==} + engines: {node: '>= 18'} + peerDependencies: + webpack: '>=5.0.0' + '@serwist/build@9.5.11': resolution: {integrity: sha512-PQfW+LhADYFOOp0PhEnjlgJCyKor6cYa06d3rID1OpiKzkmCApJV1WYfdTBB96jXaWv6OWcWSbSV4tqDLxvaVA==} engines: {node: '>=18.0.0'} @@ -1355,6 +1713,51 @@ packages: '@vitest/utils@4.1.8': resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + '@xstate/react@5.0.5': resolution: {integrity: sha512-MfF/cPHa3lNKJmGFpUycMbNP25qBXyZXrxc8VYNroAu0Nnk0DV5WzAkTcQXma0xEC4dSwsoA+YQuKbZATtqvgg==} peerDependencies: @@ -1364,6 +1767,23 @@ packages: xstate: optional: true + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1374,9 +1794,29 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1442,6 +1882,10 @@ packages: ast-v8-to-istanbul@1.0.3: resolution: {integrity: sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg==} + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -1536,6 +1980,13 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -1566,6 +2017,9 @@ packages: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1663,6 +2117,10 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1813,6 +2271,10 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1851,10 +2313,17 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1862,6 +2331,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} @@ -1879,6 +2352,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -1975,6 +2451,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@13.0.6: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} @@ -2045,6 +2524,10 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + idb@8.0.3: resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} @@ -2060,6 +2543,10 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-in-the-middle@3.2.0: + resolution: {integrity: sha512-vR2B6HKIhaBjcZr2bLpFiJ1VbzOlRQ7aby4/gw5WPIzToLjqpfWw3VJ4sk1uDchoOODEirvO2jyrSPtUSL5CrQ==} + engines: {node: '>=18'} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2148,6 +2635,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -2209,6 +2699,10 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + jiti@2.7.0: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true @@ -2249,6 +2743,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -2360,6 +2857,10 @@ packages: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} + loader-runner@4.3.2: + resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} + engines: {node: '>=6.11.5'} + locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} @@ -2420,14 +2921,25 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + meriyah@6.1.4: + resolution: {integrity: sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==} + engines: {node: '>=18.0.0'} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} @@ -2442,6 +2954,9 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -2462,6 +2977,9 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next-auth@4.24.14: resolution: {integrity: sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig==} peerDependencies: @@ -2504,6 +3022,15 @@ packages: node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + node-mock-http@1.0.4: resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} @@ -2696,9 +3223,16 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2756,6 +3290,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-in-the-middle@8.0.1: + resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} + engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2777,6 +3315,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2803,6 +3346,13 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + + semifies@1.0.0: + resolution: {integrity: sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2905,6 +3455,10 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stacktrace-parser@0.1.11: + resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} + engines: {node: '>=6'} + std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} @@ -2972,6 +3526,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -2990,6 +3548,49 @@ packages: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} + terser-webpack-plugin@5.6.1: + resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@minify-html/node': '*' + '@swc/core': '*' + '@swc/css': '*' + '@swc/html': '*' + clean-css: '*' + cssnano: '*' + csso: '*' + esbuild: '*' + html-minifier-terser: '*' + lightningcss: '*' + postcss: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@minify-html/node': + optional: true + '@swc/core': + optional: true + '@swc/css': + optional: true + '@swc/html': + optional: true + clean-css: + optional: true + cssnano: + optional: true + csso: + optional: true + esbuild: + optional: true + html-minifier-terser: + optional: true + lightningcss: + optional: true + postcss: + optional: true + uglify-js: + optional: true + terser@5.48.0: resolution: {integrity: sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==} engines: {node: '>=10'} @@ -3033,6 +3634,9 @@ packages: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -3056,6 +3660,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + type-fest@5.6.0: resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} engines: {node: '>=20'} @@ -3293,6 +3901,13 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + watchpack@2.5.2: + resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} + engines: {node: '>=10.13.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -3300,6 +3915,20 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} + webpack-sources@3.5.0: + resolution: {integrity: sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==} + engines: {node: '>=10.13.0'} + + webpack@5.107.2: + resolution: {integrity: sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} @@ -3308,6 +3937,9 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} @@ -3393,6 +4025,30 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@apm-js-collab/code-transformer-bundler-plugins@0.5.0': + dependencies: + '@apm-js-collab/code-transformer': 0.15.0 + es-module-lexer: 2.1.0 + magic-string: 0.30.21 + module-details-from-path: 1.0.4 + + '@apm-js-collab/code-transformer@0.15.0': + dependencies: + '@types/estree': 1.0.9 + astring: 1.9.0 + esquery: 1.7.0 + meriyah: 6.1.4 + semifies: 1.0.0 + source-map: 0.6.1 + + '@apm-js-collab/tracing-hooks@0.10.0': + dependencies: + '@apm-js-collab/code-transformer': 0.15.0 + debug: 4.4.3 + module-details-from-path: 1.0.4 + transitivePeerDependencies: + - supports-color + '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 @@ -3818,7 +4474,6 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - optional: true '@jridgewell/sourcemap-codec@1.5.5': {} @@ -3878,6 +4533,41 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@opentelemetry/api-logs@0.214.0': + dependencies: + '@opentelemetry/api': 1.9.1 + + '@opentelemetry/api@1.9.1': {} + + '@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.214.0 + import-in-the-middle: 3.2.0 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/resources@2.8.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/semantic-conventions@1.41.1': {} + '@oxc-project/types@0.133.0': {} '@panva/hkdf@1.2.1': {} @@ -3937,8 +4627,288 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} + '@rollup/plugin-commonjs@28.0.1(rollup@4.62.2)': + dependencies: + '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.5.0(picomatch@4.0.4) + is-reference: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.4 + optionalDependencies: + rollup: 4.62.2 + + '@rollup/pluginutils@5.4.0(rollup@4.62.2)': + dependencies: + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.4 + optionalDependencies: + rollup: 4.62.2 + + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + '@rtsao/scc@1.1.0': {} + '@sentry/babel-plugin-component-annotate@5.3.0': {} + + '@sentry/browser-utils@10.59.0': + dependencies: + '@sentry/core': 10.59.0 + + '@sentry/browser@10.59.0': + dependencies: + '@sentry/browser-utils': 10.59.0 + '@sentry/core': 10.59.0 + '@sentry/feedback': 10.59.0 + '@sentry/replay': 10.59.0 + '@sentry/replay-canvas': 10.59.0 + + '@sentry/bundler-plugin-core@5.3.0': + dependencies: + '@babel/core': 7.29.7 + '@sentry/babel-plugin-component-annotate': 5.3.0 + '@sentry/cli': 2.58.6 + dotenv: 16.6.1 + find-up: 5.0.0 + glob: 13.0.6 + magic-string: 0.30.21 + transitivePeerDependencies: + - encoding + - supports-color + + '@sentry/cli-darwin@2.58.6': + optional: true + + '@sentry/cli-linux-arm64@2.58.6': + optional: true + + '@sentry/cli-linux-arm@2.58.6': + optional: true + + '@sentry/cli-linux-i686@2.58.6': + optional: true + + '@sentry/cli-linux-x64@2.58.6': + optional: true + + '@sentry/cli-win32-arm64@2.58.6': + optional: true + + '@sentry/cli-win32-i686@2.58.6': + optional: true + + '@sentry/cli-win32-x64@2.58.6': + optional: true + + '@sentry/cli@2.58.6': + dependencies: + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + optionalDependencies: + '@sentry/cli-darwin': 2.58.6 + '@sentry/cli-linux-arm': 2.58.6 + '@sentry/cli-linux-arm64': 2.58.6 + '@sentry/cli-linux-i686': 2.58.6 + '@sentry/cli-linux-x64': 2.58.6 + '@sentry/cli-win32-arm64': 2.58.6 + '@sentry/cli-win32-i686': 2.58.6 + '@sentry/cli-win32-x64': 2.58.6 + transitivePeerDependencies: + - encoding + - supports-color + + '@sentry/conventions@0.12.0': {} + + '@sentry/core@10.59.0': {} + + '@sentry/feedback@10.59.0': + dependencies: + '@sentry/core': 10.59.0 + + '@sentry/nextjs@10.59.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))(webpack@5.107.2(esbuild@0.25.12))': + dependencies: + '@opentelemetry/api': 1.9.1 + '@rollup/plugin-commonjs': 28.0.1(rollup@4.62.2) + '@sentry/browser-utils': 10.59.0 + '@sentry/bundler-plugin-core': 5.3.0 + '@sentry/conventions': 0.12.0 + '@sentry/core': 10.59.0 + '@sentry/node': 10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) + '@sentry/react': 10.59.0(react@19.2.4) + '@sentry/vercel-edge': 10.59.0 + '@sentry/webpack-plugin': 5.3.0(webpack@5.107.2(esbuild@0.25.12)) + next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + rollup: 4.62.2 + stacktrace-parser: 0.1.11 + transitivePeerDependencies: + - '@opentelemetry/core' + - '@opentelemetry/exporter-trace-otlp-http' + - '@opentelemetry/sdk-trace-base' + - encoding + - react + - supports-color + - vite + - webpack + + '@sentry/node-core@10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))': + dependencies: + '@sentry/conventions': 0.12.0 + '@sentry/core': 10.59.0 + '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) + import-in-the-middle: 3.2.0 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) + + '@sentry/node@10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + '@sentry/core': 10.59.0 + '@sentry/node-core': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) + '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) + '@sentry/server-utils': 10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + import-in-the-middle: 3.2.0 + transitivePeerDependencies: + - '@opentelemetry/exporter-trace-otlp-http' + - supports-color + - vite + + '@sentry/opentelemetry@10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) + '@sentry/conventions': 0.12.0 + '@sentry/core': 10.59.0 + + '@sentry/react@10.59.0(react@19.2.4)': + dependencies: + '@sentry/browser': 10.59.0 + '@sentry/core': 10.59.0 + react: 19.2.4 + + '@sentry/replay-canvas@10.59.0': + dependencies: + '@sentry/core': 10.59.0 + '@sentry/replay': 10.59.0 + + '@sentry/replay@10.59.0': + dependencies: + '@sentry/browser-utils': 10.59.0 + '@sentry/core': 10.59.0 + + '@sentry/server-utils@10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))': + dependencies: + '@apm-js-collab/code-transformer': 0.15.0 + '@apm-js-collab/code-transformer-bundler-plugins': 0.5.0 + '@apm-js-collab/tracing-hooks': 0.10.0 + '@sentry/conventions': 0.12.0 + '@sentry/core': 10.59.0 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0) + transitivePeerDependencies: + - supports-color + + '@sentry/vercel-edge@10.59.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) + '@sentry/core': 10.59.0 + + '@sentry/webpack-plugin@5.3.0(webpack@5.107.2(esbuild@0.25.12))': + dependencies: + '@sentry/bundler-plugin-core': 5.3.0 + webpack: 5.107.2(esbuild@0.25.12) + transitivePeerDependencies: + - encoding + - supports-color + '@serwist/build@9.5.11(browserslist@4.28.2)(typescript@5.9.3)': dependencies: '@serwist/utils': 9.5.11(browserslist@4.28.2) @@ -3953,7 +4923,7 @@ snapshots: transitivePeerDependencies: - browserslist - '@serwist/turbopack@9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)': + '@serwist/turbopack@9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)': dependencies: '@serwist/build': 9.5.11(browserslist@4.28.2)(typescript@5.9.3) '@serwist/utils': 9.5.11(browserslist@4.28.2) @@ -3961,7 +4931,7 @@ snapshots: '@swc/core': 1.15.32 browserslist: 4.28.2 kolorist: 1.8.0 - next: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 semver: 7.7.4 serwist: 9.5.11(browserslist@4.28.2)(typescript@5.9.3) @@ -4340,7 +5310,7 @@ snapshots: obug: 2.1.2 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) '@vitest/expect@4.1.8': dependencies: @@ -4386,7 +5356,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vitest: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) '@vitest/utils@4.1.8': dependencies: @@ -4394,6 +5364,82 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + '@xstate/react@5.0.5(@types/react@19.2.16)(react@19.2.4)(xstate@5.32.0)': dependencies: react: 19.2.4 @@ -4404,12 +5450,39 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + acorn-import-attributes@1.9.5(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn-import-phases@1.0.4(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 acorn@8.16.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-keywords@5.1.0(ajv@8.20.0): + dependencies: + ajv: 8.20.0 + fast-deep-equal: 3.1.3 + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 @@ -4417,6 +5490,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-regex@5.0.1: {} ansi-styles@3.2.1: @@ -4513,6 +5593,8 @@ snapshots: estree-walker: 3.0.3 js-tokens: 10.0.0 + astring@1.9.0: {} + async-function@1.0.0: {} atomic-sleep@1.0.0: {} @@ -4562,8 +5644,7 @@ snapshots: node-releases: 2.0.47 update-browserslist-db: 1.2.3(browserslist@4.28.2) - buffer-from@1.1.2: - optional: true + buffer-from@1.1.2: {} call-bind-apply-helpers@1.0.2: dependencies: @@ -4603,6 +5684,10 @@ snapshots: dependencies: readdirp: 5.0.0 + chrome-trace-event@1.0.4: {} + + cjs-module-lexer@2.2.0: {} + classnames@2.5.1: {} client-only@0.0.1: {} @@ -4625,11 +5710,12 @@ snapshots: color-name@1.1.4: {} - commander@2.20.3: - optional: true + commander@2.20.3: {} common-tags@1.8.2: {} + commondir@1.0.1: {} + concat-map@0.0.1: {} convert-source-map@2.0.0: {} @@ -4720,6 +5806,8 @@ snapshots: dependencies: esutils: 2.0.3 + dotenv@16.6.1: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -5016,6 +6104,11 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -5082,14 +6175,20 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 esutils@2.0.3: {} + events@3.3.0: {} + expect-type@1.3.0: {} fast-deep-equal@3.1.3: {} @@ -5106,6 +6205,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.2: {} + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -5206,6 +6307,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@13.0.6: dependencies: minimatch: 10.2.5 @@ -5275,6 +6378,13 @@ snapshots: html-escaper@2.0.2: {} + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + idb@8.0.3: {} ignore@5.3.2: {} @@ -5286,6 +6396,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@3.2.0: + dependencies: + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) + cjs-module-lexer: 2.2.0 + module-details-from-path: 1.0.4 + imurmurhash@0.1.4: {} internal-slot@1.1.0: @@ -5375,6 +6492,10 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.9 + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -5442,6 +6563,12 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + jest-worker@27.5.1: + dependencies: + '@types/node': 20.19.41 + merge-stream: 2.0.0 + supports-color: 8.1.1 + jiti@2.7.0: {} jose@4.15.9: {} @@ -5488,6 +6615,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: @@ -5576,6 +6705,8 @@ snapshots: pify: 3.0.0 strip-bom: 3.0.0 + loader-runner@4.3.2: {} + locate-path@2.0.0: dependencies: p-locate: 2.0.0 @@ -5633,13 +6764,19 @@ snapshots: mdn-data@2.27.1: {} + merge-stream@2.0.0: {} + merge2@1.4.1: {} + meriyah@6.1.4: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.2 + mime-db@1.54.0: {} + minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 @@ -5652,6 +6789,8 @@ snapshots: minipass@7.1.3: {} + module-details-from-path@1.0.4: {} + mrmime@2.0.1: {} ms@2.1.3: {} @@ -5662,13 +6801,15 @@ snapshots: natural-compare@1.4.0: {} - next-auth@4.24.14(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + neo-async@2.6.2: {} + + next-auth@4.24.14(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@babel/runtime': 7.29.7 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) oauth: 0.9.15 openid-client: 5.7.1 preact: 10.29.2 @@ -5677,7 +6818,7 @@ snapshots: react-dom: 19.2.4(react@19.2.4) uuid: 8.3.2 - next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@next/env': 16.2.7 '@swc/helpers': 0.5.15 @@ -5696,6 +6837,7 @@ snapshots: '@next/swc-linux-x64-musl': 16.2.7 '@next/swc-win32-arm64-msvc': 16.2.7 '@next/swc-win32-x64-msvc': 16.2.7 + '@opentelemetry/api': 1.9.1 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -5710,6 +6852,10 @@ snapshots: node-fetch-native@1.6.7: {} + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + node-mock-http@1.0.4: {} node-releases@2.0.47: {} @@ -5904,12 +7050,16 @@ snapshots: process-warning@5.0.0: {} + progress@2.0.3: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 + proxy-from-env@1.1.0: {} + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -5961,6 +7111,13 @@ snapshots: require-from-string@2.0.2: {} + require-in-the-middle@8.0.1: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + transitivePeerDependencies: + - supports-color + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -5997,6 +7154,37 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.3 '@rolldown/binding-win32-x64-msvc': 1.0.3 + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -6028,6 +7216,15 @@ snapshots: scheduler@0.27.0: {} + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) + + semifies@1.0.0: {} + semver@6.3.1: {} semver@7.7.4: {} @@ -6155,10 +7352,8 @@ snapshots: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - optional: true - source-map@0.6.1: - optional: true + source-map@0.6.1: {} source-map@0.8.0-beta.0: dependencies: @@ -6170,6 +7365,10 @@ snapshots: stackback@0.0.2: {} + stacktrace-parser@0.1.11: + dependencies: + type-fest: 0.7.1 + std-env@4.1.0: {} stop-iteration-iterator@1.1.0: @@ -6256,6 +7455,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} symbol-tree@3.2.4: {} @@ -6266,13 +7469,22 @@ snapshots: tapable@2.3.3: {} + terser-webpack-plugin@5.6.1(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.48.0 + webpack: 5.107.2(esbuild@0.25.12) + optionalDependencies: + esbuild: 0.25.12 + terser@5.48.0: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 - optional: true thread-stream@4.2.0: dependencies: @@ -6305,6 +7517,8 @@ snapshots: dependencies: tldts: 7.4.2 + tr46@0.0.3: {} + tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -6330,6 +7544,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@0.7.1: {} + type-fest@5.6.0: dependencies: tagged-tag: 1.0.0 @@ -6477,7 +7693,7 @@ snapshots: jiti: 2.7.0 terser: 5.48.0 - vitest@4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)): + vitest@4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)): dependencies: '@vitest/expect': 4.1.8 '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) @@ -6500,6 +7716,7 @@ snapshots: vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.1 '@types/node': 20.19.41 '@vitest/coverage-v8': 4.1.8(vitest@4.1.8) '@vitest/ui': 4.1.8(vitest@4.1.8) @@ -6511,10 +7728,57 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + watchpack@2.5.2: + dependencies: + graceful-fs: 4.2.11 + + webidl-conversions@3.0.1: {} + webidl-conversions@4.0.2: {} webidl-conversions@8.0.1: {} + webpack-sources@3.5.0: {} + + webpack@5.107.2(esbuild@0.25.12): + dependencies: + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) + browserslist: 4.28.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.22.2 + es-module-lexer: 2.1.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + loader-runner: 4.3.2 + mime-db: 1.54.0 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.3 + terser-webpack-plugin: 5.6.1(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)) + watchpack: 2.5.2 + webpack-sources: 3.5.0 + transitivePeerDependencies: + - '@minify-html/node' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - uglify-js + whatwg-mimetype@5.0.0: {} whatwg-url@16.0.1: @@ -6525,6 +7789,11 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0 diff --git a/sentry.edge.config.ts b/sentry.edge.config.ts new file mode 100644 index 00000000..c3be7f5b --- /dev/null +++ b/sentry.edge.config.ts @@ -0,0 +1,24 @@ +// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). +// The config you add here will be used whenever one of the edge features is loaded. +// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +const dsn = process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN; + +if (dsn) { + Sentry.init({ + dsn, + + tracesSampleRate: Number( + process.env.SENTRY_TRACES_SAMPLE_RATE ?? + (process.env.NODE_ENV === "production" ? "0.1" : "1"), + ), + + enableLogs: true, + + // Chat content and auth data are sensitive; do not send default PII. + sendDefaultPii: false, + }); +} diff --git a/sentry.server.config.ts b/sentry.server.config.ts new file mode 100644 index 00000000..5b4afe22 --- /dev/null +++ b/sentry.server.config.ts @@ -0,0 +1,23 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever the server handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +const dsn = process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN; + +if (dsn) { + Sentry.init({ + dsn, + + tracesSampleRate: Number( + process.env.SENTRY_TRACES_SAMPLE_RATE ?? + (process.env.NODE_ENV === "production" ? "0.1" : "1"), + ), + + enableLogs: true, + + // Chat content and auth data are sensitive; do not send default PII. + sendDefaultPii: false, + }); +} diff --git a/src/instrumentation-client.ts b/src/instrumentation-client.ts new file mode 100644 index 00000000..648aa205 --- /dev/null +++ b/src/instrumentation-client.ts @@ -0,0 +1,33 @@ +// This file configures the initialization of Sentry on the client. +// The added config here will be used whenever a users loads a page in their browser. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; + +if (dsn) { + Sentry.init({ + dsn, + + integrations: [Sentry.replayIntegration()], + + tracesSampleRate: Number( + process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE ?? + (process.env.NODE_ENV === "production" ? "0.1" : "1"), + ), + enableLogs: true, + + replaysSessionSampleRate: Number( + process.env.NEXT_PUBLIC_SENTRY_REPLAY_SAMPLE_RATE ?? "0.05", + ), + replaysOnErrorSampleRate: Number( + process.env.NEXT_PUBLIC_SENTRY_REPLAY_ERROR_SAMPLE_RATE ?? "1", + ), + + // Chat content and auth data are sensitive; do not send default PII. + sendDefaultPii: false, + }); +} + +export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; diff --git a/src/instrumentation.ts b/src/instrumentation.ts new file mode 100644 index 00000000..ecb65282 --- /dev/null +++ b/src/instrumentation.ts @@ -0,0 +1,13 @@ +import * as Sentry from "@sentry/nextjs"; + +export async function register() { + if (process.env.NEXT_RUNTIME === "nodejs") { + await import("../sentry.server.config"); + } + + if (process.env.NEXT_RUNTIME === "edge") { + await import("../sentry.edge.config"); + } +} + +export const onRequestError = Sentry.captureRequestError; From c9d75b6fe6407ecf58a5b27fde6f60d7fda616f1 Mon Sep 17 00:00:00 2001 From: chenhang Date: Tue, 23 Jun 2026 11:51:23 +0800 Subject: [PATCH 4/5] Revert "feat(observability): add sentry monitoring" This reverts commit e21f2502a5ab9eaf329fc7ef89075013cdadac90. --- .gitignore | 3 - next.config.ts | 14 +- package.json | 1 - pnpm-lock.yaml | 1311 +-------------------------------- sentry.edge.config.ts | 24 - sentry.server.config.ts | 23 - src/instrumentation-client.ts | 33 - src/instrumentation.ts | 13 - 8 files changed, 22 insertions(+), 1400 deletions(-) delete mode 100644 sentry.edge.config.ts delete mode 100644 sentry.server.config.ts delete mode 100644 src/instrumentation-client.ts delete mode 100644 src/instrumentation.ts diff --git a/.gitignore b/.gitignore index fd12008c..756e1f64 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,3 @@ implementation_plan.md # PWA build artifacts (regenerated each build, hashes change) public/sw.js public/workbox-*.js - -# Sentry Config File -.env.sentry-build-plugin diff --git a/next.config.ts b/next.config.ts index e14cdbda..c4ede2aa 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,4 +1,3 @@ -import { withSentryConfig } from "@sentry/nextjs"; import type { NextConfig } from "next"; import { withSerwist } from "@serwist/turbopack"; @@ -37,15 +36,4 @@ const nextConfig: NextConfig = { }, }; -export default withSentryConfig(withSerwist(nextConfig), { - org: process.env.SENTRY_ORG ?? "shenzhen-banlv-zhidao-technolo", - project: process.env.SENTRY_PROJECT ?? "javascript-nextjs", - silent: !process.env.CI, - widenClientFileUpload: true, - webpack: { - automaticVercelMonitors: true, - treeshake: { - removeDebugLogging: true, - }, - }, -}); +export default withSerwist(nextConfig); diff --git a/package.json b/package.json index 29c510fd..1ef85886 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ }, "dependencies": { "@fingerprintjs/fingerprintjs": "^5.2.0", - "@sentry/nextjs": "^10.59.0", "@stripe/react-stripe-js": "^6.6.0", "@stripe/stripe-js": "^9.8.0", "@xstate/react": "^5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa346b20..ebe88d73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ importers: '@fingerprintjs/fingerprintjs': specifier: ^5.2.0 version: 5.2.0 - '@sentry/nextjs': - specifier: ^10.59.0 - version: 10.59.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))(webpack@5.107.2(esbuild@0.25.12)) '@stripe/react-stripe-js': specifier: ^6.6.0 version: 6.6.0(@stripe/stripe-js@9.8.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -37,10 +34,10 @@ importers: version: 1.18.0(react@19.2.4) next: specifier: 16.2.7 - version: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next-auth: specifier: ^4.24.14 - version: 4.24.14(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 4.24.14(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) ofetch: specifier: ^1.5.1 version: 1.5.1 @@ -71,7 +68,7 @@ importers: devDependencies: '@serwist/turbopack': specifier: ^9.0.0 - version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) '@tailwindcss/postcss': specifier: ^4 version: 4.3.0 @@ -116,7 +113,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.1.8 - version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + version: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) packages: @@ -124,17 +121,6 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@apm-js-collab/code-transformer-bundler-plugins@0.5.0': - resolution: {integrity: sha512-YxLBY5nGlurL7QeJLq6e5g0ouBpAp0pwgyA/5rHXEXwhiPLn9ZHbT+Y2LlP90GT872cSocfjWRYu/fnpuBudNQ==} - engines: {node: '>=18.0.0'} - - '@apm-js-collab/code-transformer@0.15.0': - resolution: {integrity: sha512-XmXYVs8CzJ1Aj79noVbn2weUO/XWtRyURpGqx7aU7DOXlUQhR0WKOQNF0okh7PCeY37vxf7kU3v57OAkEPm3ww==} - hasBin: true - - '@apm-js-collab/tracing-hooks@0.10.0': - resolution: {integrity: sha512-2/Z3NTewJTruUkmsSnBC5bJlLNUd9keuD1OLlTEpim4FyLhm6m2Rnfv+wrFdUvFfhmH8CRdiDZBqBrn+wyaGuA==} - '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -752,42 +738,6 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} - '@opentelemetry/api-logs@0.214.0': - resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/api@1.9.1': - resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/core@2.8.0': - resolution: {integrity: sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/instrumentation@0.214.0': - resolution: {integrity: sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/resources@2.8.0': - resolution: {integrity: sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.10.0' - - '@opentelemetry/sdk-trace-base@2.8.0': - resolution: {integrity: sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.10.0' - - '@opentelemetry/semantic-conventions@1.41.1': - resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} - engines: {node: '>=14'} - '@oxc-project/types@0.133.0': resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} @@ -898,317 +848,9 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rollup/plugin-commonjs@28.0.1': - resolution: {integrity: sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==} - engines: {node: '>=16.0.0 || 14 >= 14.17'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@5.4.0': - resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} - cpu: [x64] - os: [win32] - '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@sentry/babel-plugin-component-annotate@5.3.0': - resolution: {integrity: sha512-p4q8gn8wcFqZGP/s2MnJCAAd8fTikaU6A0mM97RDHQgStcrYiaS0Sc5zUNfb1V+UOLPuvdEdL6MwyxfzjYJQTA==} - engines: {node: '>= 18'} - - '@sentry/browser-utils@10.59.0': - resolution: {integrity: sha512-DpJIrNi0Hsj/YONTZ8km1wv7ue2NzrTmFKJ3lRW8Q2nS/mrMeP3LCvjreLtKheTouB4go58NxM68AEFbXk4rPg==} - engines: {node: '>=18'} - - '@sentry/browser@10.59.0': - resolution: {integrity: sha512-d0o0oc78KNWCZ6yq9gREf9BPXWza/Wj9W+nCm0CvPD5k2IbouD/eJsm2Mb+d53YfEm12L+SePfgOx01KbbVx4A==} - engines: {node: '>=18'} - - '@sentry/bundler-plugin-core@5.3.0': - resolution: {integrity: sha512-L5T60sWdAI3qWwdg3Ptwek/0TY59PERrxyqp4XMUkroayQvGd9r5dIW9Q1kSeXX9iJ442nXbFZKAOyCKV4Z13Q==} - engines: {node: '>= 18'} - - '@sentry/cli-darwin@2.58.6': - resolution: {integrity: sha512-udAVvcyfNa0R+95GvPz/+43/N3TC0TYKdkQ7D7jhPSzbcMc7l2fxRNN5yB3UpCA5fWFnW4toeaqwDBhb/Wh3LA==} - engines: {node: '>=10'} - os: [darwin] - - '@sentry/cli-linux-arm64@2.58.6': - resolution: {integrity: sha512-q8mEcNNmeXMy5i+jWT30TVpH7LcP4HD21CD5XRSPAd/a912HF6EpK0ybf/1USO14WOhoXbAGi9txwaWabSe33g==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux, freebsd, android] - - '@sentry/cli-linux-arm@2.58.6': - resolution: {integrity: sha512-pD0LAt5PcUzAinBwvDqc66x9+2CabHEv486yP0gRjWO7SakbaxmfVq/EXd8VLq/Tzi39LAu422UYK1lpW3MILw==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux, freebsd, android] - - '@sentry/cli-linux-i686@2.58.6': - resolution: {integrity: sha512-q8vNJi1eOV/4vxAFWBsEwLHoSYapaZHIf4j76KJGJXFKTkEbsjCOOsKbwUIBTQQhRgV4DFWh3ryfsPS/que4Kg==} - engines: {node: '>=10'} - cpu: [x86, ia32] - os: [linux, freebsd, android] - - '@sentry/cli-linux-x64@2.58.6': - resolution: {integrity: sha512-DZu956Mhi3ZRjTBe1WdbGV46ldVbA8d2rgp/fh51GsI25zjBHah4wZnPTSzpc+YqxU6pJpg579B/r3jrIK530Q==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux, freebsd, android] - - '@sentry/cli-win32-arm64@2.58.6': - resolution: {integrity: sha512-nj0Ff/kmAB73EPDhR8B4O9r+NUHK5GkPCkGWC+kXVemqAJWL5jcJ5KdxG0l/S0z6RoEoltID8/43/B+TaMlT7A==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@sentry/cli-win32-i686@2.58.6': - resolution: {integrity: sha512-WNZiDzPbgsEMQWq4avsQ391v/xWKJDIWWWo9GYl+N/w5qcYKkoDW7wQG7T9FasI6ENn68phChTOAPXXxbfAdOg==} - engines: {node: '>=10'} - cpu: [x86, ia32] - os: [win32] - - '@sentry/cli-win32-x64@2.58.6': - resolution: {integrity: sha512-R35WJ17oF4D2eqI1DR2sQQqr0fjRTt5xoP16WrTu91XM2lndRMFsnjh+/GttbxapLCBNlrjzia99MJ0PZHZpgA==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@sentry/cli@2.58.6': - resolution: {integrity: sha512-baBcNPLLfUi9WuL+Tpri9BFaAdvugZIKelC5X0tt0Zdy+K0K+PCVSrnNmwMWU/HyaF/SEv6b6UHnXIdqanBlcg==} - engines: {node: '>= 10'} - hasBin: true - - '@sentry/conventions@0.12.0': - resolution: {integrity: sha512-z1JQrl/1SLY+8wpzvork6vl+fpsg/oCCxM7HWWhUnI/R+OGNyoIzieQuggX3uUMY7NBtp8UWCQx6FeFazzOF9g==} - engines: {node: '>=14'} - - '@sentry/core@10.59.0': - resolution: {integrity: sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ==} - engines: {node: '>=18'} - - '@sentry/feedback@10.59.0': - resolution: {integrity: sha512-Sa/06LlG/mYR4z8/JlxOwvkcOHJnaMW6JyTMKNsgEoR1SHZULIpirjUuHIp4P+7R1mqX/KGTj8I7SQ3adA0TxQ==} - engines: {node: '>=18'} - - '@sentry/nextjs@10.59.0': - resolution: {integrity: sha512-McZJWks3IbhEi/Cp/02FHJHiln4w/SDsQvjPe8xC0ySz68IMeaPOC1S9T8Mj4/kdbVUP0/LHBe3K5fDWJulzcg==} - engines: {node: '>=18'} - peerDependencies: - next: ^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0 - - '@sentry/node-core@10.59.0': - resolution: {integrity: sha512-qFbepzntYhDleNG9ZCZWCSoAJK0Nsx+UJxsuiygaaAf1rJMj95RVckLyslhY86pyDLVATNMmWm2elm6etgKaJw==} - engines: {node: '>=18'} - peerDependencies: - '@opentelemetry/api': ^1.9.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 - '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1' - '@opentelemetry/instrumentation': '>=0.57.1 <1' - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@opentelemetry/core': - optional: true - '@opentelemetry/exporter-trace-otlp-http': - optional: true - '@opentelemetry/instrumentation': - optional: true - '@opentelemetry/sdk-trace-base': - optional: true - - '@sentry/node@10.59.0': - resolution: {integrity: sha512-qzqbP6OVoMijlDBUxWtbvVF5j73+vyzGFi+yFIslhVvzBj97TFkIeP3TpBLsmu/0L5ZvxpQCCEmzJ677tFkq/g==} - engines: {node: '>=18'} - - '@sentry/opentelemetry@10.59.0': - resolution: {integrity: sha512-wV9/HR9btrNhSkJC2S0urqsD9pE4K0f6AmdfTK3qhH505mLoyV4ekTG66hdDR9xD2zOYCm58CNzaK+336zu3Gg==} - engines: {node: '>=18'} - peerDependencies: - '@opentelemetry/api': ^1.9.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 - - '@sentry/react@10.59.0': - resolution: {integrity: sha512-B3MmXooGLnTu0gyL8hxElCu1+WVEXjIGoDPvGqn5qMHZNSmB2oPTAt1/UutuxAc6EWu2UKIHnyPowNeY2MPH3g==} - engines: {node: '>=18'} - peerDependencies: - react: ^16.14.0 || 17.x || 18.x || 19.x - - '@sentry/replay-canvas@10.59.0': - resolution: {integrity: sha512-bJkqvxQiat27P7+hUYC/m545Ct/uVxZCjh+PeCFdRcuHnZZ92e6Z7XPLf0LqAR6tR1U7wDUa4V5ugrMIEz+vpQ==} - engines: {node: '>=18'} - - '@sentry/replay@10.59.0': - resolution: {integrity: sha512-fpHL25JErsSfTyusuyZ3Q5JmRZeWYWynJO3PNiQH6A/58EqaCp8U5y8LCJ+CSPaeuBMka3S3Qn6U4eXcvkDMRA==} - engines: {node: '>=18'} - - '@sentry/server-utils@10.59.0': - resolution: {integrity: sha512-mR3fWaU7uGxIstRba6YO+/6V3qIa7432F7/U8EWHry+dY4C9DWAVG90E2GCzeD2MwLSP0tB25i8p1TWTGiQgVg==} - engines: {node: '>=18'} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - vite: - optional: true - - '@sentry/vercel-edge@10.59.0': - resolution: {integrity: sha512-4iVIZemakPvF8xlRAD7rlYtUlIloCvFHl3s2WGwO4vCa6vs1HtqggOdsDzW/zj6CoZ7kTu7+e7/Rw0EXYsWYrQ==} - engines: {node: '>=18'} - - '@sentry/webpack-plugin@5.3.0': - resolution: {integrity: sha512-i3OQUrS0FZlXLgq57RIKDp+vHHzuvYKPCKewAPXULWKMsBXFGhP6veGRQ+6To/pmZkkXjEX5ofVNDy9C3jEPKQ==} - engines: {node: '>= 18'} - peerDependencies: - webpack: '>=5.0.0' - '@serwist/build@9.5.11': resolution: {integrity: sha512-PQfW+LhADYFOOp0PhEnjlgJCyKor6cYa06d3rID1OpiKzkmCApJV1WYfdTBB96jXaWv6OWcWSbSV4tqDLxvaVA==} engines: {node: '>=18.0.0'} @@ -1713,51 +1355,6 @@ packages: '@vitest/utils@4.1.8': resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} - '@webassemblyjs/ast@1.14.1': - resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - - '@webassemblyjs/floating-point-hex-parser@1.13.2': - resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - - '@webassemblyjs/helper-api-error@1.13.2': - resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - - '@webassemblyjs/helper-buffer@1.14.1': - resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - - '@webassemblyjs/helper-numbers@1.13.2': - resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': - resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - - '@webassemblyjs/helper-wasm-section@1.14.1': - resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - - '@webassemblyjs/ieee754@1.13.2': - resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - - '@webassemblyjs/leb128@1.13.2': - resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - - '@webassemblyjs/utf8@1.13.2': - resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - - '@webassemblyjs/wasm-edit@1.14.1': - resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - - '@webassemblyjs/wasm-gen@1.14.1': - resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - - '@webassemblyjs/wasm-opt@1.14.1': - resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - - '@webassemblyjs/wasm-parser@1.14.1': - resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - - '@webassemblyjs/wast-printer@1.14.1': - resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - '@xstate/react@5.0.5': resolution: {integrity: sha512-MfF/cPHa3lNKJmGFpUycMbNP25qBXyZXrxc8VYNroAu0Nnk0DV5WzAkTcQXma0xEC4dSwsoA+YQuKbZATtqvgg==} peerDependencies: @@ -1767,23 +1364,6 @@ packages: xstate: optional: true - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - - acorn-import-attributes@1.9.5: - resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} - peerDependencies: - acorn: ^8 - - acorn-import-phases@1.0.4: - resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} - engines: {node: '>=10.13.0'} - peerDependencies: - acorn: ^8.14.0 - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1794,29 +1374,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv-keywords@5.1.0: - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - ajv@8.20.0: - resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1882,10 +1442,6 @@ packages: ast-v8-to-istanbul@1.0.3: resolution: {integrity: sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg==} - astring@1.9.0: - resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} - hasBin: true - async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -1980,13 +1536,6 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} - - cjs-module-lexer@2.2.0: - resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} - classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -2017,9 +1566,6 @@ packages: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -2117,10 +1663,6 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -2271,10 +1813,6 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2313,17 +1851,10 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -2331,10 +1862,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} @@ -2352,9 +1879,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.1.2: - resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} - fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -2451,9 +1975,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@13.0.6: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} @@ -2524,10 +2045,6 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - idb@8.0.3: resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} @@ -2543,10 +2060,6 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-in-the-middle@3.2.0: - resolution: {integrity: sha512-vR2B6HKIhaBjcZr2bLpFiJ1VbzOlRQ7aby4/gw5WPIzToLjqpfWw3VJ4sk1uDchoOODEirvO2jyrSPtUSL5CrQ==} - engines: {node: '>=18'} - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2635,9 +2148,6 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -2699,10 +2209,6 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - jiti@2.7.0: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true @@ -2743,9 +2249,6 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -2857,10 +2360,6 @@ packages: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} - loader-runner@4.3.2: - resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} - engines: {node: '>=6.11.5'} - locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} @@ -2921,25 +2420,14 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - meriyah@6.1.4: - resolution: {integrity: sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==} - engines: {node: '>=18.0.0'} - micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} @@ -2954,9 +2442,6 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} - module-details-from-path@1.0.4: - resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} - mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -2977,9 +2462,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - next-auth@4.24.14: resolution: {integrity: sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig==} peerDependencies: @@ -3022,15 +2504,6 @@ packages: node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-mock-http@1.0.4: resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} @@ -3223,16 +2696,9 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} - progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -3290,10 +2756,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-in-the-middle@8.0.1: - resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} - engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -3315,11 +2777,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -3346,13 +2803,6 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - schema-utils@4.3.3: - resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} - engines: {node: '>= 10.13.0'} - - semifies@1.0.0: - resolution: {integrity: sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw==} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3455,10 +2905,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - stacktrace-parser@0.1.11: - resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} - engines: {node: '>=6'} - std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} @@ -3526,10 +2972,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -3548,49 +2990,6 @@ packages: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} - terser-webpack-plugin@5.6.1: - resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@minify-html/node': '*' - '@swc/core': '*' - '@swc/css': '*' - '@swc/html': '*' - clean-css: '*' - cssnano: '*' - csso: '*' - esbuild: '*' - html-minifier-terser: '*' - lightningcss: '*' - postcss: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@minify-html/node': - optional: true - '@swc/core': - optional: true - '@swc/css': - optional: true - '@swc/html': - optional: true - clean-css: - optional: true - cssnano: - optional: true - csso: - optional: true - esbuild: - optional: true - html-minifier-terser: - optional: true - lightningcss: - optional: true - postcss: - optional: true - uglify-js: - optional: true - terser@5.48.0: resolution: {integrity: sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==} engines: {node: '>=10'} @@ -3634,9 +3033,6 @@ packages: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -3660,10 +3056,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - type-fest@5.6.0: resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} engines: {node: '>=20'} @@ -3901,13 +3293,6 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - watchpack@2.5.2: - resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} - engines: {node: '>=10.13.0'} - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -3915,20 +3300,6 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} - webpack-sources@3.5.0: - resolution: {integrity: sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==} - engines: {node: '>=10.13.0'} - - webpack@5.107.2: - resolution: {integrity: sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} @@ -3937,9 +3308,6 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} @@ -4025,30 +3393,6 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@apm-js-collab/code-transformer-bundler-plugins@0.5.0': - dependencies: - '@apm-js-collab/code-transformer': 0.15.0 - es-module-lexer: 2.1.0 - magic-string: 0.30.21 - module-details-from-path: 1.0.4 - - '@apm-js-collab/code-transformer@0.15.0': - dependencies: - '@types/estree': 1.0.9 - astring: 1.9.0 - esquery: 1.7.0 - meriyah: 6.1.4 - semifies: 1.0.0 - source-map: 0.6.1 - - '@apm-js-collab/tracing-hooks@0.10.0': - dependencies: - '@apm-js-collab/code-transformer': 0.15.0 - debug: 4.4.3 - module-details-from-path: 1.0.4 - transitivePeerDependencies: - - supports-color - '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 @@ -4474,6 +3818,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 + optional: true '@jridgewell/sourcemap-codec@1.5.5': {} @@ -4533,41 +3878,6 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} - '@opentelemetry/api-logs@0.214.0': - dependencies: - '@opentelemetry/api': 1.9.1 - - '@opentelemetry/api@1.9.1': {} - - '@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1)': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/semantic-conventions': 1.41.1 - - '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.214.0 - import-in-the-middle: 3.2.0 - require-in-the-middle: 8.0.1 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/resources@2.8.0(@opentelemetry/api@1.9.1)': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 - - '@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 - - '@opentelemetry/semantic-conventions@1.41.1': {} - '@oxc-project/types@0.133.0': {} '@panva/hkdf@1.2.1': {} @@ -4627,288 +3937,8 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@rollup/plugin-commonjs@28.0.1(rollup@4.62.2)': - dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) - commondir: 1.0.1 - estree-walker: 2.0.2 - fdir: 6.5.0(picomatch@4.0.4) - is-reference: 1.2.1 - magic-string: 0.30.21 - picomatch: 4.0.4 - optionalDependencies: - rollup: 4.62.2 - - '@rollup/pluginutils@5.4.0(rollup@4.62.2)': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.4 - optionalDependencies: - rollup: 4.62.2 - - '@rollup/rollup-android-arm-eabi@4.62.2': - optional: true - - '@rollup/rollup-android-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-x64@4.62.2': - optional: true - - '@rollup/rollup-freebsd-arm64@4.62.2': - optional: true - - '@rollup/rollup-freebsd-x64@4.62.2': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.62.2': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.62.2': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.62.2': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.62.2': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-x64-musl@4.62.2': - optional: true - - '@rollup/rollup-openbsd-x64@4.62.2': - optional: true - - '@rollup/rollup-openharmony-arm64@4.62.2': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.62.2': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.62.2': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.62.2': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.62.2': - optional: true - '@rtsao/scc@1.1.0': {} - '@sentry/babel-plugin-component-annotate@5.3.0': {} - - '@sentry/browser-utils@10.59.0': - dependencies: - '@sentry/core': 10.59.0 - - '@sentry/browser@10.59.0': - dependencies: - '@sentry/browser-utils': 10.59.0 - '@sentry/core': 10.59.0 - '@sentry/feedback': 10.59.0 - '@sentry/replay': 10.59.0 - '@sentry/replay-canvas': 10.59.0 - - '@sentry/bundler-plugin-core@5.3.0': - dependencies: - '@babel/core': 7.29.7 - '@sentry/babel-plugin-component-annotate': 5.3.0 - '@sentry/cli': 2.58.6 - dotenv: 16.6.1 - find-up: 5.0.0 - glob: 13.0.6 - magic-string: 0.30.21 - transitivePeerDependencies: - - encoding - - supports-color - - '@sentry/cli-darwin@2.58.6': - optional: true - - '@sentry/cli-linux-arm64@2.58.6': - optional: true - - '@sentry/cli-linux-arm@2.58.6': - optional: true - - '@sentry/cli-linux-i686@2.58.6': - optional: true - - '@sentry/cli-linux-x64@2.58.6': - optional: true - - '@sentry/cli-win32-arm64@2.58.6': - optional: true - - '@sentry/cli-win32-i686@2.58.6': - optional: true - - '@sentry/cli-win32-x64@2.58.6': - optional: true - - '@sentry/cli@2.58.6': - dependencies: - https-proxy-agent: 5.0.1 - node-fetch: 2.7.0 - progress: 2.0.3 - proxy-from-env: 1.1.0 - which: 2.0.2 - optionalDependencies: - '@sentry/cli-darwin': 2.58.6 - '@sentry/cli-linux-arm': 2.58.6 - '@sentry/cli-linux-arm64': 2.58.6 - '@sentry/cli-linux-i686': 2.58.6 - '@sentry/cli-linux-x64': 2.58.6 - '@sentry/cli-win32-arm64': 2.58.6 - '@sentry/cli-win32-i686': 2.58.6 - '@sentry/cli-win32-x64': 2.58.6 - transitivePeerDependencies: - - encoding - - supports-color - - '@sentry/conventions@0.12.0': {} - - '@sentry/core@10.59.0': {} - - '@sentry/feedback@10.59.0': - dependencies: - '@sentry/core': 10.59.0 - - '@sentry/nextjs@10.59.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))(webpack@5.107.2(esbuild@0.25.12))': - dependencies: - '@opentelemetry/api': 1.9.1 - '@rollup/plugin-commonjs': 28.0.1(rollup@4.62.2) - '@sentry/browser-utils': 10.59.0 - '@sentry/bundler-plugin-core': 5.3.0 - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.59.0 - '@sentry/node': 10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) - '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) - '@sentry/react': 10.59.0(react@19.2.4) - '@sentry/vercel-edge': 10.59.0 - '@sentry/webpack-plugin': 5.3.0(webpack@5.107.2(esbuild@0.25.12)) - next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - rollup: 4.62.2 - stacktrace-parser: 0.1.11 - transitivePeerDependencies: - - '@opentelemetry/core' - - '@opentelemetry/exporter-trace-otlp-http' - - '@opentelemetry/sdk-trace-base' - - encoding - - react - - supports-color - - vite - - webpack - - '@sentry/node-core@10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))': - dependencies: - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.59.0 - '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) - import-in-the-middle: 3.2.0 - optionalDependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) - - '@sentry/node@10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 - '@sentry/core': 10.59.0 - '@sentry/node-core': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) - '@sentry/opentelemetry': 10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)) - '@sentry/server-utils': 10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) - import-in-the-middle: 3.2.0 - transitivePeerDependencies: - - '@opentelemetry/exporter-trace-otlp-http' - - supports-color - - vite - - '@sentry/opentelemetry@10.59.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.59.0 - - '@sentry/react@10.59.0(react@19.2.4)': - dependencies: - '@sentry/browser': 10.59.0 - '@sentry/core': 10.59.0 - react: 19.2.4 - - '@sentry/replay-canvas@10.59.0': - dependencies: - '@sentry/core': 10.59.0 - '@sentry/replay': 10.59.0 - - '@sentry/replay@10.59.0': - dependencies: - '@sentry/browser-utils': 10.59.0 - '@sentry/core': 10.59.0 - - '@sentry/server-utils@10.59.0(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))': - dependencies: - '@apm-js-collab/code-transformer': 0.15.0 - '@apm-js-collab/code-transformer-bundler-plugins': 0.5.0 - '@apm-js-collab/tracing-hooks': 0.10.0 - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.59.0 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0) - transitivePeerDependencies: - - supports-color - - '@sentry/vercel-edge@10.59.0': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@sentry/core': 10.59.0 - - '@sentry/webpack-plugin@5.3.0(webpack@5.107.2(esbuild@0.25.12))': - dependencies: - '@sentry/bundler-plugin-core': 5.3.0 - webpack: 5.107.2(esbuild@0.25.12) - transitivePeerDependencies: - - encoding - - supports-color - '@serwist/build@9.5.11(browserslist@4.28.2)(typescript@5.9.3)': dependencies: '@serwist/utils': 9.5.11(browserslist@4.28.2) @@ -4923,7 +3953,7 @@ snapshots: transitivePeerDependencies: - browserslist - '@serwist/turbopack@9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)': + '@serwist/turbopack@9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)': dependencies: '@serwist/build': 9.5.11(browserslist@4.28.2)(typescript@5.9.3) '@serwist/utils': 9.5.11(browserslist@4.28.2) @@ -4931,7 +3961,7 @@ snapshots: '@swc/core': 1.15.32 browserslist: 4.28.2 kolorist: 1.8.0 - next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 semver: 7.7.4 serwist: 9.5.11(browserslist@4.28.2)(typescript@5.9.3) @@ -5310,7 +4340,7 @@ snapshots: obug: 2.1.2 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + vitest: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) '@vitest/expect@4.1.8': dependencies: @@ -5356,7 +4386,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) + vitest: 4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) '@vitest/utils@4.1.8': dependencies: @@ -5364,82 +4394,6 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - - '@webassemblyjs/helper-api-error@1.13.2': {} - - '@webassemblyjs/helper-buffer@1.14.1': {} - - '@webassemblyjs/helper-numbers@1.13.2': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.13.2 - '@webassemblyjs/helper-api-error': 1.13.2 - '@xtuc/long': 4.2.2 - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} - - '@webassemblyjs/helper-wasm-section@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/wasm-gen': 1.14.1 - - '@webassemblyjs/ieee754@1.13.2': - dependencies: - '@xtuc/ieee754': 1.2.0 - - '@webassemblyjs/leb128@1.13.2': - dependencies: - '@xtuc/long': 4.2.2 - - '@webassemblyjs/utf8@1.13.2': {} - - '@webassemblyjs/wasm-edit@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/helper-wasm-section': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-opt': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wast-printer': 1.14.1 - - '@webassemblyjs/wasm-gen@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wasm-opt@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - - '@webassemblyjs/wasm-parser@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-api-error': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wast-printer@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@xtuc/long': 4.2.2 - '@xstate/react@5.0.5(@types/react@19.2.16)(react@19.2.4)(xstate@5.32.0)': dependencies: react: 19.2.4 @@ -5450,39 +4404,12 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@xtuc/ieee754@1.2.0': {} - - '@xtuc/long@4.2.2': {} - - acorn-import-attributes@1.9.5(acorn@8.16.0): - dependencies: - acorn: 8.16.0 - - acorn-import-phases@1.0.4(acorn@8.16.0): - dependencies: - acorn: 8.16.0 - acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 acorn@8.16.0: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - ajv-formats@2.1.1(ajv@8.20.0): - optionalDependencies: - ajv: 8.20.0 - - ajv-keywords@5.1.0(ajv@8.20.0): - dependencies: - ajv: 8.20.0 - fast-deep-equal: 3.1.3 - ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 @@ -5490,13 +4417,6 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.20.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.2 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-regex@5.0.1: {} ansi-styles@3.2.1: @@ -5593,8 +4513,6 @@ snapshots: estree-walker: 3.0.3 js-tokens: 10.0.0 - astring@1.9.0: {} - async-function@1.0.0: {} atomic-sleep@1.0.0: {} @@ -5644,7 +4562,8 @@ snapshots: node-releases: 2.0.47 update-browserslist-db: 1.2.3(browserslist@4.28.2) - buffer-from@1.1.2: {} + buffer-from@1.1.2: + optional: true call-bind-apply-helpers@1.0.2: dependencies: @@ -5684,10 +4603,6 @@ snapshots: dependencies: readdirp: 5.0.0 - chrome-trace-event@1.0.4: {} - - cjs-module-lexer@2.2.0: {} - classnames@2.5.1: {} client-only@0.0.1: {} @@ -5710,12 +4625,11 @@ snapshots: color-name@1.1.4: {} - commander@2.20.3: {} + commander@2.20.3: + optional: true common-tags@1.8.2: {} - commondir@1.0.1: {} - concat-map@0.0.1: {} convert-source-map@2.0.0: {} @@ -5806,8 +4720,6 @@ snapshots: dependencies: esutils: 2.0.3 - dotenv@16.6.1: {} - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -6104,11 +5016,6 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -6175,20 +5082,14 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} - estree-walker@2.0.2: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 esutils@2.0.3: {} - events@3.3.0: {} - expect-type@1.3.0: {} fast-deep-equal@3.1.3: {} @@ -6205,8 +5106,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.1.2: {} - fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -6307,8 +5206,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - glob@13.0.6: dependencies: minimatch: 10.2.5 @@ -6378,13 +5275,6 @@ snapshots: html-escaper@2.0.2: {} - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - idb@8.0.3: {} ignore@5.3.2: {} @@ -6396,13 +5286,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-in-the-middle@3.2.0: - dependencies: - acorn: 8.16.0 - acorn-import-attributes: 1.9.5(acorn@8.16.0) - cjs-module-lexer: 2.2.0 - module-details-from-path: 1.0.4 - imurmurhash@0.1.4: {} internal-slot@1.1.0: @@ -6492,10 +5375,6 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.9 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -6563,12 +5442,6 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jest-worker@27.5.1: - dependencies: - '@types/node': 20.19.41 - merge-stream: 2.0.0 - supports-color: 8.1.1 - jiti@2.7.0: {} jose@4.15.9: {} @@ -6615,8 +5488,6 @@ snapshots: json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: @@ -6705,8 +5576,6 @@ snapshots: pify: 3.0.0 strip-bom: 3.0.0 - loader-runner@4.3.2: {} - locate-path@2.0.0: dependencies: p-locate: 2.0.0 @@ -6764,19 +5633,13 @@ snapshots: mdn-data@2.27.1: {} - merge-stream@2.0.0: {} - merge2@1.4.1: {} - meriyah@6.1.4: {} - micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.2 - mime-db@1.54.0: {} - minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 @@ -6789,8 +5652,6 @@ snapshots: minipass@7.1.3: {} - module-details-from-path@1.0.4: {} - mrmime@2.0.1: {} ms@2.1.3: {} @@ -6801,15 +5662,13 @@ snapshots: natural-compare@1.4.0: {} - neo-async@2.6.2: {} - - next-auth@4.24.14(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next-auth@4.24.14(next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@babel/runtime': 7.29.7 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) oauth: 0.9.15 openid-client: 5.7.1 preact: 10.29.2 @@ -6818,7 +5677,7 @@ snapshots: react-dom: 19.2.4(react@19.2.4) uuid: 8.3.2 - next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next@16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@next/env': 16.2.7 '@swc/helpers': 0.5.15 @@ -6837,7 +5696,6 @@ snapshots: '@next/swc-linux-x64-musl': 16.2.7 '@next/swc-win32-arm64-msvc': 16.2.7 '@next/swc-win32-x64-msvc': 16.2.7 - '@opentelemetry/api': 1.9.1 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -6852,10 +5710,6 @@ snapshots: node-fetch-native@1.6.7: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - node-mock-http@1.0.4: {} node-releases@2.0.47: {} @@ -7050,16 +5904,12 @@ snapshots: process-warning@5.0.0: {} - progress@2.0.3: {} - prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 - proxy-from-env@1.1.0: {} - punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -7111,13 +5961,6 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@8.0.1: - dependencies: - debug: 4.4.3 - module-details-from-path: 1.0.4 - transitivePeerDependencies: - - supports-color - resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -7154,37 +5997,6 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.3 '@rolldown/binding-win32-x64-msvc': 1.0.3 - rollup@4.62.2: - dependencies: - '@types/estree': 1.0.9 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.62.2 - '@rollup/rollup-android-arm64': 4.62.2 - '@rollup/rollup-darwin-arm64': 4.62.2 - '@rollup/rollup-darwin-x64': 4.62.2 - '@rollup/rollup-freebsd-arm64': 4.62.2 - '@rollup/rollup-freebsd-x64': 4.62.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 - '@rollup/rollup-linux-arm-musleabihf': 4.62.2 - '@rollup/rollup-linux-arm64-gnu': 4.62.2 - '@rollup/rollup-linux-arm64-musl': 4.62.2 - '@rollup/rollup-linux-loong64-gnu': 4.62.2 - '@rollup/rollup-linux-loong64-musl': 4.62.2 - '@rollup/rollup-linux-ppc64-gnu': 4.62.2 - '@rollup/rollup-linux-ppc64-musl': 4.62.2 - '@rollup/rollup-linux-riscv64-gnu': 4.62.2 - '@rollup/rollup-linux-riscv64-musl': 4.62.2 - '@rollup/rollup-linux-s390x-gnu': 4.62.2 - '@rollup/rollup-linux-x64-gnu': 4.62.2 - '@rollup/rollup-linux-x64-musl': 4.62.2 - '@rollup/rollup-openbsd-x64': 4.62.2 - '@rollup/rollup-openharmony-arm64': 4.62.2 - '@rollup/rollup-win32-arm64-msvc': 4.62.2 - '@rollup/rollup-win32-ia32-msvc': 4.62.2 - '@rollup/rollup-win32-x64-gnu': 4.62.2 - '@rollup/rollup-win32-x64-msvc': 4.62.2 - fsevents: 2.3.3 - run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -7216,15 +6028,6 @@ snapshots: scheduler@0.27.0: {} - schema-utils@4.3.3: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.20.0 - ajv-formats: 2.1.1(ajv@8.20.0) - ajv-keywords: 5.1.0(ajv@8.20.0) - - semifies@1.0.0: {} - semver@6.3.1: {} semver@7.7.4: {} @@ -7352,8 +6155,10 @@ snapshots: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + optional: true - source-map@0.6.1: {} + source-map@0.6.1: + optional: true source-map@0.8.0-beta.0: dependencies: @@ -7365,10 +6170,6 @@ snapshots: stackback@0.0.2: {} - stacktrace-parser@0.1.11: - dependencies: - type-fest: 0.7.1 - std-env@4.1.0: {} stop-iteration-iterator@1.1.0: @@ -7455,10 +6256,6 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} symbol-tree@3.2.4: {} @@ -7469,22 +6266,13 @@ snapshots: tapable@2.3.3: {} - terser-webpack-plugin@5.6.1(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - terser: 5.48.0 - webpack: 5.107.2(esbuild@0.25.12) - optionalDependencies: - esbuild: 0.25.12 - terser@5.48.0: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 + optional: true thread-stream@4.2.0: dependencies: @@ -7517,8 +6305,6 @@ snapshots: dependencies: tldts: 7.4.2 - tr46@0.0.3: {} - tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -7544,8 +6330,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-fest@0.7.1: {} - type-fest@5.6.0: dependencies: tagged-tag: 1.0.0 @@ -7693,7 +6477,7 @@ snapshots: jiti: 2.7.0 terser: 5.48.0 - vitest@4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)): + vitest@4.1.8(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)): dependencies: '@vitest/expect': 4.1.8 '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)) @@ -7716,7 +6500,6 @@ snapshots: vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0) why-is-node-running: 2.3.0 optionalDependencies: - '@opentelemetry/api': 1.9.1 '@types/node': 20.19.41 '@vitest/coverage-v8': 4.1.8(vitest@4.1.8) '@vitest/ui': 4.1.8(vitest@4.1.8) @@ -7728,57 +6511,10 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - watchpack@2.5.2: - dependencies: - graceful-fs: 4.2.11 - - webidl-conversions@3.0.1: {} - webidl-conversions@4.0.2: {} webidl-conversions@8.0.1: {} - webpack-sources@3.5.0: {} - - webpack@5.107.2(esbuild@0.25.12): - dependencies: - '@types/estree': 1.0.9 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) - browserslist: 4.28.2 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.22.2 - es-module-lexer: 2.1.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - loader-runner: 4.3.2 - mime-db: 1.54.0 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.3 - terser-webpack-plugin: 5.6.1(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)) - watchpack: 2.5.2 - webpack-sources: 3.5.0 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - uglify-js - whatwg-mimetype@5.0.0: {} whatwg-url@16.0.1: @@ -7789,11 +6525,6 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0 diff --git a/sentry.edge.config.ts b/sentry.edge.config.ts deleted file mode 100644 index c3be7f5b..00000000 --- a/sentry.edge.config.ts +++ /dev/null @@ -1,24 +0,0 @@ -// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). -// The config you add here will be used whenever one of the edge features is loaded. -// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const dsn = process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN; - -if (dsn) { - Sentry.init({ - dsn, - - tracesSampleRate: Number( - process.env.SENTRY_TRACES_SAMPLE_RATE ?? - (process.env.NODE_ENV === "production" ? "0.1" : "1"), - ), - - enableLogs: true, - - // Chat content and auth data are sensitive; do not send default PII. - sendDefaultPii: false, - }); -} diff --git a/sentry.server.config.ts b/sentry.server.config.ts deleted file mode 100644 index 5b4afe22..00000000 --- a/sentry.server.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever the server handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const dsn = process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN; - -if (dsn) { - Sentry.init({ - dsn, - - tracesSampleRate: Number( - process.env.SENTRY_TRACES_SAMPLE_RATE ?? - (process.env.NODE_ENV === "production" ? "0.1" : "1"), - ), - - enableLogs: true, - - // Chat content and auth data are sensitive; do not send default PII. - sendDefaultPii: false, - }); -} diff --git a/src/instrumentation-client.ts b/src/instrumentation-client.ts deleted file mode 100644 index 648aa205..00000000 --- a/src/instrumentation-client.ts +++ /dev/null @@ -1,33 +0,0 @@ -// This file configures the initialization of Sentry on the client. -// The added config here will be used whenever a users loads a page in their browser. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; - -if (dsn) { - Sentry.init({ - dsn, - - integrations: [Sentry.replayIntegration()], - - tracesSampleRate: Number( - process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE ?? - (process.env.NODE_ENV === "production" ? "0.1" : "1"), - ), - enableLogs: true, - - replaysSessionSampleRate: Number( - process.env.NEXT_PUBLIC_SENTRY_REPLAY_SAMPLE_RATE ?? "0.05", - ), - replaysOnErrorSampleRate: Number( - process.env.NEXT_PUBLIC_SENTRY_REPLAY_ERROR_SAMPLE_RATE ?? "1", - ), - - // Chat content and auth data are sensitive; do not send default PII. - sendDefaultPii: false, - }); -} - -export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; diff --git a/src/instrumentation.ts b/src/instrumentation.ts deleted file mode 100644 index ecb65282..00000000 --- a/src/instrumentation.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as Sentry from "@sentry/nextjs"; - -export async function register() { - if (process.env.NEXT_RUNTIME === "nodejs") { - await import("../sentry.server.config"); - } - - if (process.env.NEXT_RUNTIME === "edge") { - await import("../sentry.edge.config"); - } -} - -export const onRequestError = Sentry.captureRequestError; From ebd44c49804d24132da9d8e4f32cdf553eef5d88 Mon Sep 17 00:00:00 2001 From: chenhang Date: Tue, 23 Jun 2026 13:21:57 +0800 Subject: [PATCH 5/5] feat(chat): add private message unlock flow --- env-example/.env.local.example | 4 +- src/app/chat/chat-screen.tsx | 40 ++++-- src/app/chat/components/chat-area.tsx | 29 +++- src/app/chat/components/index.ts | 1 + src/app/chat/components/message-bubble.tsx | 32 ++++- src/app/chat/components/message-content.tsx | 36 ++++- .../private-message-card.module.css | 57 ++++++++ .../chat/components/private-message-card.tsx | 38 ++++++ src/data/dto/chat/ui_message.ts | 4 + src/data/repositories/chat_repository.ts | 39 ++++++ .../interfaces/ichat_repository.ts | 6 + .../schemas/chat/unlock_private_response.ts | 8 +- src/data/storage/chat/local_chat_db.ts | 3 + src/data/storage/chat/local_message.ts | 12 ++ src/stores/chat/chat-context.tsx | 2 + src/stores/chat/chat-events.ts | 1 + src/stores/chat/chat-machine.actors.ts | 35 +++++ src/stores/chat/chat-machine.helpers.ts | 9 ++ src/stores/chat/chat-machine.ts | 124 ++++++++++++++++++ src/stores/chat/chat-state.ts | 4 +- 20 files changed, 455 insertions(+), 29 deletions(-) create mode 100644 src/app/chat/components/private-message-card.module.css create mode 100644 src/app/chat/components/private-message-card.tsx diff --git a/env-example/.env.local.example b/env-example/.env.local.example index 869256ad..9a7f6e48 100644 --- a/env-example/.env.local.example +++ b/env-example/.env.local.example @@ -3,8 +3,8 @@ NEXT_PUBLIC_APP_ENV=test # NextAuth v4 —— OAuth callback **公**网 base URL(**必**须与**公**网域名**一**致) NEXTAUTH_URL=https://frontend-test.banlv-ai.com NEXTAUTH_URL_INTERNAL=http://localhost:3000 -NEXT_PUBLIC_API_BASE_URL=https://api.cozsweet.com -NEXT_PUBLIC_WS_BASE_URL=wss://api.cozsweet.com/ws +NEXT_PUBLIC_API_BASE_URL=https://testapi.banlv-ai.com +NEXT_PUBLIC_WS_BASE_URL=wss://testapi.banlv-ai.com/ws NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51Te8ybEJDtUGxQHo0UMySJ2hW0vVryynzllmIUI3UQdQCFgxNLci0Jmm2lQkRsTaIP7C7IQlFzfFyBJ5rOhr1ML800G8P8DF5R NEXT_PUBLIC_API_CONNECT_TIMEOUT=30000 diff --git a/src/app/chat/chat-screen.tsx b/src/app/chat/chat-screen.tsx index a1064c40..703a31bd 100644 --- a/src/app/chat/chat-screen.tsx +++ b/src/app/chat/chat-screen.tsx @@ -8,7 +8,7 @@ import type { LoginStatus } from "@/data/dto/auth"; import { AppStorage } from "@/data/storage/app/app_storage"; import { AuthStorage } from "@/data/storage/auth/auth_storage"; import { UserStorage } from "@/data/storage/user/user_storage"; -import { useChatState } from "@/stores/chat/chat-context"; +import { useChatDispatch, useChatState } from "@/stores/chat/chat-context"; import { AppEnvUtil, BrowserDetector, todayString, UrlLauncherUtil } from "@/utils"; import { ROUTE_BUILDERS, ROUTES } from "@/router/routes"; @@ -35,6 +35,7 @@ function deriveIsGuest(loginStatus: LoginStatus): boolean { export function ChatScreen() { const state = useChatState(); + const chatDispatch = useChatDispatch(); const authState = useAuthState(); const [showExternalBrowserDialog, setShowExternalBrowserDialog] = useState(false); @@ -48,8 +49,16 @@ export function ChatScreen() { state.paywallReason === "daily_limit"; const showPhotoPaywallBanner = state.paywallTriggered && state.paywallReason === "photo_paywall"; - const showExhaustedBanner = - showDailyLimitBanner || showPhotoPaywallBanner; + const showPrivatePaywallBanner = + state.paywallTriggered && state.paywallReason === "private_paywall"; + const showInlineUpgradeBanner = + showPhotoPaywallBanner || showPrivatePaywallBanner; + const inlineUpgradeTitle = showPrivatePaywallBanner + ? "Unlock VIP to view private messages" + : "Unlock VIP to view Elio's photos"; + const inlineUpgradeCta = showPrivatePaywallBanner + ? "Activate VIP to view private messages" + : "Activate VIP to view photos"; const externalBrowserPromptShownRef = useRef(false); @@ -122,6 +131,10 @@ export function ChatScreen() { UrlLauncherUtil.openUrlWithExternalBrowser(ROUTES.splash); } + function handleUnlockPrivateMessage(messageId: string): void { + chatDispatch({ type: "ChatUnlockPrivateMessage", messageId }); + } + return (
@@ -144,20 +157,19 @@ export function ChatScreen() { messages={state.messages} isReplyingAI={state.isReplyingAI} isGuest={isGuest} + unlockingPrivateMessageId={state.unlockingPrivateMessageId} + onUnlockPrivateMessage={handleUnlockPrivateMessage} /> - {showExhaustedBanner ? ( + {showInlineUpgradeBanner ? ( + + ) : null} + + {showDailyLimitBanner ? ( ) : ( diff --git a/src/app/chat/components/chat-area.tsx b/src/app/chat/components/chat-area.tsx index 9d8a9f51..417a3671 100644 --- a/src/app/chat/components/chat-area.tsx +++ b/src/app/chat/components/chat-area.tsx @@ -28,9 +28,16 @@ export interface ChatAreaProps { messages: readonly UiMessage[]; isReplyingAI: boolean; isGuest: boolean; + unlockingPrivateMessageId?: string | null; + onUnlockPrivateMessage?: (messageId: string) => void; } -export function ChatArea({ messages, isReplyingAI }: ChatAreaProps) { +export function ChatArea({ + messages, + isReplyingAI, + unlockingPrivateMessageId, + onUnlockPrivateMessage, +}: ChatAreaProps) { const scrollRef = useRef(null); const prevLengthRef = useRef(messages.length); @@ -49,7 +56,11 @@ export function ChatArea({ messages, isReplyingAI }: ChatAreaProps) {
- {renderMessagesWithDateHeaders(messages)} + {renderMessagesWithDateHeaders( + messages, + unlockingPrivateMessageId, + onUnlockPrivateMessage, + )} {isReplyingAI && }
@@ -57,7 +68,11 @@ export function ChatArea({ messages, isReplyingAI }: ChatAreaProps) { } /** 渲染消息列表(按日期分组插入分隔条) */ -function renderMessagesWithDateHeaders(messages: readonly UiMessage[]) { +function renderMessagesWithDateHeaders( + messages: readonly UiMessage[], + unlockingPrivateMessageId?: string | null, + onUnlockPrivateMessage?: (messageId: string) => void, +) { const items: Array<{ type: "date"; date: string; key: string } | { type: "msg"; message: UiMessage; key: string }> = []; messages.forEach((m, i) => { @@ -73,9 +88,17 @@ function renderMessagesWithDateHeaders(messages: readonly UiMessage[]) { ) : ( ), ); diff --git a/src/app/chat/components/index.ts b/src/app/chat/components/index.ts index c522a0b5..56e09e75 100644 --- a/src/app/chat/components/index.ts +++ b/src/app/chat/components/index.ts @@ -22,5 +22,6 @@ export * from "./message-bubble"; export * from "./message-content"; export * from "./pwa-install-dialog"; export * from "./pwa-install-overlay"; +export * from "./private-message-card"; export * from "./text-bubble"; export * from "./user-message-avatar"; diff --git a/src/app/chat/components/message-bubble.tsx b/src/app/chat/components/message-bubble.tsx index 77297ce1..3c6c10e7 100644 --- a/src/app/chat/components/message-bubble.tsx +++ b/src/app/chat/components/message-bubble.tsx @@ -15,12 +15,26 @@ import { MessageContent } from "./message-content"; import styles from "./chat-area.module.css"; export interface MessageBubbleProps { + id?: string; content: string; imageUrl?: string | null; isFromAI: boolean; + privateLocked?: boolean | null; + privateHint?: string | null; + isUnlockingPrivate?: boolean; + onUnlockPrivateMessage?: (messageId: string) => void; } -export function MessageBubble({ content, imageUrl, isFromAI }: MessageBubbleProps) { +export function MessageBubble({ + id, + content, + imageUrl, + isFromAI, + privateLocked, + privateHint, + isUnlockingPrivate, + onUnlockPrivateMessage, +}: MessageBubbleProps) { const { avatarUrl } = useUserState(); if (isFromAI) { @@ -29,9 +43,14 @@ export function MessageBubble({ content, imageUrl, isFromAI }: MessageBubbleProp
{/* 占位:保持与头像宽度一致 */}
@@ -41,7 +60,16 @@ export function MessageBubble({ content, imageUrl, isFromAI }: MessageBubbleProp return (
{/* 占位 */} - +
diff --git a/src/app/chat/components/message-content.tsx b/src/app/chat/components/message-content.tsx index e55671b6..76064fb8 100644 --- a/src/app/chat/components/message-content.tsx +++ b/src/app/chat/components/message-content.tsx @@ -10,19 +10,35 @@ * - 两者都有:图片在上,文字在下 */ import { ImageBubble } from "./image-bubble"; +import { PrivateMessageCard } from "./private-message-card"; import { TextBubble } from "./text-bubble"; export interface MessageContentProps { + messageId?: string; content: string; imageUrl?: string | null; isFromAI: boolean; + privateLocked?: boolean | null; + privateHint?: string | null; + isUnlockingPrivate?: boolean; + onUnlockPrivateMessage?: (messageId: string) => void; } const IMAGE_PLACEHOLDER = "[图片]"; -export function MessageContent({ content, imageUrl, isFromAI }: MessageContentProps) { +export function MessageContent({ + messageId, + content, + imageUrl, + isFromAI, + privateLocked, + privateHint, + isUnlockingPrivate = false, + onUnlockPrivateMessage, +}: MessageContentProps) { const hasImage = imageUrl != null && imageUrl.length > 0; const hasText = content.length > 0 && content !== IMAGE_PLACEHOLDER; + const isLockedPrivateMessage = privateLocked === true; return (
- {hasImage && imageUrl && } - {hasText && } + {isLockedPrivateMessage ? ( + onUnlockPrivateMessage?.(messageId) + : undefined + } + /> + ) : ( + <> + {hasImage && imageUrl && } + {hasText && } + + )}
); } diff --git a/src/app/chat/components/private-message-card.module.css b/src/app/chat/components/private-message-card.module.css new file mode 100644 index 00000000..66821132 --- /dev/null +++ b/src/app/chat/components/private-message-card.module.css @@ -0,0 +1,57 @@ +.card { + max-width: min(280px, 100%); + padding: 14px; + border: 1px solid rgba(246, 87, 160, 0.2); + border-radius: 18px; + background: + linear-gradient(180deg, rgba(255, 244, 248, 0.95), rgba(255, 255, 255, 0.95)), + #ffffff; + box-shadow: 0 4px 12px rgba(246, 87, 160, 0.12); + color: #3c3b3b; +} + +.iconWrap { + width: 42px; + height: 42px; + border-radius: 50%; + background: linear-gradient(135deg, #ff8fc7 0%, #f657a0 100%); + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10px; +} + +.icon { + display: block; +} + +.hint { + margin: 0; + color: #3c3b3b; + font-size: 14px; + line-height: 1.4; +} + +.button { + width: 100%; + margin-top: 12px; + padding: 10px 12px; + border: 0; + border-radius: 999px; + background: linear-gradient(90deg, #ff67e0, #ff52a2); + color: #ffffff; + cursor: pointer; + font-size: 14px; + font-weight: 700; +} + +.button:disabled { + cursor: not-allowed; + opacity: 0.65; +} + +.button:focus-visible { + outline: 2px solid #f657a0; + outline-offset: 3px; +} diff --git a/src/app/chat/components/private-message-card.tsx b/src/app/chat/components/private-message-card.tsx new file mode 100644 index 00000000..7c7deda1 --- /dev/null +++ b/src/app/chat/components/private-message-card.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { LockKeyhole } from "lucide-react"; + +import styles from "./private-message-card.module.css"; + +export interface PrivateMessageCardProps { + hint?: string | null; + isUnlocking?: boolean; + onUnlock?: () => void; +} + +export function PrivateMessageCard({ + hint, + isUnlocking = false, + onUnlock, +}: PrivateMessageCardProps) { + return ( +
+ +

+ {hint && hint.length > 0 + ? hint + : "Elio has a private message for you."} +

+ +
+ ); +} diff --git a/src/data/dto/chat/ui_message.ts b/src/data/dto/chat/ui_message.ts index fa154322..a0eac429 100644 --- a/src/data/dto/chat/ui_message.ts +++ b/src/data/dto/chat/ui_message.ts @@ -8,6 +8,7 @@ import { z } from "zod"; export const UiMessageSchema = z.object({ + id: z.string().optional(), content: z.string(), isFromAI: z.boolean(), /** 日期分隔条使用的本地日期(YYYY-MM-DD) */ @@ -16,6 +17,9 @@ export const UiMessageSchema = z.object({ imageUrl: z.string().optional(), /** 语音 URL */ voiceUrl: z.string().optional(), + isPrivate: z.boolean().nullable().optional(), + privateLocked: z.boolean().nullable().optional(), + privateHint: z.string().nullable().optional(), }); export type UiMessage = z.infer; diff --git a/src/data/repositories/chat_repository.ts b/src/data/repositories/chat_repository.ts index 8b42c8be..76fe0f5e 100644 --- a/src/data/repositories/chat_repository.ts +++ b/src/data/repositories/chat_repository.ts @@ -68,6 +68,39 @@ export class ChatRepository implements IChatRepository { ); } + /** 把本地缓存中的私密消息标记为已解锁。 */ + async markPrivateMessageUnlockedInLocal( + messageId: string, + content: string, + ): Promise> { + return Result.wrap(async () => { + const localResult = await this.getLocalMessages(); + if (Result.isErr(localResult)) { + throw localResult.error; + } + + let changed = false; + const updatedMessages = localResult.data.map((message) => { + if (message.id !== messageId) return message; + changed = true; + return ChatMessage.from({ + ...message.toJson(), + content, + isPrivate: message.isPrivate ?? true, + privateLocked: false, + privateHint: null, + }); + }); + + if (!changed) return; + + const saveResult = await this.saveMessagesToLocal(updatedMessages); + if (Result.isErr(saveResult)) { + throw saveResult.error; + } + }); + } + // ============ 本地(Dexie)操作 ============ /** 把一条消息写入本地存储。 */ @@ -125,6 +158,9 @@ export class ChatRepository implements IChatRepository { content: message.content, createdAt: message.createdAt, imageUrl: message.imageUrl, + isPrivate: message.isPrivate, + privateLocked: message.privateLocked, + privateHint: message.privateHint, sessionId: "", }); } @@ -137,6 +173,9 @@ export class ChatRepository implements IChatRepository { content: local.content, createdAt: local.createdAt, imageUrl: local.imageUrl, + isPrivate: local.isPrivate, + privateLocked: local.privateLocked, + privateHint: local.privateHint, }); } diff --git a/src/data/repositories/interfaces/ichat_repository.ts b/src/data/repositories/interfaces/ichat_repository.ts index 92b5dd43..f19ba0ec 100644 --- a/src/data/repositories/interfaces/ichat_repository.ts +++ b/src/data/repositories/interfaces/ichat_repository.ts @@ -32,6 +32,12 @@ export interface IChatRepository { /** 解锁私密消息。 */ unlockPrivateMessage(messageId: string): Promise>; + /** 把本地缓存中的私密消息标记为已解锁。 */ + markPrivateMessageUnlockedInLocal( + messageId: string, + content: string, + ): Promise>; + /** 把一条消息写入本地存储。 */ saveMessageToLocal(message: ChatMessage): Promise>; diff --git a/src/data/schemas/chat/unlock_private_response.ts b/src/data/schemas/chat/unlock_private_response.ts index 378d7936..e9f8e63b 100644 --- a/src/data/schemas/chat/unlock_private_response.ts +++ b/src/data/schemas/chat/unlock_private_response.ts @@ -13,10 +13,10 @@ export const UnlockPrivateReasonSchema = z.enum([ export const UnlockPrivateResponseSchema = z.object({ unlocked: z.boolean(), content: z.string().nullable(), - showUpgrade: z.boolean(), - paywallTriggered: z.boolean(), - privateFreeLimit: z.number(), - privateUsedToday: z.number(), + showUpgrade: z.boolean().default(false), + paywallTriggered: z.boolean().default(false), + privateFreeLimit: z.number().default(0), + privateUsedToday: z.number().default(0), reason: UnlockPrivateReasonSchema, }); diff --git a/src/data/storage/chat/local_chat_db.ts b/src/data/storage/chat/local_chat_db.ts index 3b78ced5..f4a245af 100644 --- a/src/data/storage/chat/local_chat_db.ts +++ b/src/data/storage/chat/local_chat_db.ts @@ -22,6 +22,9 @@ export interface LocalMessageRow { content: string; createdAt: string; imageUrl?: string | null; + isPrivate?: boolean | null; + privateLocked?: boolean | null; + privateHint?: string | null; sessionId: string; } diff --git a/src/data/storage/chat/local_message.ts b/src/data/storage/chat/local_message.ts index d5b0dc04..de18ea4a 100644 --- a/src/data/storage/chat/local_message.ts +++ b/src/data/storage/chat/local_message.ts @@ -23,6 +23,9 @@ export const LocalMessageSchema = z.object({ content: z.string(), createdAt: z.string().default(""), imageUrl: z.string().nullable().default(null), + isPrivate: z.boolean().nullable().default(null), + privateLocked: z.boolean().nullable().default(null), + privateHint: z.string().nullable().default(null), sessionId: z.string().default(""), }); @@ -35,6 +38,9 @@ export class LocalMessage { declare readonly content: string; declare readonly createdAt: string; declare readonly imageUrl: string | null; + declare readonly isPrivate: boolean | null; + declare readonly privateLocked: boolean | null; + declare readonly privateHint: string | null; declare readonly sessionId: string; private constructor(input: LocalMessageInput) { @@ -63,6 +69,9 @@ export class LocalMessage { content: this.content, createdAt: this.createdAt, imageUrl: this.imageUrl, + isPrivate: this.isPrivate, + privateLocked: this.privateLocked, + privateHint: this.privateHint, sessionId: this.sessionId, }; } @@ -75,6 +84,9 @@ export class LocalMessage { content: row.content, createdAt: row.createdAt, imageUrl: row.imageUrl ?? null, + isPrivate: row.isPrivate ?? null, + privateLocked: row.privateLocked ?? null, + privateHint: row.privateHint ?? null, sessionId: row.sessionId, }); } diff --git a/src/stores/chat/chat-context.tsx b/src/stores/chat/chat-context.tsx index 0d8aa4e8..a7c4ac75 100644 --- a/src/stores/chat/chat-context.tsx +++ b/src/stores/chat/chat-context.tsx @@ -24,6 +24,7 @@ interface ChatState { paywallTriggered: boolean; paywallReason: MachineContext["paywallReason"]; paywallDetail: MachineContext["paywallDetail"]; + unlockingPrivateMessageId: MachineContext["unlockingPrivateMessageId"]; isLoadingMore: boolean; hasMore: boolean; historyOffset: number; @@ -49,6 +50,7 @@ export function ChatProvider({ children }: ChatProviderProps) { paywallTriggered: state.context.paywallTriggered, paywallReason: state.context.paywallReason, paywallDetail: state.context.paywallDetail, + unlockingPrivateMessageId: state.context.unlockingPrivateMessageId, isLoadingMore: state.context.isLoadingMore, hasMore: state.context.hasMore, historyOffset: state.context.historyOffset, diff --git a/src/stores/chat/chat-events.ts b/src/stores/chat/chat-events.ts index 6977abd3..ec877663 100644 --- a/src/stores/chat/chat-events.ts +++ b/src/stores/chat/chat-events.ts @@ -25,6 +25,7 @@ export type ChatEvent = // 业务事件 | { type: "ChatSendMessage"; content: string } | { type: "ChatSendImage"; imageBase64: string } + | { type: "ChatUnlockPrivateMessage"; messageId: string } | { type: "ChatLoadMoreHistory" } | { type: "ChatImageReceived"; imageUrl: string } | { diff --git a/src/stores/chat/chat-machine.actors.ts b/src/stores/chat/chat-machine.actors.ts index 4676a14c..2d9a20d8 100644 --- a/src/stores/chat/chat-machine.actors.ts +++ b/src/stores/chat/chat-machine.actors.ts @@ -105,6 +105,41 @@ export const loadMoreHistoryActor = fromPromise< }; }); +export const unlockPrivateMessageActor = fromPromise< + { + messageId: string; + response: import("@/data/dto/chat").UnlockPrivateResponse; + }, + { messageId: string } +>(async ({ input }) => { + const result = await chatRepo.unlockPrivateMessage(input.messageId); + if (Result.isErr(result)) { + log.error("[chat-machine] unlockPrivateMessageActor failed", { + messageId: input.messageId, + error: result.error, + }); + throw result.error; + } + + if (result.data.unlocked && result.data.content != null) { + const localResult = await chatRepo.markPrivateMessageUnlockedInLocal( + input.messageId, + result.data.content, + ); + if (Result.isErr(localResult)) { + log.error("[chat-machine] unlockPrivateMessageActor local sync failed", { + messageId: input.messageId, + error: localResult.error, + }); + } + } + + return { + messageId: input.messageId, + response: result.data, + }; +}); + // ============================================================ // WebSocket: long-lived callback // ============================================================ diff --git a/src/stores/chat/chat-machine.helpers.ts b/src/stores/chat/chat-machine.helpers.ts index 1a73dfca..1f31b054 100644 --- a/src/stores/chat/chat-machine.helpers.ts +++ b/src/stores/chat/chat-machine.helpers.ts @@ -49,17 +49,25 @@ export const chatRepo: IChatRepository = chatRepository; */ export function localMessagesToUi( records: ReadonlyArray<{ + id?: string; content: string; role: string; createdAt: string; imageUrl?: string | null; + isPrivate?: boolean | null; + privateLocked?: boolean | null; + privateHint?: string | null; }>, ): UiMessage[] { return records.map((m) => ({ + ...(m.id ? { id: m.id } : {}), content: m.content, isFromAI: m.role === "assistant", date: messageDateFromCreatedAt(m.createdAt), ...(m.imageUrl ? { imageUrl: m.imageUrl } : {}), + ...(m.isPrivate != null ? { isPrivate: m.isPrivate } : {}), + ...(m.privateLocked != null ? { privateLocked: m.privateLocked } : {}), + ...(m.privateHint != null ? { privateHint: m.privateHint } : {}), })); } @@ -76,6 +84,7 @@ function messageDateFromCreatedAt(createdAt: string): string { */ export function sendResponseToUiMessage(response: ChatSendResponse): UiMessage { return { + ...(response.messageId ? { id: response.messageId } : {}), content: response.reply, isFromAI: true, date: todayString(new Date(response.timestamp)), diff --git a/src/stores/chat/chat-machine.ts b/src/stores/chat/chat-machine.ts index a95f9964..bbdc67c2 100644 --- a/src/stores/chat/chat-machine.ts +++ b/src/stores/chat/chat-machine.ts @@ -47,6 +47,7 @@ import { sendMessageWsActor, loadMoreHistoryActor, chatWebSocketActor, + unlockPrivateMessageActor, } from "./chat-machine.actors"; const log = new Logger("StoresChatChatMachine"); @@ -70,6 +71,7 @@ export const chatMachine = setup({ sendMessageWs: sendMessageWsActor, loadMoreHistory: loadMoreHistoryActor, chatWebSocket: chatWebSocketActor, + unlockPrivateMessage: unlockPrivateMessageActor, }, actions: { startGuestSession: assign(() => ({ @@ -276,6 +278,65 @@ export const chatMachine = setup({ }; }), + setUnlockingPrivateMessage: assign(({ event }) => { + if (event.type !== "ChatUnlockPrivateMessage") return {}; + return { + unlockingPrivateMessageId: event.messageId, + paywallTriggered: false, + paywallReason: null, + paywallDetail: null, + }; + }), + + applyUnlockPrivateOutput: assign(({ context, event }) => { + if (!("output" in event)) return {}; + const output = event.output as { + messageId: string; + response: import("@/data/dto/chat").UnlockPrivateResponse; + }; + const { messageId, response } = output; + + if (response.unlocked && response.content != null) { + return { + messages: context.messages.map((message) => + message.id === messageId + ? { + ...message, + content: response.content ?? message.content, + privateLocked: false, + privateHint: null, + isPrivate: message.isPrivate ?? true, + } + : message, + ), + unlockingPrivateMessageId: null, + paywallTriggered: false, + paywallReason: null, + paywallDetail: null, + }; + } + + if (response.showUpgrade) { + return { + unlockingPrivateMessageId: null, + paywallTriggered: true, + paywallReason: "private_paywall", + paywallDetail: { + usedToday: response.privateUsedToday, + limit: response.privateFreeLimit, + }, + }; + } + + return { + unlockingPrivateMessageId: null, + }; + }), + + clearUnlockingPrivateMessage: assign({ + unlockingPrivateMessageId: null, + }), + setWsConnected: assign({ wsConnected: true }), clearWsConnected: assign({ wsConnected: false }), }, @@ -356,6 +417,10 @@ export const chatMachine = setup({ actions: "appendGuestUserImage", target: "sending", }, + ChatUnlockPrivateMessage: { + actions: "setUnlockingPrivateMessage", + target: "unlockingPrivate", + }, // 删除 ChatLoadMoreHistory / WS handlers —— 游客无服务端 history,也不连接 WS }, }, @@ -377,6 +442,23 @@ export const chatMachine = setup({ }, }, }, + unlockingPrivate: { + invoke: { + src: "unlockPrivateMessage", + input: ({ event }) => ({ + messageId: + event.type === "ChatUnlockPrivateMessage" ? event.messageId : "", + }), + onDone: { + target: "ready", + actions: "applyUnlockPrivateOutput", + }, + onError: { + target: "ready", + actions: "clearUnlockingPrivateMessage", + }, + }, + }, }, }, @@ -437,6 +519,10 @@ export const chatMachine = setup({ ChatLoadMoreHistory: { target: "loadingMore", }, + ChatUnlockPrivateMessage: { + actions: "setUnlockingPrivateMessage", + target: "unlockingPrivate", + }, }, }, sendingViaHttp: { @@ -476,6 +562,23 @@ export const chatMachine = setup({ }, }, }, + unlockingPrivate: { + invoke: { + src: "unlockPrivateMessage", + input: ({ event }) => ({ + messageId: + event.type === "ChatUnlockPrivateMessage" ? event.messageId : "", + }), + onDone: { + target: "ready", + actions: "applyUnlockPrivateOutput", + }, + onError: { + target: "ready", + actions: "clearUnlockingPrivateMessage", + }, + }, + }, }, }, @@ -577,6 +680,10 @@ export const chatMachine = setup({ ChatLoadMoreHistory: { target: "loadingMore", }, + ChatUnlockPrivateMessage: { + actions: "setUnlockingPrivateMessage", + target: "unlockingPrivate", + }, // 注:ChatAISentenceReceived / ChatWebSocketError / ChatWebSocketConnected // 已上提到 vipUserSession.on,子级不再声明 }, @@ -651,6 +758,23 @@ export const chatMachine = setup({ }, }, }, + unlockingPrivate: { + invoke: { + src: "unlockPrivateMessage", + input: ({ event }) => ({ + messageId: + event.type === "ChatUnlockPrivateMessage" ? event.messageId : "", + }), + onDone: { + target: "ready", + actions: "applyUnlockPrivateOutput", + }, + onError: { + target: "ready", + actions: "clearUnlockingPrivateMessage", + }, + }, + }, }, }, }, diff --git a/src/stores/chat/chat-state.ts b/src/stores/chat/chat-state.ts index b579ac8f..12e2df89 100644 --- a/src/stores/chat/chat-state.ts +++ b/src/stores/chat/chat-state.ts @@ -19,8 +19,9 @@ export interface ChatState { */ wsConnected: boolean; paywallTriggered: boolean; - paywallReason: "daily_limit" | "photo_paywall" | null; + paywallReason: "daily_limit" | "photo_paywall" | "private_paywall" | null; paywallDetail: { usedToday: number; limit: number } | null; + unlockingPrivateMessageId: string | null; isLoadingMore: boolean; hasMore: boolean; historyOffset: number; @@ -38,6 +39,7 @@ export const initialState: ChatState = { paywallTriggered: false, paywallReason: null, paywallDetail: null, + unlockingPrivateMessageId: null, isLoadingMore: false, hasMore: true, historyOffset: 0,