diff --git a/packages/web/src/app/api/board/[id]/comments/route.ts b/packages/web/src/app/api/board/[id]/comments/route.ts
index 94227c5..aa2e323 100644
--- a/packages/web/src/app/api/board/[id]/comments/route.ts
+++ b/packages/web/src/app/api/board/[id]/comments/route.ts
@@ -6,6 +6,7 @@ import { getBoardAuth } from '@/lib/board-auth';
import { errorResponse, Errors, successResponse } from '@/lib/api-error';
import { grantWebScore } from '@/lib/score';
import { sanitizeDescription } from '@/lib/sanitize';
+import { sendPushToMember } from '@/lib/push';
const { boardPosts, boardComments, ActivityScoreType } = sharedDb;
@@ -35,8 +36,9 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
}
// Validate parentId + secret comment reply restrictions
+ let parent: { id: string; memberId: string; isSecret: boolean } | null = null;
if (parentId) {
- const [parent] = await database
+ const [parentData] = await database
.select({
id: boardComments.id,
memberId: boardComments.memberId,
@@ -46,10 +48,11 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
.where(and(eq(boardComments.id, parentId), eq(boardComments.postId, postId)))
.limit(1);
- if (!parent) return Errors.badRequest('상위 댓글을 찾을 수 없습니다.').toResponse();
+ if (!parentData) return Errors.badRequest('상위 댓글을 찾을 수 없습니다.').toResponse();
+ parent = parentData as { id: string; memberId: string; isSecret: boolean };
// 비밀댓글 답글: 댓글 작성자/글 작성자/관리자만 가능
- if (parent.isSecret) {
+ if (parent && parent.isSecret) {
const isCommentOwner = parent.memberId === auth.memberId;
const isPostAuthor = post.memberId === auth.memberId;
if (!isCommentOwner && !isPostAuthor && !auth.isAdmin) {
@@ -73,6 +76,10 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
})
.returning();
+ if (!newComment) {
+ return Errors.externalServiceError('댓글 생성에 실패했습니다.').toResponse();
+ }
+
// Increment comment_count
await database
.update(boardPosts)
@@ -88,6 +95,34 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
).catch((err) => console.error('[score] grantWebScore failed:', err));
}
+ // 1. 내가 쓴 글에 댓글이 달리면 무조건 알림 (본인 제외)
+ if (post.memberId !== auth.memberId) {
+ const postIdentifier = postId;
+ sendPushToMember(post.memberId, {
+ title: '새 댓글이 달렸습니다',
+ body: `${content.trim().slice(0, 50)}${content.length > 50 ? '...' : ''}`,
+ clickUrl: `/board/${postIdentifier}`,
+ data: { type: 'board_comment', postId: postIdentifier, commentId: newComment.id },
+ }).catch((err) => console.error('[push] Comment notification failed:', err));
+ }
+
+ // 2. 대댓글의 경우 원댓글 작성자에게도 알림
+ if (parentId && parent) {
+ const pmid = parent.memberId;
+ const amid = auth.memberId;
+
+ // 내 댓글에 답글이 달리면 알림 (작성자 본인 제외)
+ if (pmid !== amid) {
+ const postIdentifier = postId;
+ sendPushToMember(pmid, {
+ title: '💬 답글이 달렸습니다',
+ body: `${content.trim().slice(0, 50)}${content.length > 50 ? '...' : ''}`,
+ clickUrl: `/board/${postIdentifier}`,
+ data: { type: 'board_reply', postId: postIdentifier, commentId: newComment.id },
+ }).catch((err) => console.error('[push] Reply notification failed:', err));
+ }
+ }
+
return successResponse(newComment, '댓글이 작성되었습니다.', 201);
} catch (error) {
return errorResponse(error);
diff --git a/packages/web/src/app/api/board/route.ts b/packages/web/src/app/api/board/route.ts
index a00e4d3..11fb158 100644
--- a/packages/web/src/app/api/board/route.ts
+++ b/packages/web/src/app/api/board/route.ts
@@ -14,8 +14,9 @@ import { getAdminDiscordIds } from '@/lib/admin';
import { isValidCategory } from '@/lib/board-config';
import { sanitizeDescription, sanitizeTiptapContent } from '@/lib/sanitize';
import { grantWebScore } from '@/lib/score';
+import { sendPushToMembers } from '@/lib/push';
-const { boardPosts, members, boardPolls, boardPollOptions, ActivityScoreType } = sharedDb;
+const { boardPosts, members, boardPolls, boardPollOptions, ActivityScoreType, MemberStatus } = sharedDb;
export async function GET(request: NextRequest) {
try {
@@ -257,6 +258,24 @@ export async function POST(request: NextRequest) {
sanitizeDescription(title.trim().slice(0, 50))
).catch((err) => console.error('[score] grantWebScore failed:', err));
+ // 공지사항인 경우 활성 멤버 전체에게 알림
+ if (category === 'notice') {
+ const activeMembers = await database
+ .select({ id: members.id })
+ .from(members)
+ .where(eq(members.status, MemberStatus.ACTIVE));
+
+ sendPushToMembers(
+ activeMembers.map((m) => m.id),
+ {
+ title: '📢 새 공지사항',
+ body: title.trim(),
+ clickUrl: `/board/${result.id}`,
+ data: { type: 'board_notice', postId: result.id },
+ }
+ ).catch((err) => console.error('[push] Notice notification failed:', err));
+ }
+
return successResponse(result, '게시글이 작성되었습니다.', 201);
} catch (error) {
return errorResponse(error);
diff --git a/packages/web/src/app/api/notification-preferences/route.ts b/packages/web/src/app/api/notification-preferences/route.ts
new file mode 100644
index 0000000..350f2e8
--- /dev/null
+++ b/packages/web/src/app/api/notification-preferences/route.ts
@@ -0,0 +1,78 @@
+import { NextRequest } from 'next/server';
+import { eq } from 'drizzle-orm';
+import { getDb } from '@/lib/db';
+import { db as sharedDb } from '@blog-study/shared';
+import { getBoardAuth } from '@/lib/board-auth';
+import { errorResponse, Errors, successResponse } from '@/lib/api-error';
+
+const { notificationPreferences, NotificationType } = sharedDb;
+
+/**
+ * GET /api/notification-preferences
+ * 알림 설정 조회
+ */
+export async function GET(_request: NextRequest) {
+ try {
+ const auth = await getBoardAuth();
+ if (!auth) return Errors.unauthorized().toResponse();
+
+ const database = getDb();
+
+ // 모든 알림 타입에 대한 설정 조회 (없으면 기본값 true로 생성)
+ const allTypes = Object.values(NotificationType);
+ const existing = await database
+ .select()
+ .from(notificationPreferences)
+ .where(eq(notificationPreferences.memberId, auth.memberId));
+
+ const existingMap = new Map(existing.map((e) => [e.type, e.enabled]));
+ const preferences = allTypes.map((type) => ({
+ type,
+ enabled: existingMap.get(type) ?? true,
+ }));
+
+ return successResponse(preferences);
+ } catch (error) {
+ return errorResponse(error);
+ }
+}
+
+/**
+ * PUT /api/notification-preferences
+ * 알림 설정 업데이트
+ */
+export async function PUT(request: NextRequest) {
+ try {
+ const auth = await getBoardAuth();
+ if (!auth) return Errors.unauthorized().toResponse();
+
+ const body = await request.json();
+ const { type, enabled } = body;
+
+ if (!type || typeof enabled !== 'boolean') {
+ return Errors.badRequest('type과 enabled 값을 모두 제공해주세요.').toResponse();
+ }
+
+ if (!Object.values(NotificationType).includes(type)) {
+ return Errors.badRequest('잘못된 알림 타입입니다.').toResponse();
+ }
+
+ const database = getDb();
+
+ await database
+ .insert(notificationPreferences)
+ .values({
+ memberId: auth.memberId,
+ type,
+ enabled,
+ })
+ .onConflictDoUpdate({
+ target: [notificationPreferences.memberId, notificationPreferences.type],
+ set: { enabled, updatedAt: new Date() },
+ });
+
+ return successResponse({ type, enabled }, '알림 설정이 저장되었습니다.');
+ } catch (error) {
+ return errorResponse(error);
+ }
+}
diff --git a/packages/web/src/app/api/posts/[id]/comments/route.ts b/packages/web/src/app/api/posts/[id]/comments/route.ts
index fa5d1d4..b29e3ff 100644
--- a/packages/web/src/app/api/posts/[id]/comments/route.ts
+++ b/packages/web/src/app/api/posts/[id]/comments/route.ts
@@ -7,6 +7,7 @@ import { getAdminDiscordIds } from '@/lib/admin';
import { errorResponse, Errors, successResponse } from '@/lib/api-error';
import { grantWebScore } from '@/lib/score';
import { sanitizeDescription } from '@/lib/sanitize';
+import { sendPushToMember } from '@/lib/push';
const { posts, postComments, members, ActivityScoreType } = sharedDb;
@@ -108,9 +109,10 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
}
// parentId 유효성 검증
+ let parent: { id: string; memberId: string } | null = null;
if (parentId) {
- const [parent] = await database
- .select({ id: postComments.id })
+ const [parentData] = await database
+ .select({ id: postComments.id, memberId: postComments.memberId })
.from(postComments)
.where(
and(
@@ -120,7 +122,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
)
)
.limit(1);
- if (!parent) return Errors.badRequest('상위 댓글을 찾을 수 없습니다.').toResponse();
+ if (!parentData) return Errors.badRequest('상위 댓글을 찾을 수 없습니다.').toResponse();
+ parent = parentData;
}
const [newComment] = await database
@@ -163,6 +166,32 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
}
}
+ // 1. 내가 쓴 포스트에 댓글이 달리면 무조건 알림 (본인 제외)
+ if (post.memberId !== auth.memberId) {
+ sendPushToMember(post.memberId, {
+ title: '새 댓글이 달렸습니다',
+ body: `${content.trim().slice(0, 50)}${content.length > 50 ? '...' : ''}`,
+ clickUrl: `/posts/${postId}`,
+ data: { type: 'post_comment', postId, commentId: newComment?.id ?? '' },
+ }).catch((err) => console.error('[push] Post comment notification failed:', err));
+ }
+
+ // 2. 대댓글의 경우 원댓글 작성자에게도 알림
+ if (parentId && parent) {
+ const pmid = parent.memberId;
+ const amid = auth.memberId;
+
+ // 내 댓글에 답글이 달리면 알림 (작성자 본인 제외)
+ if (pmid !== amid) {
+ sendPushToMember(pmid, {
+ title: '💬 답글이 달렸습니다',
+ body: `${content.trim().slice(0, 50)}${content.length > 50 ? '...' : ''}`,
+ clickUrl: `/posts/${postId}`,
+ data: { type: 'post_reply', postId, commentId: newComment?.id ?? '' },
+ }).catch((err) => console.error('[push] Post reply notification failed:', err));
+ }
+ }
+
return successResponse(newComment, '댓글이 작성되었습니다.', 201);
} catch (error) {
return errorResponse(error);
diff --git a/packages/web/src/app/api/push/subscribe/route.ts b/packages/web/src/app/api/push/subscribe/route.ts
new file mode 100644
index 0000000..dc1e86f
--- /dev/null
+++ b/packages/web/src/app/api/push/subscribe/route.ts
@@ -0,0 +1,51 @@
+import { NextRequest } from 'next/server';
+import { getDb } from '@/lib/db';
+import { db as sharedDb } from '@blog-study/shared';
+import { getBoardAuth } from '@/lib/board-auth';
+import { errorResponse, Errors, successResponse } from '@/lib/api-error';
+
+const { fcmTokens } = sharedDb;
+
+const MAX_TOKEN_LENGTH = 500;
+const MAX_DEVICE_INFO_LENGTH = 200;
+
+export async function POST(request: NextRequest) {
+ try {
+ const auth = await getBoardAuth();
+ if (!auth) return Errors.unauthorized().toResponse();
+
+ const { token, deviceInfo } = await request.json();
+
+ if (!token || typeof token !== 'string') {
+ return Errors.badRequest('FCM 토큰이 필요합니다.').toResponse();
+ }
+
+ if (token.length > MAX_TOKEN_LENGTH) {
+ return Errors.badRequest('FCM 토큰이 너무 깁니다.').toResponse();
+ }
+
+ const sanitizedDeviceInfo =
+ typeof deviceInfo === 'string' ? deviceInfo.slice(0, MAX_DEVICE_INFO_LENGTH) : null;
+
+ const database = getDb();
+
+ await database
+ .insert(fcmTokens)
+ .values({
+ memberId: auth.memberId,
+ token,
+ deviceInfo: sanitizedDeviceInfo,
+ })
+ .onConflictDoUpdate({
+ target: [fcmTokens.memberId, fcmTokens.token],
+ set: {
+ lastUsedAt: new Date(),
+ deviceInfo: sanitizedDeviceInfo,
+ },
+ });
+
+ return successResponse({ subscribed: true }, '알림이 구독되었습니다.');
+ } catch (error) {
+ return errorResponse(error);
+ }
+}
diff --git a/packages/web/src/app/api/push/test/route.ts b/packages/web/src/app/api/push/test/route.ts
new file mode 100644
index 0000000..534624f
--- /dev/null
+++ b/packages/web/src/app/api/push/test/route.ts
@@ -0,0 +1,71 @@
+import { NextRequest } from 'next/server';
+import { getBoardAuth } from '@/lib/board-auth';
+import { sendPushToMember } from '@/lib/push';
+import { errorResponse, Errors, successResponse } from '@/lib/api-error';
+
+const TEST_MESSAGES: Record
= {
+ board_comment: {
+ title: '💬 게시판 댓글 테스트',
+ body: '누군가 내 게시글에 댓글을 남겼습니다.',
+ },
+ board_reply: {
+ title: '↩️ 게시판 답글 테스트',
+ body: '누군가 내 댓글에 답글을 남겼습니다.',
+ },
+ post_comment: {
+ title: '📝 포스트 댓글 테스트',
+ body: '누군가 내 포스트에 댓글을 남겼습니다.',
+ },
+ post_reply: {
+ title: '↩️ 포스트 답글 테스트',
+ body: '누군가 내 포스트 댓글에 답글을 남겼습니다.',
+ },
+ board_notice: {
+ title: '📢 공지사항 테스트',
+ body: '새로운 공지사항이 게시되었습니다.',
+ },
+};
+
+// 유저별 레이트 리밋 (분당 5회)
+const rateLimitMap = new Map();
+const RATE_LIMIT_WINDOW = 60_000;
+const RATE_LIMIT_MAX = 5;
+
+function checkRateLimit(memberId: string): boolean {
+ const now = Date.now();
+ const timestamps = rateLimitMap.get(memberId) ?? [];
+ const recent = timestamps.filter((t) => now - t < RATE_LIMIT_WINDOW);
+ if (recent.length >= RATE_LIMIT_MAX) return false;
+ recent.push(now);
+ rateLimitMap.set(memberId, recent);
+ return true;
+}
+
+export async function POST(request: NextRequest) {
+ try {
+ const auth = await getBoardAuth();
+ if (!auth) return Errors.unauthorized().toResponse();
+
+ if (!checkRateLimit(auth.memberId)) {
+ return Errors.badRequest('테스트 알림은 1분에 5회까지 가능합니다.').toResponse();
+ }
+
+ const { type } = await request.json();
+
+ const message = TEST_MESSAGES[type];
+ if (!message) {
+ return Errors.badRequest('잘못된 알림 타입입니다.').toResponse();
+ }
+
+ const result = await sendPushToMember(auth.memberId, {
+ title: message.title,
+ body: message.body,
+ clickUrl: '/profile/notifications',
+ data: { type },
+ });
+
+ return successResponse(result, '테스트 알림이 전송되었습니다.');
+ } catch (error) {
+ return errorResponse(error);
+ }
+}
diff --git a/packages/web/src/app/api/push/unsubscribe/route.ts b/packages/web/src/app/api/push/unsubscribe/route.ts
new file mode 100644
index 0000000..1f4cae7
--- /dev/null
+++ b/packages/web/src/app/api/push/unsubscribe/route.ts
@@ -0,0 +1,36 @@
+import { NextRequest } from 'next/server';
+import { eq, and } from 'drizzle-orm';
+import { getDb } from '@/lib/db';
+import { db as sharedDb } from '@blog-study/shared';
+import { getBoardAuth } from '@/lib/board-auth';
+import { errorResponse, Errors, successResponse } from '@/lib/api-error';
+
+const { fcmTokens } = sharedDb;
+
+export async function POST(request: NextRequest) {
+ try {
+ const auth = await getBoardAuth();
+ if (!auth) return Errors.unauthorized().toResponse();
+
+ const { token } = await request.json();
+
+ if (!token) {
+ return Errors.badRequest('FCM 토큰이 필요합니다.').toResponse();
+ }
+
+ const database = getDb();
+
+ await database
+ .delete(fcmTokens)
+ .where(
+ and(
+ eq(fcmTokens.token, token),
+ eq(fcmTokens.memberId, auth.memberId)
+ )
+ );
+
+ return successResponse({ unsubscribed: true }, '구독이 취소되었습니다.');
+ } catch (error) {
+ return errorResponse(error);
+ }
+}
diff --git a/packages/web/src/components/settings/push-notification-settings.tsx b/packages/web/src/components/settings/push-notification-settings.tsx
new file mode 100644
index 0000000..735f398
--- /dev/null
+++ b/packages/web/src/components/settings/push-notification-settings.tsx
@@ -0,0 +1,216 @@
+'use client';
+
+import { useEffect, useState } from 'react';
+import { Bell, Megaphone, MessageCircle, MessageSquare, SendHorizonal } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { Switch } from '@/components/ui/switch';
+import { toast } from 'sonner';
+import { usePushNotification } from '@/hooks/use-push-notification';
+
+interface NotificationPreference {
+ type: string;
+ enabled: boolean;
+}
+
+type IconComponent = React.ComponentType<{ className?: string }>;
+
+const NOTIFICATION_LABELS: Record<
+ string,
+ { label: string; icon: IconComponent; description: string }
+> = {
+ board_comment: {
+ label: '게시판 댓글',
+ icon: MessageSquare,
+ description: '내 게시글에 댓글이 달릴 때',
+ },
+ board_reply: {
+ label: '게시판 답글',
+ icon: MessageCircle,
+ description: '내 댓글에 답글이 달릴 때',
+ },
+ post_comment: {
+ label: '포스트 댓글',
+ icon: MessageSquare,
+ description: '내 포스트에 댓글이 달릴 때',
+ },
+ post_reply: {
+ label: '포스트 답글',
+ icon: MessageCircle,
+ description: '내 댓글에 답글이 달릴 때',
+ },
+ board_notice: { label: '공지사항', icon: Megaphone, description: '새 공지사항이 게시될 때' },
+};
+
+export function PushNotificationSettings() {
+ const { permission, token, requestPermission, unsubscribe, isSupported } = usePushNotification();
+ const [preferences, setPreferences] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [sendingTest, setSendingTest] = useState(null);
+
+ const handleTestPush = async (type: string) => {
+ setSendingTest(type);
+ try {
+ const res = await fetch('/api/push/test', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ type }),
+ });
+ const data = await res.json();
+ if (!data.success) {
+ throw new Error(data.message || '테스트 알림 전송에 실패했습니다.');
+ }
+ if (data.data?.success > 0) {
+ toast.success('테스트 알림이 전송되었습니다.');
+ } else {
+ toast.error('알림 전송에 실패했습니다. Firebase 설정을 확인해주세요.');
+ }
+ } catch {
+ toast.error('테스트 알림 전송에 실패했습니다.');
+ } finally {
+ setSendingTest(null);
+ }
+ };
+
+ // 알림 설정 불러오기
+ useEffect(() => {
+ if (permission !== 'granted' || !token) {
+ setLoading(false);
+ return;
+ }
+
+ fetch('/api/notification-preferences')
+ .then((res) => res.json())
+ .then((data) => {
+ if (data.success) {
+ setPreferences(data.data);
+ }
+ })
+ .catch(() => {
+ toast.error('알림 설정을 불러오는데 실패했습니다.');
+ })
+ .finally(() => {
+ setLoading(false);
+ });
+ }, [permission, token]);
+
+ // 알림 토글
+ const handleToggle = async (type: string, enabled: boolean) => {
+ const snapshot = preferences;
+ setPreferences((current) => current.map((p) => (p.type === type ? { ...p, enabled } : p)));
+
+ try {
+ const res = await fetch('/api/notification-preferences', {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ type, enabled }),
+ });
+
+ const data = await res.json();
+ if (!data.success) {
+ throw new Error(data.message || '설정 저장에 실패했습니다.');
+ }
+
+ toast.success(enabled ? '알림이 켜졌습니다.' : '알림이 꺼졌습니다.');
+ } catch {
+ setPreferences(snapshot);
+ toast.error('설정 저장에 실패했습니다. 다시 시도해주세요.');
+ }
+ };
+
+ if (!isSupported) {
+ return (
+ 이 브라우저는 알림을 지원하지 않습니다.
+ );
+ }
+
+ const isPushEnabled = permission === 'granted' && token;
+
+ return (
+
+ {/* 푸시 알림 켜기/끄기 */}
+
+
+
푸시 알림
+
+ {isPushEnabled
+ ? '브라우저 알림이 활성화되어 있습니다.'
+ : '중요한 알림을 실시간으로 받아보세요.'}
+
+
+
+
+
+ {/* 알림 타입별 설정 */}
+ {isPushEnabled && (
+
+
알림 종류
+
+ {loading ? (
+
+ 로딩 중…
+
+ ) : (
+
+ {preferences.map((pref) => {
+ const {
+ label,
+ icon: Icon,
+ description,
+ } = NOTIFICATION_LABELS[pref.type] || {
+ label: pref.type,
+ icon: Bell,
+ description: '',
+ };
+
+ return (
+
+
+
+
+
+
+
+ {label}
+
+
{description}
+
+
+
+
+ handleToggle(pref.type, checked)}
+ aria-labelledby={`label-${pref.type}`}
+ />
+
+
+ );
+ })}
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/packages/web/src/components/ui/switch.tsx b/packages/web/src/components/ui/switch.tsx
index 5f4117f..9c51976 100644
--- a/packages/web/src/components/ui/switch.tsx
+++ b/packages/web/src/components/ui/switch.tsx
@@ -1,9 +1,9 @@
-"use client"
+'use client';
-import * as React from "react"
-import * as SwitchPrimitives from "@radix-ui/react-switch"
+import * as React from 'react';
+import * as SwitchPrimitives from '@radix-ui/react-switch';
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils';
const Switch = React.forwardRef<
React.ElementRef,
@@ -11,7 +11,7 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
-))
-Switch.displayName = SwitchPrimitives.Root.displayName
+));
+Switch.displayName = SwitchPrimitives.Root.displayName;
-export { Switch }
+export { Switch };
diff --git a/packages/web/src/hooks/use-push-notification.ts b/packages/web/src/hooks/use-push-notification.ts
new file mode 100644
index 0000000..74b67a8
--- /dev/null
+++ b/packages/web/src/hooks/use-push-notification.ts
@@ -0,0 +1,117 @@
+'use client';
+
+import { useEffect, useState } from 'react';
+import { toast } from 'sonner';
+import { onForegroundMessage, requestFCMToken } from '@/lib/firebase/client';
+
+const PUSH_UNSUBSCRIBED_KEY = 'push-unsubscribed';
+
+export function usePushNotification() {
+ const [permission, setPermission] = useState(
+ typeof window !== 'undefined' && 'Notification' in window ? Notification.permission : 'default'
+ );
+ const [token, setToken] = useState(null);
+
+ // 권한이 granted이고 명시적으로 해제하지 않았으면 토큰 자동 복원 + 서버 재구독
+ useEffect(() => {
+ const unsubscribed = localStorage.getItem(PUSH_UNSUBSCRIBED_KEY) === 'true';
+ if ('Notification' in window && Notification.permission === 'granted' && !unsubscribed) {
+ requestFCMToken().then((fcmToken) => {
+ if (fcmToken) {
+ setToken(fcmToken);
+ subscribeToPush(fcmToken);
+ }
+ });
+ }
+ }, []);
+
+ useEffect(() => {
+ if ('Notification' in window) {
+ const unsubscribe = onForegroundMessage((payload) => {
+ toast(payload.notification?.title || '알림', {
+ description: payload.notification?.body,
+ });
+ });
+
+ return () => unsubscribe();
+ }
+ }, []);
+
+ const requestPermission = async () => {
+ if (!('Notification' in window)) {
+ toast.error('이 브라우저는 알림을 지원하지 않습니다.');
+ return false;
+ }
+
+ const result = await Notification.requestPermission();
+ setPermission(result);
+
+ if (result === 'granted') {
+ const fcmToken = await requestFCMToken();
+ if (fcmToken) {
+ setToken(fcmToken);
+ localStorage.removeItem(PUSH_UNSUBSCRIBED_KEY);
+ await subscribeToPush(fcmToken);
+ toast.success('알림이 활성화되었습니다.');
+ return true;
+ }
+ }
+
+ if (result === 'denied') {
+ toast.error('알림이 차단되었습니다. 브라우저 설정에서 변경해주세요.');
+ }
+
+ return false;
+ };
+
+ const subscribeToPush = async (fcmToken: string) => {
+ try {
+ const res = await fetch('/api/push/subscribe', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ token: fcmToken,
+ deviceInfo: navigator.userAgent.slice(0, 200),
+ }),
+ });
+ if (!res.ok) {
+ throw new Error(`HTTP ${res.status}`);
+ }
+ const data = await res.json();
+ if (!data.success) {
+ throw new Error(data.message || '구독 실패');
+ }
+ } catch (error) {
+ console.error('Push subscription failed:', error);
+ toast.error('알림 구독에 실패했습니다.');
+ }
+ };
+
+ const unsubscribe = async () => {
+ // 토큰이 없으면 재발급 시도 후 삭제
+ let currentToken = token;
+ if (!currentToken) {
+ currentToken = await requestFCMToken();
+ }
+
+ if (currentToken) {
+ await fetch('/api/push/unsubscribe', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ token: currentToken }),
+ });
+ }
+
+ setToken(null);
+ localStorage.setItem(PUSH_UNSUBSCRIBED_KEY, 'true');
+ toast.success('알림이 비활성화되었습니다.');
+ };
+
+ return {
+ permission,
+ token,
+ requestPermission,
+ unsubscribe,
+ isSupported: typeof window !== 'undefined' && 'Notification' in window,
+ };
+}
diff --git a/packages/web/src/lib/firebase/admin.ts b/packages/web/src/lib/firebase/admin.ts
new file mode 100644
index 0000000..544fbeb
--- /dev/null
+++ b/packages/web/src/lib/firebase/admin.ts
@@ -0,0 +1,48 @@
+import admin from 'firebase-admin';
+import { getApps } from 'firebase-admin/app';
+
+let initialized = false;
+
+function ensureInitialized(): boolean {
+ if (initialized || getApps().length > 0) {
+ initialized = true;
+ return true;
+ }
+
+ try {
+ const serviceAccount = {
+ type: 'service_account',
+ project_id: process.env.FIREBASE_PROJECT_ID,
+ private_key_id: process.env.FIREBASE_PRIVATE_KEY_ID,
+ private_key: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
+ client_email: process.env.FIREBASE_CLIENT_EMAIL,
+ client_id: process.env.FIREBASE_CLIENT_ID,
+ auth_uri: 'https://accounts.google.com/o/oauth2/auth',
+ token_uri: 'https://oauth2.googleapis.com/token',
+ auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
+ client_x509_cert_url: `https://www.googleapis.com/robot/v1/metadata/x509/${process.env.FIREBASE_CLIENT_EMAIL}`,
+ };
+
+ if (!serviceAccount.project_id || !serviceAccount.private_key || !serviceAccount.client_email) {
+ throw new Error('Required Firebase environment variables are missing');
+ }
+
+ admin.initializeApp({
+ credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
+ });
+
+ console.log('[Firebase] Admin SDK initialized successfully');
+ initialized = true;
+ return true;
+ } catch (error) {
+ console.error('[Firebase] Failed to initialize Firebase Admin:', error);
+ return false;
+ }
+}
+
+export function getAdminMessaging() {
+ if (!ensureInitialized()) {
+ return null;
+ }
+ return admin.messaging();
+}
diff --git a/packages/web/src/lib/firebase/client.ts b/packages/web/src/lib/firebase/client.ts
new file mode 100644
index 0000000..266f6cf
--- /dev/null
+++ b/packages/web/src/lib/firebase/client.ts
@@ -0,0 +1,70 @@
+import { initializeApp, getApps, type FirebaseApp } from 'firebase/app';
+import { getMessaging, getToken, onMessage, type Messaging } from 'firebase/messaging';
+
+const firebaseConfig = {
+ apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
+ authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
+ projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
+ storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
+ messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
+ appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
+};
+
+let app: FirebaseApp | null = null;
+let messagingInstance: Messaging | null = null;
+
+function getApp(): FirebaseApp {
+ if (!app) {
+ app = !getApps().length ? initializeApp(firebaseConfig) : getApps()[0]!;
+ }
+ return app;
+}
+
+function getMessagingInstance(): Messaging {
+ if (!messagingInstance) {
+ messagingInstance = getMessaging(getApp());
+ }
+ return messagingInstance;
+}
+
+async function registerServiceWorker() {
+ if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
+ try {
+ const registration = await navigator.serviceWorker.register(
+ '/firebase-messaging-sw.js',
+ { type: 'classic' }
+ );
+ return registration;
+ } catch (error) {
+ console.error('[FCM] Service Worker registration failed:', error);
+ return null;
+ }
+ }
+ return null;
+}
+
+export async function requestFCMToken(): Promise {
+ try {
+ const registration = await registerServiceWorker();
+
+ if (!registration) {
+ console.error('[FCM] Service Worker registration failed');
+ return null;
+ }
+
+ const token = await getToken(getMessagingInstance(), {
+ vapidKey: process.env.NEXT_PUBLIC_FIREBASE_VAPID_KEY,
+ serviceWorkerRegistration: registration,
+ });
+ return token;
+ } catch (error) {
+ console.error('[FCM] Token request failed:', error);
+ return null;
+ }
+}
+
+export function onForegroundMessage(
+ callback: (payload: { notification?: { title?: string; body?: string } }) => void
+): () => void {
+ return onMessage(getMessagingInstance(), callback);
+}
diff --git a/packages/web/src/lib/push.ts b/packages/web/src/lib/push.ts
new file mode 100644
index 0000000..3912b65
--- /dev/null
+++ b/packages/web/src/lib/push.ts
@@ -0,0 +1,258 @@
+import { eq, inArray, and } from 'drizzle-orm';
+import { getDb } from '@/lib/db';
+import { db as sharedDb } from '@blog-study/shared';
+import { getAdminMessaging } from '@/lib/firebase/admin';
+import type { MulticastMessage } from 'firebase-admin/messaging';
+
+const { fcmTokens, notificationPreferences } = sharedDb;
+
+export interface PushPayload {
+ title: string;
+ body: string;
+ icon?: string;
+ clickUrl?: string;
+ data?: Record;
+}
+
+/**
+ * 사용자 알림 설정 확인 (기본값: true)
+ */
+async function isNotificationEnabled(memberId: string, type: string): Promise {
+ try {
+ const database = getDb();
+ const pref = await database
+ .select({ enabled: notificationPreferences.enabled })
+ .from(notificationPreferences)
+ .where(
+ and(
+ eq(notificationPreferences.memberId, memberId),
+ eq(notificationPreferences.type, type)
+ )
+ )
+ .limit(1);
+
+ return pref[0]?.enabled ?? true;
+ } catch {
+ return true; // 에러 시 기본값 true로 알림 허용
+ }
+}
+
+/**
+ * 특정 멤버에게 FCM 푸시 알림 전송
+ */
+export async function sendPushToMember(
+ memberId: string,
+ payload: PushPayload
+): Promise<{ success: number; failed: number }> {
+ const notificationType = payload.data?.type;
+ if (notificationType) {
+ const enabled = await isNotificationEnabled(memberId, notificationType);
+ if (!enabled) {
+ return { success: 0, failed: 0 }; // 알림 끄면 전송 안 함
+ }
+ }
+
+ const database = getDb();
+
+ const tokens = await database
+ .select({ token: fcmTokens.token })
+ .from(fcmTokens)
+ .where(eq(fcmTokens.memberId, memberId));
+
+ if (tokens.length === 0) {
+ return { success: 0, failed: 0 };
+ }
+
+ const message: MulticastMessage = {
+ notification: {
+ title: payload.title,
+ body: payload.body,
+ },
+ data: {
+ clickUrl: payload.clickUrl || '/dashboard',
+ ...payload.data,
+ },
+ webpush: {
+ notification: {
+ icon: payload.icon || '/icon-192.png',
+ },
+ fcmOptions: {
+ link: payload.clickUrl || '/dashboard',
+ },
+ },
+ tokens: tokens.map((t) => t.token),
+ };
+
+ const messaging = getAdminMessaging();
+ if (!messaging) {
+ console.warn('[push] Firebase Admin not initialized, skipping push');
+ return { success: 0, failed: tokens.length };
+ }
+
+ try {
+ const response = await messaging.sendEachForMulticast(message);
+
+ const failedTokens: string[] = [];
+ const succeededTokens: string[] = [];
+ response.responses.forEach((resp: { success: boolean }, idx: number) => {
+ if (resp.success) {
+ succeededTokens.push(tokens[idx]!.token);
+ } else {
+ failedTokens.push(tokens[idx]!.token);
+ }
+ });
+
+ // 실패한 토큰 삭제 (memberId 스코프)
+ if (failedTokens.length > 0) {
+ await database
+ .delete(fcmTokens)
+ .where(and(
+ eq(fcmTokens.memberId, memberId),
+ inArray(fcmTokens.token, failedTokens)
+ ));
+ }
+
+ // 성공한 토큰만 마지막 사용 시간 업데이트
+ if (succeededTokens.length > 0) {
+ await database
+ .update(fcmTokens)
+ .set({ lastUsedAt: new Date() })
+ .where(and(
+ eq(fcmTokens.memberId, memberId),
+ inArray(fcmTokens.token, succeededTokens)
+ ));
+ }
+
+ return {
+ success: response.successCount,
+ failed: response.failureCount,
+ };
+ } catch (error) {
+ console.error('[push] Failed to send:', error);
+ return { success: 0, failed: tokens.length };
+ }
+}
+
+/**
+ * 여러 멤버에게 FCM 푸시 알림 전송
+ */
+export async function sendPushToMembers(
+ memberIds: string[],
+ payload: PushPayload
+): Promise<{ success: number; failed: number }> {
+ const database = getDb();
+
+ // 알림 설정으로 수신 거부한 멤버 필터링
+ const notificationType = payload.data?.type;
+ let filteredMemberIds = memberIds;
+ if (notificationType) {
+ const disabledPrefs = await database
+ .select({ memberId: notificationPreferences.memberId })
+ .from(notificationPreferences)
+ .where(
+ and(
+ inArray(notificationPreferences.memberId, memberIds),
+ eq(notificationPreferences.type, notificationType),
+ eq(notificationPreferences.enabled, false)
+ )
+ );
+ const disabledSet = new Set(disabledPrefs.map((p) => p.memberId));
+ filteredMemberIds = memberIds.filter((id) => !disabledSet.has(id));
+ }
+
+ if (filteredMemberIds.length === 0) {
+ return { success: 0, failed: 0 };
+ }
+
+ const tokens = await database
+ .select({ token: fcmTokens.token, memberId: fcmTokens.memberId })
+ .from(fcmTokens)
+ .where(inArray(fcmTokens.memberId, filteredMemberIds));
+
+ if (tokens.length === 0) {
+ return { success: 0, failed: 0 };
+ }
+
+ // 멤버별로 그룹화하여 전송 (FCM quota 최적화)
+ const memberTokens = new Map();
+ tokens.forEach((t) => {
+ if (!memberTokens.has(t.memberId)) {
+ memberTokens.set(t.memberId, []);
+ }
+ memberTokens.get(t.memberId)!.push(t.token);
+ });
+
+ let totalSuccess = 0;
+ let totalFailed = 0;
+
+ // 멤버별로 전송 (중복 알림 방지)
+ for (const [memberId, tokenList] of memberTokens) {
+ const message: MulticastMessage = {
+ notification: {
+ title: payload.title,
+ body: payload.body,
+ },
+ data: {
+ clickUrl: payload.clickUrl || '/dashboard',
+ ...payload.data,
+ },
+ webpush: {
+ notification: {
+ icon: payload.icon || '/icon-192.png',
+ },
+ fcmOptions: {
+ link: payload.clickUrl || '/dashboard',
+ },
+ },
+ tokens: tokenList,
+ };
+
+ try {
+ const messaging = getAdminMessaging();
+ if (!messaging) {
+ totalFailed += tokenList.length;
+ continue;
+ }
+
+ const response = await messaging.sendEachForMulticast(message);
+ totalSuccess += response.successCount;
+ totalFailed += response.failureCount;
+
+ const failedTokens: string[] = [];
+ const succeededTokens: string[] = [];
+ response.responses.forEach((resp: { success: boolean }, idx: number) => {
+ if (resp.success) {
+ succeededTokens.push(tokenList[idx]!);
+ } else {
+ failedTokens.push(tokenList[idx]!);
+ }
+ });
+
+ // 실패한 토큰 삭제 (memberId 스코프)
+ if (failedTokens.length > 0) {
+ await database
+ .delete(fcmTokens)
+ .where(and(
+ eq(fcmTokens.memberId, memberId),
+ inArray(fcmTokens.token, failedTokens)
+ ));
+ }
+
+ // 성공한 토큰만 마지막 사용 시간 업데이트
+ if (succeededTokens.length > 0) {
+ await database
+ .update(fcmTokens)
+ .set({ lastUsedAt: new Date() })
+ .where(and(
+ eq(fcmTokens.memberId, memberId),
+ inArray(fcmTokens.token, succeededTokens)
+ ));
+ }
+ } catch (error) {
+ console.error(`[push] Failed to send to ${memberId}:`, error);
+ totalFailed += tokenList.length;
+ }
+ }
+
+ return { success: totalSuccess, failed: totalFailed };
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5a5b662..8a7eebc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,10 @@ overrides:
importers:
.:
+ dependencies:
+ firebase-admin:
+ specifier: ^13.7.0
+ version: 13.7.0
devDependencies:
'@playwright/test':
specifier: ^1.58.2
@@ -103,6 +107,9 @@ importers:
packages/shared:
dependencies:
+ '@radix-ui/react-switch':
+ specifier: ^1.2.6
+ version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
dotenv:
specifier: ^16.4.5
version: 16.6.1
@@ -233,6 +240,12 @@ importers:
feedsmith:
specifier: ^2.9.0
version: 2.9.0
+ firebase:
+ specifier: ^12.10.0
+ version: 12.10.0
+ firebase-admin:
+ specifier: ^13.7.0
+ version: 13.7.0
framer-motion:
specifier: ^12.35.1
version: 12.35.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -1044,11 +1057,224 @@ packages:
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@fastify/busboy@3.2.0':
+ resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==}
+
'@fastify/otel@0.16.0':
resolution: {integrity: sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA==}
peerDependencies:
'@opentelemetry/api': ^1.9.0
+ '@firebase/ai@2.9.0':
+ resolution: {integrity: sha512-NPvBBuvdGo9x3esnABAucFYmqbBmXvyTMimBq2PCuLZbdANZoHzGlx7vfzbwNDaEtCBq4RGGNMliLIv6bZ+PtA==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+ '@firebase/app-types': 0.x
+
+ '@firebase/analytics-compat@0.2.26':
+ resolution: {integrity: sha512-0j2ruLOoVSwwcXAF53AMoniJKnkwiTjGVfic5LDzqiRkR13vb5j6TXMeix787zbLeQtN/m1883Yv1TxI0gItbA==}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/analytics-types@0.8.3':
+ resolution: {integrity: sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==}
+
+ '@firebase/analytics@0.10.20':
+ resolution: {integrity: sha512-adGTNVUWH5q66tI/OQuKLSN6mamPpfYhj0radlH2xt+3eL6NFPtXoOs+ulvs+UsmK27vNFx5FjRDfWk+TyduHg==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/app-check-compat@0.4.1':
+ resolution: {integrity: sha512-yjSvSl5B1u4CirnxhzirN1uiTRCRfx+/qtfbyeyI+8Cx8Cw1RWAIO/OqytPSVwLYbJJ1vEC3EHfxazRaMoWKaA==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/app-check-interop-types@0.3.3':
+ resolution: {integrity: sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==}
+
+ '@firebase/app-check-types@0.5.3':
+ resolution: {integrity: sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==}
+
+ '@firebase/app-check@0.11.1':
+ resolution: {integrity: sha512-gmKfwQ2k8aUQlOyRshc+fOQLq0OwUmibIZvpuY1RDNu2ho0aTMlwxOuEiJeYOs7AxzhSx7gnXPFNsXCFbnvXUQ==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/app-compat@0.5.9':
+ resolution: {integrity: sha512-e5LzqjO69/N2z7XcJeuMzIp4wWnW696dQeaHAUpQvGk89gIWHAIvG6W+mA3UotGW6jBoqdppEJ9DnuwbcBByug==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/app-types@0.9.3':
+ resolution: {integrity: sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==}
+
+ '@firebase/app@0.14.9':
+ resolution: {integrity: sha512-3gtUX0e584MYkKBQMgSECMvE1Dwzg+eONefDQ0wxVSe5YMBsZwdN5pL7UapwWBlV8+i8QCztF9TP947tEjZAGA==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/auth-compat@0.6.3':
+ resolution: {integrity: sha512-nHOkupcYuGVxI1AJJ/OBhLPaRokbP14Gq4nkkoVvf1yvuREEWqdnrYB/CdsSnPxHMAnn5wJIKngxBF9jNX7s/Q==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/auth-interop-types@0.2.4':
+ resolution: {integrity: sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==}
+
+ '@firebase/auth-types@0.13.0':
+ resolution: {integrity: sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==}
+ peerDependencies:
+ '@firebase/app-types': 0.x
+ '@firebase/util': 1.x
+
+ '@firebase/auth@1.12.1':
+ resolution: {integrity: sha512-nXKj7d5bMBlnq6XpcQQpmnSVwEeHBkoVbY/+Wk0P1ebLSICoH4XPtvKOFlXKfIHmcS84mLQ99fk3njlDGKSDtw==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+ '@react-native-async-storage/async-storage': ^2.2.0
+ peerDependenciesMeta:
+ '@react-native-async-storage/async-storage':
+ optional: true
+
+ '@firebase/component@0.7.1':
+ resolution: {integrity: sha512-mFzsm7CLHR60o08S23iLUY8m/i6kLpOK87wdEFPLhdlCahaxKmWOwSVGiWoENYSmFJJoDhrR3gKSCxz7ENdIww==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/data-connect@0.4.0':
+ resolution: {integrity: sha512-vLXM6WHNIR3VtEeYNUb/5GTsUOyl3Of4iWNZHBe1i9f88sYFnxybJNWVBjvJ7flhCyF8UdxGpzWcUnv6F5vGfg==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/database-compat@2.1.1':
+ resolution: {integrity: sha512-heAEVZ9Z8c8PnBUcmGh91JHX0cXcVa1yESW/xkLuwaX7idRFyLiN8sl73KXpR8ZArGoPXVQDanBnk6SQiekRCQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/database-types@1.0.17':
+ resolution: {integrity: sha512-4eWaM5fW3qEIHjGzfi3cf0Jpqi1xQsAdT6rSDE1RZPrWu8oGjgrq6ybMjobtyHQFgwGCykBm4YM89qDzc+uG/w==}
+
+ '@firebase/database@1.1.1':
+ resolution: {integrity: sha512-LwIXe8+mVHY5LBPulWECOOIEXDiatyECp/BOlu0gOhe+WOcKjWHROaCbLlkFTgHMY7RHr5MOxkLP/tltWAH3dA==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/firestore-compat@0.4.6':
+ resolution: {integrity: sha512-NgVyR4hHHN2FvSNQOtbgBOuVsEdD/in30d9FKbEvvITiAChrBN2nBstmhfjI4EOTnHaP8zigwvkNYFI9yKGAkQ==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/firestore-types@3.0.3':
+ resolution: {integrity: sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==}
+ peerDependencies:
+ '@firebase/app-types': 0.x
+ '@firebase/util': 1.x
+
+ '@firebase/firestore@4.12.0':
+ resolution: {integrity: sha512-PM47OyiiAAoAMB8kkq4Je14mTciaRoAPDd3ng3Ckqz9i2TX9D9LfxIRcNzP/OxzNV4uBKRq6lXoOggkJBQR3Gw==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/functions-compat@0.4.2':
+ resolution: {integrity: sha512-YNxgnezvZDkqxqXa6cT7/oTeD4WXbxgIP7qZp4LFnathQv5o2omM6EoIhXiT9Ie5AoQDcIhG9Y3/dj+DFJGaGQ==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/functions-types@0.6.3':
+ resolution: {integrity: sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==}
+
+ '@firebase/functions@0.13.2':
+ resolution: {integrity: sha512-tHduUD+DeokM3NB1QbHCvEMoL16e8Z8JSkmuVA4ROoJKPxHn8ibnecHPO2e3nVCJR1D9OjuKvxz4gksfq92/ZQ==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/installations-compat@0.2.20':
+ resolution: {integrity: sha512-9C9pL/DIEGucmoPj8PlZTnztbX3nhNj5RTYVpUM7wQq/UlHywaYv99969JU/WHLvi9ptzIogXYS9d1eZ6XFe9g==}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/installations-types@0.5.3':
+ resolution: {integrity: sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==}
+ peerDependencies:
+ '@firebase/app-types': 0.x
+
+ '@firebase/installations@0.6.20':
+ resolution: {integrity: sha512-LOzvR7XHPbhS0YB5ANXhqXB5qZlntPpwU/4KFwhSNpXNsGk/sBQ9g5hepi0y0/MfenJLe2v7t644iGOOElQaHQ==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/logger@0.5.0':
+ resolution: {integrity: sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/messaging-compat@0.2.24':
+ resolution: {integrity: sha512-wXH8FrKbJvFuFe6v98TBhAtvgknxKIZtGM/wCVsfpOGmaAE80bD8tBxztl+uochjnFb9plihkd6mC4y7sZXSpA==}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/messaging-interop-types@0.2.3':
+ resolution: {integrity: sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==}
+
+ '@firebase/messaging@0.12.24':
+ resolution: {integrity: sha512-UtKoubegAhHyehcB7iQjvQ8OVITThPbbWk3g2/2ze42PrQr6oe6OmCElYQkBrE5RDCeMTNucXejbdulrQ2XwVg==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/performance-compat@0.2.23':
+ resolution: {integrity: sha512-c7qOAGBUAOpIuUlHu1axWcrCVtIYKPMhH0lMnoCDWnPwn1HcPuPUBVTWETbC7UWw71RMJF8DpirfWXzMWJQfgA==}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/performance-types@0.2.3':
+ resolution: {integrity: sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==}
+
+ '@firebase/performance@0.7.10':
+ resolution: {integrity: sha512-8nRFld+Ntzp5cLKzZuG9g+kBaSn8Ks9dmn87UQGNFDygbmR6ebd8WawauEXiJjMj1n70ypkvAOdE+lzeyfXtGA==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/remote-config-compat@0.2.22':
+ resolution: {integrity: sha512-uW/eNKKtRBot2gnCC5mnoy5Voo2wMzZuQ7dwqqGHU176fO9zFgMwKiRzk+aaC99NLrFk1KOmr0ZVheD+zdJmjQ==}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/remote-config-types@0.5.0':
+ resolution: {integrity: sha512-vI3bqLoF14L/GchtgayMiFpZJF+Ao3uR8WCde0XpYNkSokDpAKca2DxvcfeZv7lZUqkUwQPL2wD83d3vQ4vvrg==}
+
+ '@firebase/remote-config@0.8.1':
+ resolution: {integrity: sha512-L86TReBnPiiJOWd7k9iaiE9f7rHtMpjAoYN0fH2ey2ZRzsOChHV0s5sYf1+IIUYzplzsE46pjlmAUNkRRKwHSQ==}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/storage-compat@0.4.1':
+ resolution: {integrity: sha512-bgl3FHHfXAmBgzIK/Fps6Xyv2HiAQlSTov07CBL+RGGhrC5YIk4lruS8JVIC+UkujRdYvnf8cpQFGn2RCilJ/A==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app-compat': 0.x
+
+ '@firebase/storage-types@0.8.3':
+ resolution: {integrity: sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==}
+ peerDependencies:
+ '@firebase/app-types': 0.x
+ '@firebase/util': 1.x
+
+ '@firebase/storage@0.14.1':
+ resolution: {integrity: sha512-uIpYgBBsv1vIET+5xV20XT7wwqV+H4GFp6PBzfmLUcEgguS4SWNFof56Z3uOC2lNDh0KDda1UflYq2VwD9Nefw==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@firebase/app': 0.x
+
+ '@firebase/util@1.14.0':
+ resolution: {integrity: sha512-/gnejm7MKkVIXnSJGpc9L2CvvvzJvtDPeAEq5jAwgVlf/PeNxot+THx/bpD20wQ8uL5sz0xqgXy1nisOYMU+mw==}
+ engines: {node: '>=20.0.0'}
+
+ '@firebase/webchannel-wrapper@1.0.5':
+ resolution: {integrity: sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==}
+
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
@@ -1064,6 +1290,44 @@ packages:
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
+ '@google-cloud/firestore@7.11.6':
+ resolution: {integrity: sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==}
+ engines: {node: '>=14.0.0'}
+
+ '@google-cloud/paginator@5.0.2':
+ resolution: {integrity: sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==}
+ engines: {node: '>=14.0.0'}
+
+ '@google-cloud/projectify@4.0.0':
+ resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==}
+ engines: {node: '>=14.0.0'}
+
+ '@google-cloud/promisify@4.0.0':
+ resolution: {integrity: sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==}
+ engines: {node: '>=14'}
+
+ '@google-cloud/storage@7.19.0':
+ resolution: {integrity: sha512-n2FjE7NAOYyshogdc7KQOl/VZb4sneqPjWouSyia9CMDdMhRX5+RIbqalNmC7LOLzuLAN89VlF2HvG8na9G+zQ==}
+ engines: {node: '>=14'}
+
+ '@grpc/grpc-js@1.14.3':
+ resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==}
+ engines: {node: '>=12.10.0'}
+
+ '@grpc/grpc-js@1.9.15':
+ resolution: {integrity: sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==}
+ engines: {node: ^8.13.0 || >=10.10.0}
+
+ '@grpc/proto-loader@0.7.15':
+ resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ '@grpc/proto-loader@0.8.0':
+ resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==}
+ engines: {node: '>=6'}
+ hasBin: true
+
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -1226,6 +1490,10 @@ packages:
cpu: [x64]
os: [win32]
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
'@jest/schemas@29.6.3':
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1249,6 +1517,9 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@js-sdsl/ordered-map@4.4.2':
+ resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
+
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -1535,6 +1806,10 @@ packages:
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
'@playwright/test@1.58.2':
resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==}
engines: {node: '>=18'}
@@ -1545,6 +1820,36 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.8
+ '@protobufjs/aspromise@1.1.2':
+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
+
+ '@protobufjs/base64@1.1.2':
+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
+
+ '@protobufjs/codegen@2.0.4':
+ resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
+
+ '@protobufjs/eventemitter@1.1.0':
+ resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
+
+ '@protobufjs/fetch@1.1.0':
+ resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
+
+ '@protobufjs/float@1.0.2':
+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
+
+ '@protobufjs/inquire@1.1.0':
+ resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
+
+ '@protobufjs/path@1.1.2':
+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
+
+ '@protobufjs/pool@1.1.0':
+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
+
+ '@protobufjs/utf8@1.1.0':
+ resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
+
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@@ -2607,12 +2912,19 @@ packages:
'@tiptap/starter-kit@3.20.0':
resolution: {integrity: sha512-W4+1re35pDNY/7rpXVg+OKo/Fa4Gfrn08Bq3E3fzlJw6gjE3tYU8dY9x9vC2rK9pd9NOp7Af11qCFDaWpohXkw==}
+ '@tootallnate/once@2.0.0':
+ resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+ engines: {node: '>= 10'}
+
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
'@types/body-parser@1.19.6':
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
+ '@types/caseless@0.12.5':
+ resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==}
+
'@types/connect@3.4.38':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
@@ -2647,15 +2959,24 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ '@types/jsonwebtoken@9.0.10':
+ resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
+
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
+ '@types/long@4.0.2':
+ resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
+
'@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
'@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/mysql@2.15.27':
resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==}
@@ -2688,6 +3009,9 @@ packages:
'@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
+ '@types/request@2.48.13':
+ resolution: {integrity: sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==}
+
'@types/send@1.2.1':
resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==}
@@ -2697,6 +3021,9 @@ packages:
'@types/tedious@4.0.14':
resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==}
+ '@types/tough-cookie@4.0.5':
+ resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
+
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@@ -2991,6 +3318,10 @@ packages:
'@xtuc/long@4.2.2':
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
+ abort-controller@3.0.0:
+ resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
+ engines: {node: '>=6.5'}
+
accepts@2.0.0:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
@@ -3029,6 +3360,10 @@ packages:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -3055,6 +3390,10 @@ packages:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
+ ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
+ engines: {node: '>=12'}
+
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
@@ -3063,6 +3402,10 @@ packages:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
engines: {node: '>=10'}
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+ engines: {node: '>=12'}
+
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
@@ -3113,6 +3456,10 @@ packages:
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
engines: {node: '>= 0.4'}
+ arrify@2.0.1:
+ resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
+ engines: {node: '>=8'}
+
assertion-error@1.1.0:
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
@@ -3123,6 +3470,9 @@ packages:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
+ async-retry@1.3.3:
+ resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
+
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -3152,11 +3502,17 @@ packages:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
baseline-browser-mapping@2.10.0:
resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==}
engines: {node: '>=6.0.0'}
hasBin: true
+ bignumber.js@9.3.1:
+ resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
+
body-parser@2.2.2:
resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==}
engines: {node: '>=18'}
@@ -3183,6 +3539,9 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -3254,6 +3613,10 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
@@ -3344,6 +3707,10 @@ packages:
damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+ data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+
data-view-buffer@1.0.2:
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
@@ -3556,12 +3923,24 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+ duplexify@4.1.3:
+ resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
+
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ ecdsa-sig-formatter@1.0.11:
+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
electron-to-chromium@1.5.302:
resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==}
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
@@ -3818,6 +4197,10 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
+ event-target-shim@5.0.1:
+ resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
+ engines: {node: '>=6'}
+
events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
@@ -3836,6 +4219,13 @@ packages:
resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
engines: {node: '>= 18'}
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+ farmhash-modern@1.1.0:
+ resolution: {integrity: sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==}
+ engines: {node: '>=18.0.0'}
+
fast-check@3.23.2:
resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
engines: {node: '>=8.0.0'}
@@ -3877,6 +4267,10 @@ packages:
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+ faye-websocket@0.11.4:
+ resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
+ engines: {node: '>=0.8.0'}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -3889,6 +4283,10 @@ packages:
feedsmith@2.9.0:
resolution: {integrity: sha512-TYucytOx4bTrD4ON0iuJG9y0Me7fiT0EZ+7MIE0xptvd8TL6nY0Z1jVPa9W39WMJUtPqV2r27TQxL/z5DCCmdA==}
+ fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+
file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -3909,6 +4307,13 @@ packages:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
+ firebase-admin@13.7.0:
+ resolution: {integrity: sha512-o3qS8zCJbApe7aKzkO2Pa380t9cHISqeSd3blqYTtOuUUUua3qZTLwNWgGUOss3td6wbzrZhiHIj3c8+fC046Q==}
+ engines: {node: '>=18'}
+
+ firebase@12.10.0:
+ resolution: {integrity: sha512-tAjHnEirksqWpa+NKDUSUMjulOnsTcsPC1X1rQ+gwPtjlhJS572na91CwaBXQJHXharIrfj7sw/okDkXOsphjA==}
+
fix-dts-default-cjs-exports@1.0.1:
resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==}
@@ -3936,10 +4341,22 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+
+ form-data@2.5.5:
+ resolution: {integrity: sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==}
+ engines: {node: '>= 0.12'}
+
form-data@4.0.5:
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
engines: {node: '>= 6'}
+ formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+
forwarded-parse@2.1.2:
resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
@@ -3985,9 +4402,28 @@ packages:
resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
engines: {node: '>= 0.4'}
+ functional-red-black-tree@1.0.1:
+ resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
+
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ gaxios@6.7.1:
+ resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==}
+ engines: {node: '>=14'}
+
+ gaxios@7.1.3:
+ resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==}
+ engines: {node: '>=18'}
+
+ gcp-metadata@6.1.1:
+ resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==}
+ engines: {node: '>=14'}
+
+ gcp-metadata@8.1.2:
+ resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==}
+ engines: {node: '>=18'}
+
generator-function@2.0.1:
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
engines: {node: '>= 0.4'}
@@ -3996,6 +4432,10 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
get-func-name@2.0.2:
resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
@@ -4033,6 +4473,11 @@ packages:
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+ glob@10.5.0:
+ resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
+ hasBin: true
+
glob@13.0.6:
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
engines: {node: 18 || 20 || >=22}
@@ -4061,6 +4506,26 @@ packages:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
+ google-auth-library@10.6.1:
+ resolution: {integrity: sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==}
+ engines: {node: '>=18'}
+
+ google-auth-library@9.15.1:
+ resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==}
+ engines: {node: '>=14'}
+
+ google-gax@4.6.1:
+ resolution: {integrity: sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==}
+ engines: {node: '>=14'}
+
+ google-logging-utils@0.0.2:
+ resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==}
+ engines: {node: '>=14'}
+
+ google-logging-utils@1.1.3:
+ resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==}
+ engines: {node: '>=14'}
+
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -4071,6 +4536,10 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ gtoken@7.1.0:
+ resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==}
+ engines: {node: '>=14.0.0'}
+
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -4121,10 +4590,21 @@ packages:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'}
+ http-parser-js@0.5.10:
+ resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==}
+
+ http-proxy-agent@5.0.0:
+ resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
+ engines: {node: '>= 6'}
+
https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
@@ -4141,6 +4621,9 @@ packages:
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
engines: {node: '>=0.10.0'}
+ idb@7.1.1:
+ resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -4222,6 +4705,10 @@ packages:
resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
engines: {node: '>= 0.4'}
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
is-generator-function@1.1.2:
resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
engines: {node: '>= 0.4'}
@@ -4268,6 +4755,10 @@ packages:
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'}
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
is-stream@3.0.0:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -4306,6 +4797,9 @@ packages:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
jest-worker@27.5.1:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
@@ -4314,6 +4808,9 @@ packages:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
+ jose@4.15.9:
+ resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==}
+
joycon@3.1.1:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
@@ -4333,6 +4830,9 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ json-bigint@1.0.0:
+ resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
+
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
@@ -4357,10 +4857,24 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jsonwebtoken@9.0.3:
+ resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
+ engines: {node: '>=12', npm: '>=6'}
+
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
+ jwa@2.0.1:
+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
+
+ jwks-rsa@3.2.2:
+ resolution: {integrity: sha512-BqTyEDV+lS8F2trk3A+qJnxV5Q9EqKCBJOPti3W97r7qTympCZjb7h2X6f2kc+0K3rsSTY1/6YG2eaXKoj497w==}
+ engines: {node: '>=14'}
+
+ jws@4.0.1:
+ resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -4449,6 +4963,9 @@ packages:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
+ limiter@1.1.5:
+ resolution: {integrity: sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==}
+
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@@ -4474,15 +4991,45 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash.camelcase@4.3.0:
+ resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
+
+ lodash.clonedeep@4.5.0:
+ resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
+
+ lodash.includes@4.3.0:
+ resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+
+ lodash.isboolean@3.0.3:
+ resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+
+ lodash.isinteger@4.0.4:
+ resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+
+ lodash.isnumber@3.0.3:
+ resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+
+ lodash.isplainobject@4.0.6:
+ resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+
+ lodash.isstring@4.0.1:
+ resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ lodash.once@4.1.1:
+ resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+
lodash.snakecase@4.1.1:
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -4493,6 +5040,9 @@ packages:
lowlight@3.3.0:
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
lru-cache@11.2.6:
resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==}
engines: {node: 20 || >=22}
@@ -4500,6 +5050,13 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+
+ lru-memoizer@2.3.0:
+ resolution: {integrity: sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==}
+
lucide-react@0.575.0:
resolution: {integrity: sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg==}
peerDependencies:
@@ -4561,6 +5118,11 @@ packages:
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
engines: {node: '>=18'}
+ mime@3.0.0:
+ resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+
mimic-fn@4.0.0:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
@@ -4651,6 +5213,11 @@ packages:
sass:
optional: true
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ deprecated: Use your platform's native DOMException instead
+
node-exports-info@1.6.0:
resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==}
engines: {node: '>= 0.4'}
@@ -4664,6 +5231,14 @@ packages:
encoding:
optional: true
+ node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ node-forge@1.3.3:
+ resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==}
+ engines: {node: '>= 6.13.0'}
+
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
@@ -4682,6 +5257,10 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -4748,6 +5327,9 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
@@ -4784,6 +5366,10 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
path-scurry@2.0.2:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22}
@@ -5020,6 +5606,14 @@ packages:
prosemirror-view@1.41.6:
resolution: {integrity: sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==}
+ proto3-json-serializer@2.0.2:
+ resolution: {integrity: sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==}
+ engines: {node: '>=14.0.0'}
+
+ protobufjs@7.5.4:
+ resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
+ engines: {node: '>=12.0.0'}
+
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -5110,6 +5704,10 @@ packages:
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
@@ -5126,6 +5724,10 @@ packages:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
@@ -5155,6 +5757,14 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
+ retry-request@7.0.2:
+ resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==}
+ engines: {node: '>=14'}
+
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -5164,6 +5774,10 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
+ rimraf@5.0.10:
+ resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==}
+ hasBin: true
+
rollup@4.53.3:
resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -5183,6 +5797,9 @@ packages:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'}
@@ -5332,11 +5949,25 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
- string.prototype.includes@2.0.1:
- resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
- engines: {node: '>= 0.4'}
+ stream-events@1.0.5:
+ resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==}
- string.prototype.matchall@4.0.12:
+ stream-shift@1.0.3:
+ resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
+ string.prototype.includes@2.0.1:
+ resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.matchall@4.0.12:
resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
engines: {node: '>= 0.4'}
@@ -5355,10 +5986,17 @@ packages:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
engines: {node: '>= 0.4'}
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
+ strip-ansi@7.2.0:
+ resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
+ engines: {node: '>=12'}
+
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
@@ -5381,6 +6019,9 @@ packages:
strnum@2.1.2:
resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==}
+ stubs@3.0.0:
+ resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==}
+
styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'}
@@ -5425,6 +6066,10 @@ packages:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
+ teeny-request@9.0.0:
+ resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==}
+ engines: {node: '>=14'}
+
terser-webpack-plugin@5.4.0:
resolution: {integrity: sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==}
engines: {node: '>= 10.13.0'}
@@ -5661,6 +6306,14 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ uuid@11.1.0:
+ resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
+ hasBin: true
+
+ uuid@8.3.2:
+ resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+ hasBin: true
+
uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
@@ -5743,6 +6396,13 @@ packages:
resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==}
engines: {node: '>=10.13.0'}
+ web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+
+ web-vitals@4.2.4:
+ resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
+
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -5760,6 +6420,14 @@ packages:
webpack-cli:
optional: true
+ websocket-driver@0.7.4:
+ resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
+ engines: {node: '>=0.8.0'}
+
+ websocket-extensions@0.1.4:
+ resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
+ engines: {node: '>=0.8.0'}
+
whatwg-encoding@3.1.1:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
@@ -5802,6 +6470,14 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
@@ -5821,9 +6497,24 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
@@ -6378,6 +7069,8 @@ snapshots:
'@eslint/core': 0.17.0
levn: 0.4.1
+ '@fastify/busboy@3.2.0': {}
+
'@fastify/otel@0.16.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -6388,6 +7081,324 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@firebase/ai@2.9.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/app-check-interop-types': 0.3.3
+ '@firebase/app-types': 0.9.3
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/analytics-compat@0.2.26(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/analytics': 0.10.20(@firebase/app@0.14.9)
+ '@firebase/analytics-types': 0.8.3
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/analytics-types@0.8.3': {}
+
+ '@firebase/analytics@0.10.20(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/app-check-compat@0.4.1(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-check': 0.11.1(@firebase/app@0.14.9)
+ '@firebase/app-check-types': 0.5.3
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/app-check-interop-types@0.3.3': {}
+
+ '@firebase/app-check-types@0.5.3': {}
+
+ '@firebase/app-check@0.11.1(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/app-compat@0.5.9':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/app-types@0.9.3': {}
+
+ '@firebase/app@0.14.9':
+ dependencies:
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ idb: 7.1.1
+ tslib: 2.8.1
+
+ '@firebase/auth-compat@0.6.3(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/auth': 1.12.1(@firebase/app@0.14.9)
+ '@firebase/auth-types': 0.13.0(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)
+ '@firebase/component': 0.7.1
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+ - '@firebase/app-types'
+ - '@react-native-async-storage/async-storage'
+
+ '@firebase/auth-interop-types@0.2.4': {}
+
+ '@firebase/auth-types@0.13.0(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)':
+ dependencies:
+ '@firebase/app-types': 0.9.3
+ '@firebase/util': 1.14.0
+
+ '@firebase/auth@1.12.1(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/component@0.7.1':
+ dependencies:
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/data-connect@0.4.0(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/auth-interop-types': 0.2.4
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/database-compat@2.1.1':
+ dependencies:
+ '@firebase/component': 0.7.1
+ '@firebase/database': 1.1.1
+ '@firebase/database-types': 1.0.17
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/database-types@1.0.17':
+ dependencies:
+ '@firebase/app-types': 0.9.3
+ '@firebase/util': 1.14.0
+
+ '@firebase/database@1.1.1':
+ dependencies:
+ '@firebase/app-check-interop-types': 0.3.3
+ '@firebase/auth-interop-types': 0.2.4
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ faye-websocket: 0.11.4
+ tslib: 2.8.1
+
+ '@firebase/firestore-compat@0.4.6(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/firestore': 4.12.0(@firebase/app@0.14.9)
+ '@firebase/firestore-types': 3.0.3(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+ - '@firebase/app-types'
+
+ '@firebase/firestore-types@3.0.3(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)':
+ dependencies:
+ '@firebase/app-types': 0.9.3
+ '@firebase/util': 1.14.0
+
+ '@firebase/firestore@4.12.0(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ '@firebase/webchannel-wrapper': 1.0.5
+ '@grpc/grpc-js': 1.9.15
+ '@grpc/proto-loader': 0.7.15
+ tslib: 2.8.1
+
+ '@firebase/functions-compat@0.4.2(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/functions': 0.13.2(@firebase/app@0.14.9)
+ '@firebase/functions-types': 0.6.3
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/functions-types@0.6.3': {}
+
+ '@firebase/functions@0.13.2(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/app-check-interop-types': 0.3.3
+ '@firebase/auth-interop-types': 0.2.4
+ '@firebase/component': 0.7.1
+ '@firebase/messaging-interop-types': 0.2.3
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/installations-compat@0.2.20(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/installations-types': 0.5.3(@firebase/app-types@0.9.3)
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+ - '@firebase/app-types'
+
+ '@firebase/installations-types@0.5.3(@firebase/app-types@0.9.3)':
+ dependencies:
+ '@firebase/app-types': 0.9.3
+
+ '@firebase/installations@0.6.20(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/util': 1.14.0
+ idb: 7.1.1
+ tslib: 2.8.1
+
+ '@firebase/logger@0.5.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@firebase/messaging-compat@0.2.24(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/messaging': 0.12.24(@firebase/app@0.14.9)
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/messaging-interop-types@0.2.3': {}
+
+ '@firebase/messaging@0.12.24(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/messaging-interop-types': 0.2.3
+ '@firebase/util': 1.14.0
+ idb: 7.1.1
+ tslib: 2.8.1
+
+ '@firebase/performance-compat@0.2.23(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/performance': 0.7.10(@firebase/app@0.14.9)
+ '@firebase/performance-types': 0.2.3
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/performance-types@0.2.3': {}
+
+ '@firebase/performance@0.7.10(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ web-vitals: 4.2.4
+
+ '@firebase/remote-config-compat@0.2.22(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/logger': 0.5.0
+ '@firebase/remote-config': 0.8.1(@firebase/app@0.14.9)
+ '@firebase/remote-config-types': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+
+ '@firebase/remote-config-types@0.5.0': {}
+
+ '@firebase/remote-config@0.8.1(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/logger': 0.5.0
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/storage-compat@0.4.1(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app-compat': 0.5.9
+ '@firebase/component': 0.7.1
+ '@firebase/storage': 0.14.1(@firebase/app@0.14.9)
+ '@firebase/storage-types': 0.8.3(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@firebase/app'
+ - '@firebase/app-types'
+
+ '@firebase/storage-types@0.8.3(@firebase/app-types@0.9.3)(@firebase/util@1.14.0)':
+ dependencies:
+ '@firebase/app-types': 0.9.3
+ '@firebase/util': 1.14.0
+
+ '@firebase/storage@0.14.1(@firebase/app@0.14.9)':
+ dependencies:
+ '@firebase/app': 0.14.9
+ '@firebase/component': 0.7.1
+ '@firebase/util': 1.14.0
+ tslib: 2.8.1
+
+ '@firebase/util@1.14.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@firebase/webchannel-wrapper@1.0.5': {}
+
'@floating-ui/core@1.7.3':
dependencies:
'@floating-ui/utils': 0.2.10
@@ -6405,6 +7416,78 @@ snapshots:
'@floating-ui/utils@0.2.10': {}
+ '@google-cloud/firestore@7.11.6':
+ dependencies:
+ '@opentelemetry/api': 1.9.0
+ fast-deep-equal: 3.1.3
+ functional-red-black-tree: 1.0.1
+ google-gax: 4.6.1
+ protobufjs: 7.5.4
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ '@google-cloud/paginator@5.0.2':
+ dependencies:
+ arrify: 2.0.1
+ extend: 3.0.2
+ optional: true
+
+ '@google-cloud/projectify@4.0.0':
+ optional: true
+
+ '@google-cloud/promisify@4.0.0':
+ optional: true
+
+ '@google-cloud/storage@7.19.0':
+ dependencies:
+ '@google-cloud/paginator': 5.0.2
+ '@google-cloud/projectify': 4.0.0
+ '@google-cloud/promisify': 4.0.0
+ abort-controller: 3.0.0
+ async-retry: 1.3.3
+ duplexify: 4.1.3
+ fast-xml-parser: 5.3.7
+ gaxios: 6.7.1
+ google-auth-library: 9.15.1
+ html-entities: 2.6.0
+ mime: 3.0.0
+ p-limit: 3.1.0
+ retry-request: 7.0.2
+ teeny-request: 9.0.0
+ uuid: 8.3.2
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ '@grpc/grpc-js@1.14.3':
+ dependencies:
+ '@grpc/proto-loader': 0.8.0
+ '@js-sdsl/ordered-map': 4.4.2
+ optional: true
+
+ '@grpc/grpc-js@1.9.15':
+ dependencies:
+ '@grpc/proto-loader': 0.7.15
+ '@types/node': 22.19.11
+
+ '@grpc/proto-loader@0.7.15':
+ dependencies:
+ lodash.camelcase: 4.3.0
+ long: 5.3.2
+ protobufjs: 7.5.4
+ yargs: 17.7.2
+
+ '@grpc/proto-loader@0.8.0':
+ dependencies:
+ lodash.camelcase: 4.3.0
+ long: 5.3.2
+ protobufjs: 7.5.4
+ yargs: 17.7.2
+ optional: true
+
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':
@@ -6523,6 +7606,15 @@ snapshots:
'@img/sharp-win32-x64@0.34.5':
optional: true
+ '@isaacs/cliui@8.0.2':
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.2.0
+ strip-ansi-cjs: strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: wrap-ansi@7.0.0
+
'@jest/schemas@29.6.3':
dependencies:
'@sinclair/typebox': 0.27.8
@@ -6551,6 +7643,9 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@js-sdsl/ordered-map@4.4.2':
+ optional: true
+
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.8.1
@@ -6872,6 +7967,9 @@ snapshots:
'@pinojs/redact@0.4.0': {}
+ '@pkgjs/parseargs@0.11.0':
+ optional: true
+
'@playwright/test@1.58.2':
dependencies:
playwright: 1.58.2
@@ -6883,6 +7981,29 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@protobufjs/aspromise@1.1.2': {}
+
+ '@protobufjs/base64@1.1.2': {}
+
+ '@protobufjs/codegen@2.0.4': {}
+
+ '@protobufjs/eventemitter@1.1.0': {}
+
+ '@protobufjs/fetch@1.1.0':
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/inquire': 1.1.0
+
+ '@protobufjs/float@1.0.2': {}
+
+ '@protobufjs/inquire@1.1.0': {}
+
+ '@protobufjs/path@1.1.2': {}
+
+ '@protobufjs/pool@1.1.0': {}
+
+ '@protobufjs/utf8@1.1.0': {}
+
'@radix-ui/number@1.1.1': {}
'@radix-ui/primitive@1.1.3': {}
@@ -7960,6 +9081,9 @@ snapshots:
'@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)
'@tiptap/pm': 3.20.0
+ '@tootallnate/once@2.0.0':
+ optional: true
+
'@tybys/wasm-util@0.10.1':
dependencies:
tslib: 2.8.1
@@ -7970,6 +9094,9 @@ snapshots:
'@types/connect': 3.4.38
'@types/node': 22.19.11
+ '@types/caseless@0.12.5':
+ optional: true
+
'@types/connect@3.4.38':
dependencies:
'@types/node': 22.19.11
@@ -8015,8 +9142,16 @@ snapshots:
'@types/json5@0.0.29': {}
+ '@types/jsonwebtoken@9.0.10':
+ dependencies:
+ '@types/ms': 2.1.0
+ '@types/node': 22.19.11
+
'@types/linkify-it@5.0.0': {}
+ '@types/long@4.0.2':
+ optional: true
+
'@types/markdown-it@14.1.2':
dependencies:
'@types/linkify-it': 5.0.0
@@ -8024,6 +9159,8 @@ snapshots:
'@types/mdurl@2.0.0': {}
+ '@types/ms@2.1.0': {}
+
'@types/mysql@2.15.27':
dependencies:
'@types/node': 22.19.11
@@ -8060,6 +9197,14 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/request@2.48.13':
+ dependencies:
+ '@types/caseless': 0.12.5
+ '@types/node': 22.19.11
+ '@types/tough-cookie': 4.0.5
+ form-data: 2.5.5
+ optional: true
+
'@types/send@1.2.1':
dependencies:
'@types/node': 22.19.11
@@ -8073,6 +9218,9 @@ snapshots:
dependencies:
'@types/node': 22.19.11
+ '@types/tough-cookie@4.0.5':
+ optional: true
+
'@types/unist@3.0.3': {}
'@types/use-sync-external-store@0.0.6': {}
@@ -8425,6 +9573,11 @@ snapshots:
'@xtuc/long@4.2.2': {}
+ abort-controller@3.0.0:
+ dependencies:
+ event-target-shim: 5.0.1
+ optional: true
+
accepts@2.0.0:
dependencies:
mime-types: 3.0.2
@@ -8456,6 +9609,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ agent-base@7.1.4: {}
+
ajv-formats@2.1.1(ajv@8.18.0):
optionalDependencies:
ajv: 8.18.0
@@ -8488,12 +9643,16 @@ snapshots:
ansi-regex@5.0.1: {}
+ ansi-regex@6.2.2: {}
+
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
ansi-styles@5.2.0: {}
+ ansi-styles@6.2.3: {}
+
any-promise@1.3.0: {}
argparse@2.0.1: {}
@@ -8573,12 +9732,20 @@ snapshots:
get-intrinsic: 1.3.0
is-array-buffer: 3.0.5
+ arrify@2.0.1:
+ optional: true
+
assertion-error@1.1.0: {}
ast-types-flow@0.0.8: {}
async-function@1.0.0: {}
+ async-retry@1.3.3:
+ dependencies:
+ retry: 0.13.1
+ optional: true
+
asynckit@0.4.0: {}
atomic-sleep@1.0.0: {}
@@ -8603,8 +9770,12 @@ snapshots:
balanced-match@4.0.4: {}
+ base64-js@1.5.1: {}
+
baseline-browser-mapping@2.10.0: {}
+ bignumber.js@9.3.1: {}
+
body-parser@2.2.2:
dependencies:
bytes: 3.1.2
@@ -8646,6 +9817,8 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ buffer-equal-constant-time@1.0.1: {}
+
buffer-from@1.1.2: {}
bundle-require@5.1.0(esbuild@0.27.0):
@@ -8734,6 +9907,12 @@ snapshots:
client-only@0.0.1: {}
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
clsx@2.1.1: {}
color-convert@2.0.1:
@@ -8800,6 +9979,8 @@ snapshots:
damerau-levenshtein@1.0.8: {}
+ data-uri-to-buffer@4.0.1: {}
+
data-view-buffer@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -8943,10 +10124,26 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
+ duplexify@4.1.3:
+ dependencies:
+ end-of-stream: 1.4.5
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ stream-shift: 1.0.3
+ optional: true
+
+ eastasianwidth@0.2.0: {}
+
+ ecdsa-sig-formatter@1.0.11:
+ dependencies:
+ safe-buffer: 5.2.1
+
ee-first@1.1.1: {}
electron-to-chromium@1.5.302: {}
+ emoji-regex@8.0.0: {}
+
emoji-regex@9.2.2: {}
encodeurl@2.0.0: {}
@@ -9472,6 +10669,9 @@ snapshots:
etag@1.8.1: {}
+ event-target-shim@5.0.1:
+ optional: true
+
events@3.3.0: {}
execa@8.0.1:
@@ -9524,6 +10724,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ extend@3.0.2: {}
+
+ farmhash-modern@1.1.0: {}
+
fast-check@3.23.2:
dependencies:
pure-rand: 6.1.0
@@ -9566,6 +10770,10 @@ snapshots:
dependencies:
reusify: 1.1.0
+ faye-websocket@0.11.4:
+ dependencies:
+ websocket-driver: 0.7.4
+
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
@@ -9575,6 +10783,11 @@ snapshots:
entities: 7.0.1
fast-xml-parser: 5.3.7
+ fetch-blob@3.2.0:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+
file-entry-cache@6.0.1:
dependencies:
flat-cache: 3.2.0
@@ -9603,6 +10816,58 @@ snapshots:
locate-path: 6.0.0
path-exists: 4.0.0
+ firebase-admin@13.7.0:
+ dependencies:
+ '@fastify/busboy': 3.2.0
+ '@firebase/database-compat': 2.1.1
+ '@firebase/database-types': 1.0.17
+ farmhash-modern: 1.1.0
+ fast-deep-equal: 3.1.3
+ google-auth-library: 10.6.1
+ jsonwebtoken: 9.0.3
+ jwks-rsa: 3.2.2
+ node-forge: 1.3.3
+ uuid: 11.1.0
+ optionalDependencies:
+ '@google-cloud/firestore': 7.11.6
+ '@google-cloud/storage': 7.19.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ firebase@12.10.0:
+ dependencies:
+ '@firebase/ai': 2.9.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)
+ '@firebase/analytics': 0.10.20(@firebase/app@0.14.9)
+ '@firebase/analytics-compat': 0.2.26(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/app': 0.14.9
+ '@firebase/app-check': 0.11.1(@firebase/app@0.14.9)
+ '@firebase/app-check-compat': 0.4.1(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/app-compat': 0.5.9
+ '@firebase/app-types': 0.9.3
+ '@firebase/auth': 1.12.1(@firebase/app@0.14.9)
+ '@firebase/auth-compat': 0.6.3(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)
+ '@firebase/data-connect': 0.4.0(@firebase/app@0.14.9)
+ '@firebase/database': 1.1.1
+ '@firebase/database-compat': 2.1.1
+ '@firebase/firestore': 4.12.0(@firebase/app@0.14.9)
+ '@firebase/firestore-compat': 0.4.6(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)
+ '@firebase/functions': 0.13.2(@firebase/app@0.14.9)
+ '@firebase/functions-compat': 0.4.2(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/installations': 0.6.20(@firebase/app@0.14.9)
+ '@firebase/installations-compat': 0.2.20(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)
+ '@firebase/messaging': 0.12.24(@firebase/app@0.14.9)
+ '@firebase/messaging-compat': 0.2.24(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/performance': 0.7.10(@firebase/app@0.14.9)
+ '@firebase/performance-compat': 0.2.23(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/remote-config': 0.8.1(@firebase/app@0.14.9)
+ '@firebase/remote-config-compat': 0.2.22(@firebase/app-compat@0.5.9)(@firebase/app@0.14.9)
+ '@firebase/storage': 0.14.1(@firebase/app@0.14.9)
+ '@firebase/storage-compat': 0.4.1(@firebase/app-compat@0.5.9)(@firebase/app-types@0.9.3)(@firebase/app@0.14.9)
+ '@firebase/util': 1.14.0
+ transitivePeerDependencies:
+ - '@react-native-async-storage/async-storage'
+
fix-dts-default-cjs-exports@1.0.1:
dependencies:
magic-string: 0.30.21
@@ -9628,6 +10893,21 @@ snapshots:
dependencies:
is-callable: 1.2.7
+ foreground-child@3.3.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
+
+ form-data@2.5.5:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+ safe-buffer: 5.2.1
+ optional: true
+
form-data@4.0.5:
dependencies:
asynckit: 0.4.0
@@ -9636,6 +10916,10 @@ snapshots:
hasown: 2.0.2
mime-types: 2.1.35
+ formdata-polyfill@4.0.10:
+ dependencies:
+ fetch-blob: 3.2.0
+
forwarded-parse@2.1.2: {}
forwarded@0.2.0: {}
@@ -9670,12 +10954,56 @@ snapshots:
hasown: 2.0.2
is-callable: 1.2.7
+ functional-red-black-tree@1.0.1:
+ optional: true
+
functions-have-names@1.2.3: {}
+ gaxios@6.7.1:
+ dependencies:
+ extend: 3.0.2
+ https-proxy-agent: 7.0.6
+ is-stream: 2.0.1
+ node-fetch: 2.7.0
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ gaxios@7.1.3:
+ dependencies:
+ extend: 3.0.2
+ https-proxy-agent: 7.0.6
+ node-fetch: 3.3.2
+ rimraf: 5.0.10
+ transitivePeerDependencies:
+ - supports-color
+
+ gcp-metadata@6.1.1:
+ dependencies:
+ gaxios: 6.7.1
+ google-logging-utils: 0.0.2
+ json-bigint: 1.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ gcp-metadata@8.1.2:
+ dependencies:
+ gaxios: 7.1.3
+ google-logging-utils: 1.1.3
+ json-bigint: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
generator-function@2.0.1: {}
gensync@1.0.0-beta.2: {}
+ get-caller-file@2.0.5: {}
+
get-func-name@2.0.2: {}
get-intrinsic@1.3.0:
@@ -9720,6 +11048,15 @@ snapshots:
glob-to-regexp@0.4.1: {}
+ glob@10.5.0:
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 3.4.3
+ minimatch: 9.0.5
+ minipass: 7.1.3
+ package-json-from-dist: 1.0.1
+ path-scurry: 1.11.1
+
glob@13.0.6:
dependencies:
minimatch: 10.2.2
@@ -9757,12 +11094,69 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
+ google-auth-library@10.6.1:
+ dependencies:
+ base64-js: 1.5.1
+ ecdsa-sig-formatter: 1.0.11
+ gaxios: 7.1.3
+ gcp-metadata: 8.1.2
+ google-logging-utils: 1.1.3
+ jws: 4.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ google-auth-library@9.15.1:
+ dependencies:
+ base64-js: 1.5.1
+ ecdsa-sig-formatter: 1.0.11
+ gaxios: 6.7.1
+ gcp-metadata: 6.1.1
+ gtoken: 7.1.0
+ jws: 4.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ google-gax@4.6.1:
+ dependencies:
+ '@grpc/grpc-js': 1.14.3
+ '@grpc/proto-loader': 0.7.15
+ '@types/long': 4.0.2
+ abort-controller: 3.0.0
+ duplexify: 4.1.3
+ google-auth-library: 9.15.1
+ node-fetch: 2.7.0
+ object-hash: 3.0.0
+ proto3-json-serializer: 2.0.2
+ protobufjs: 7.5.4
+ retry-request: 7.0.2
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ google-logging-utils@0.0.2:
+ optional: true
+
+ google-logging-utils@1.1.3: {}
+
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
graphemer@1.4.0: {}
+ gtoken@7.1.0:
+ dependencies:
+ gaxios: 6.7.1
+ jws: 4.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@@ -9812,6 +11206,17 @@ snapshots:
statuses: 2.0.2
toidentifier: 1.0.1
+ http-parser-js@0.5.10: {}
+
+ http-proxy-agent@5.0.0:
+ dependencies:
+ '@tootallnate/once': 2.0.0
+ agent-base: 6.0.2
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
@@ -9819,6 +11224,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
human-signals@5.0.0: {}
iceberg-js@0.8.1: {}
@@ -9831,6 +11243,8 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
+ idb@7.1.1: {}
+
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -9916,6 +11330,8 @@ snapshots:
dependencies:
call-bound: 1.0.4
+ is-fullwidth-code-point@3.0.0: {}
+
is-generator-function@1.1.2:
dependencies:
call-bound: 1.0.4
@@ -9960,6 +11376,9 @@ snapshots:
dependencies:
call-bound: 1.0.4
+ is-stream@2.0.1:
+ optional: true
+
is-stream@3.0.0: {}
is-string@1.1.1:
@@ -10001,6 +11420,12 @@ snapshots:
has-symbols: 1.1.0
set-function-name: 2.0.2
+ jackspeak@3.4.3:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
jest-worker@27.5.1:
dependencies:
'@types/node': 22.19.11
@@ -10009,6 +11434,8 @@ snapshots:
jiti@2.6.1: {}
+ jose@4.15.9: {}
+
joycon@3.1.1: {}
js-tokens@4.0.0: {}
@@ -10021,6 +11448,10 @@ snapshots:
jsesc@3.1.0: {}
+ json-bigint@1.0.0:
+ dependencies:
+ bignumber.js: 9.3.1
+
json-buffer@3.0.1: {}
json-parse-even-better-errors@2.3.1: {}
@@ -10037,6 +11468,19 @@ snapshots:
json5@2.2.3: {}
+ jsonwebtoken@9.0.3:
+ dependencies:
+ jws: 4.0.1
+ lodash.includes: 4.3.0
+ lodash.isboolean: 3.0.3
+ lodash.isinteger: 4.0.4
+ lodash.isnumber: 3.0.3
+ lodash.isplainobject: 4.0.6
+ lodash.isstring: 4.0.1
+ lodash.once: 4.1.1
+ ms: 2.1.3
+ semver: 7.7.3
+
jsx-ast-utils@3.3.5:
dependencies:
array-includes: 3.1.9
@@ -10044,6 +11488,27 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
+ jwa@2.0.1:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+
+ jwks-rsa@3.2.2:
+ dependencies:
+ '@types/jsonwebtoken': 9.0.10
+ debug: 4.4.3
+ jose: 4.15.9
+ limiter: 1.1.5
+ lru-memoizer: 2.3.0
+ transitivePeerDependencies:
+ - supports-color
+
+ jws@4.0.1:
+ dependencies:
+ jwa: 2.0.1
+ safe-buffer: 5.2.1
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -10110,6 +11575,8 @@ snapshots:
lilconfig@3.1.3: {}
+ limiter@1.1.5: {}
+
lines-and-columns@1.2.4: {}
linkify-it@5.0.0:
@@ -10131,12 +11598,32 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ lodash.camelcase@4.3.0: {}
+
+ lodash.clonedeep@4.5.0: {}
+
+ lodash.includes@4.3.0: {}
+
+ lodash.isboolean@3.0.3: {}
+
+ lodash.isinteger@4.0.4: {}
+
+ lodash.isnumber@3.0.3: {}
+
+ lodash.isplainobject@4.0.6: {}
+
+ lodash.isstring@4.0.1: {}
+
lodash.merge@4.6.2: {}
+ lodash.once@4.1.1: {}
+
lodash.snakecase@4.1.1: {}
lodash@4.17.21: {}
+ long@5.3.2: {}
+
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
@@ -10151,12 +11638,23 @@ snapshots:
devlop: 1.1.0
highlight.js: 11.11.1
+ lru-cache@10.4.3: {}
+
lru-cache@11.2.6: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
+ lru-cache@6.0.0:
+ dependencies:
+ yallist: 4.0.0
+
+ lru-memoizer@2.3.0:
+ dependencies:
+ lodash.clonedeep: 4.5.0
+ lru-cache: 6.0.0
+
lucide-react@0.575.0(react@19.2.4):
dependencies:
react: 19.2.4
@@ -10207,6 +11705,9 @@ snapshots:
dependencies:
mime-db: 1.54.0
+ mime@3.0.0:
+ optional: true
+
mimic-fn@4.0.0: {}
minimatch@10.2.2:
@@ -10293,6 +11794,8 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
+ node-domexception@1.0.0: {}
+
node-exports-info@1.6.0:
dependencies:
array.prototype.flatmap: 1.3.3
@@ -10304,6 +11807,14 @@ snapshots:
dependencies:
whatwg-url: 5.0.0
+ node-fetch@3.3.2:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
+ node-forge@1.3.3: {}
+
node-releases@2.0.27: {}
non-error@0.1.0: {}
@@ -10318,6 +11829,9 @@ snapshots:
object-assign@4.1.1: {}
+ object-hash@3.0.0:
+ optional: true
+
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -10401,6 +11915,8 @@ snapshots:
dependencies:
p-limit: 3.1.0
+ package-json-from-dist@1.0.1: {}
+
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
@@ -10430,6 +11946,11 @@ snapshots:
path-parse@1.0.7: {}
+ path-scurry@1.11.1:
+ dependencies:
+ lru-cache: 10.4.3
+ minipass: 7.1.3
+
path-scurry@2.0.2:
dependencies:
lru-cache: 11.2.6
@@ -10708,6 +12229,26 @@ snapshots:
prosemirror-state: 1.4.4
prosemirror-transform: 1.11.0
+ proto3-json-serializer@2.0.2:
+ dependencies:
+ protobufjs: 7.5.4
+ optional: true
+
+ protobufjs@7.5.4:
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/base64': 1.1.2
+ '@protobufjs/codegen': 2.0.4
+ '@protobufjs/eventemitter': 1.1.0
+ '@protobufjs/fetch': 1.1.0
+ '@protobufjs/float': 1.0.2
+ '@protobufjs/inquire': 1.1.0
+ '@protobufjs/path': 1.1.2
+ '@protobufjs/pool': 1.1.0
+ '@protobufjs/utf8': 1.1.0
+ '@types/node': 22.19.11
+ long: 5.3.2
+
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@@ -10789,6 +12330,13 @@ snapshots:
react@19.2.4: {}
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+ optional: true
+
readdirp@4.1.2: {}
real-require@0.2.0: {}
@@ -10813,6 +12361,8 @@ snapshots:
gopd: 1.2.0
set-function-name: 2.0.2
+ require-directory@2.1.1: {}
+
require-from-string@2.0.2: {}
require-in-the-middle@8.0.1:
@@ -10843,12 +12393,29 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ retry-request@7.0.2:
+ dependencies:
+ '@types/request': 2.48.13
+ extend: 3.0.2
+ teeny-request: 9.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ retry@0.13.1:
+ optional: true
+
reusify@1.1.0: {}
rimraf@3.0.2:
dependencies:
glob: 7.2.3
+ rimraf@5.0.10:
+ dependencies:
+ glob: 10.5.0
+
rollup@4.53.3:
dependencies:
'@types/estree': 1.0.8
@@ -10901,6 +12468,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
+ safe-buffer@5.2.1: {}
+
safe-push-apply@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -11096,6 +12665,26 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
+ stream-events@1.0.5:
+ dependencies:
+ stubs: 3.0.0
+ optional: true
+
+ stream-shift@1.0.3:
+ optional: true
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string-width@5.1.2:
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.2.0
+
string.prototype.includes@2.0.1:
dependencies:
call-bind: 1.0.8
@@ -11146,10 +12735,19 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+ optional: true
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
+ strip-ansi@7.2.0:
+ dependencies:
+ ansi-regex: 6.2.2
+
strip-bom@3.0.0: {}
strip-final-newline@3.0.0: {}
@@ -11164,6 +12762,9 @@ snapshots:
strnum@2.1.2: {}
+ stubs@3.0.0:
+ optional: true
+
styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4):
dependencies:
client-only: 0.0.1
@@ -11199,6 +12800,18 @@ snapshots:
tapable@2.3.0: {}
+ teeny-request@9.0.0:
+ dependencies:
+ http-proxy-agent: 5.0.0
+ https-proxy-agent: 5.0.1
+ node-fetch: 2.7.0
+ stream-events: 1.0.5
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
terser-webpack-plugin@5.4.0(webpack@5.105.4):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -11449,6 +13062,11 @@ snapshots:
util-deprecate@1.0.2: {}
+ uuid@11.1.0: {}
+
+ uuid@8.3.2:
+ optional: true
+
uuid@9.0.1: {}
vary@1.1.2: {}
@@ -11595,6 +13213,10 @@ snapshots:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.11
+ web-streams-polyfill@3.3.3: {}
+
+ web-vitals@4.2.4: {}
+
webidl-conversions@3.0.1: {}
webpack-sources@3.3.4: {}
@@ -11631,6 +13253,14 @@ snapshots:
- esbuild
- uglify-js
+ websocket-driver@0.7.4:
+ dependencies:
+ http-parser-js: 0.5.10
+ safe-buffer: 5.2.1
+ websocket-extensions: 0.1.4
+
+ websocket-extensions@0.1.4: {}
+
whatwg-encoding@3.1.1:
dependencies:
iconv-lite: 0.6.3
@@ -11694,14 +13324,42 @@ snapshots:
word-wrap@1.2.5: {}
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@8.1.0:
+ dependencies:
+ ansi-styles: 6.2.3
+ string-width: 5.1.2
+ strip-ansi: 7.2.0
+
wrappy@1.0.2: {}
ws@8.18.3: {}
xtend@4.0.2: {}
+ y18n@5.0.8: {}
+
yallist@3.1.1: {}
+ yallist@4.0.0: {}
+
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
yocto-queue@0.1.0: {}
yocto-queue@1.2.2: {}