From 4f57df81017cd9c881e330a8b45f7285dcc70680 Mon Sep 17 00:00:00 2001 From: c-d-p Date: Mon, 21 Apr 2025 20:09:41 +0200 Subject: [PATCH] [V0.3] Working dashboard calendar module --- .../core/__pycache__/config.cpython-312.pyc | Bin 1083 -> 1083 bytes backend/core/config.py | 1 + .../auth/__pycache__/api.cpython-312.pyc | Bin 4708 -> 4396 bytes .../auth/__pycache__/schemas.cpython-312.pyc | Bin 1904 -> 2240 bytes .../auth/__pycache__/security.cpython-312.pyc | Bin 8548 -> 8548 bytes backend/modules/auth/api.py | 28 +- backend/modules/auth/schemas.py | 6 + backend/modules/auth/security.py | 1 + interfaces/nativeapp/src/api/calendar.ts | 1 + interfaces/nativeapp/src/api/client.ts | 176 +- .../nativeapp/src/contexts/AuthContext.tsx | 167 +- .../nativeapp/src/screens/ChatScreen.tsx | 241 +- .../nativeapp/src/screens/DashboardScreen.tsx | 210 +- package-lock.json | 4859 +++++++++++++++++ package.json | 5 + 15 files changed, 5401 insertions(+), 294 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json diff --git a/backend/core/__pycache__/config.cpython-312.pyc b/backend/core/__pycache__/config.cpython-312.pyc index 72ecfb17e51331b720f3c4e7ca5f80dc5ac76686..fd74792d2af74f79a1c5bef5949f7c6b0d44ae39 100644 GIT binary patch delta 53 zcmdnZv73YUG%qg~0}!0=WXq`A$Q!`S_+WAz^HB*tM)QuEFAPBHqXGkuNVioZN0BU0 F9RQSL4jcdg delta 53 zcmdnZv73YUG%qg~0}yP}VaN#H$Q!`Scw=%L^HB+2M)QuEFAPBHqZ|W|NVioZN0BU0 F9RPYQ4QT)X diff --git a/backend/core/config.py b/backend/core/config.py index 392a083..a0794b9 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -13,6 +13,7 @@ class Settings(BaseSettings): JWT_ALGORITHM: str = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES: int = 30 + # ACCESS_TOKEN_EXPIRE_MINUTES: int = 1 REFRESH_TOKEN_EXPIRE_DAYS: int = 7 PEPPER: str = getenv("PEPPER", "") diff --git a/backend/modules/auth/__pycache__/api.cpython-312.pyc b/backend/modules/auth/__pycache__/api.cpython-312.pyc index e50b60104cee8eb4d93f4fbc15164ae8d0a61d22..f8f5808f507a39ac18669bce5685df9c42e57675 100644 GIT binary patch delta 2186 zcmaJ>U2M}<6!x{9|D@?(XxgT&(>A1TX$k{M`5%IIw4*$DsCXl5eP17{qHkBc!y%e#BO%oE*UL2K;Vxei$`o5HEFMHa(*GUH&>`Fd9|Gwut z=XkmOc5C!!pU=(Uv*nb1@~D?#{vbm6V40rPPj5uW8kK6PTB(t003$Q9Jzc8=qyXg| z=^MA|^GcJ{q%=#-ROL*!D1szV-jxn3tx~JfCbd!7oo-hmQiSrJ^m-*KMJex1cPOGH zQr?&DRJx=tz_1Jia)s=l0JkgWS?fB|2DoABWa)0@mj^R)6|97|sZ;tc(B^7|0uJV2 zM4tprwjL6qUjuFVR_G%7`BGq#ttXMSaLs=nSSHJoxbP_=a+n+z6}x zFI!#?J(q6NE7CQU)6o*@%Tf~H^fj+eFE`^dd^9Gw7Go9I0$)oyW#Nk7wpPpLnXuTZ zn`|D~bcqYMn>8aaiJ&@pBzqQSM&P+=sA{I~P=~ecav;Sp6&e zsGrjUmL7x3VT;=luHxsoIbL?i&d<3~Ms&@-p?~J+TBi!BjG#?I0bewh}7_HV_BO#3*DBZx%K^u`kjsH$Tcsm}BvtJad}rrI%WCI>|iA|ru13F*>r zJ0qTTgl!>2(4RWPuh(H#w4see(?JM@Vmsk>V4~VE5y(N^m@{qZ>_jSq_F$f5Qa{mi zuJe%-m$O(xhUjK)Kz3 znPaA&2cFTtaDSVhE%!E+nGk5Lu~=+2Qfj!R5tNjw530QimX`!FXmuEgR%t| z#ferv8yL)-kEc^Ij-az+r9zwW1<^J_`Y;g(SwzvRNMHtRxH$t zmxrHtf=?^jjmV+JiebY!yj&U5&v?UQ%XOW10}HOleM5!5A!Fm4kLnH?eC<+b!@|LW zr{CcFt&TW)aP#o|o8H7ULNKF^O{);mY7#vDX8EkO<{H-AWL$dIUDtexpW{`JR+{wZ z+w>mLY`WLiz{{M>>xX@H$NqJ)m3#RfxWHWGPB0gMXg@p~eX&`YtR^J0(;4|c?cyw~ z2{d>;7ku0Dl%+s75GDCnzJTfg(Y|tg?G^%P5POlGQYB0-GezEK>s<=AJPvjjg56hr zPyC^$)g6X7vRFN8ct@9=!KM1hQbTmf@2UFB!Mof=FH_Z^e^eoQI=h)~0{d9*u((D4 zzT)HEsFGZu3KKJ+Waa5JRAcdJZ8ChB{!yQR!Gx`VqW{0)14f-vA?U_d6 zYsagMXBmY^<|d-?C9(*{$d73}j`KDXofC^tODT|Ux9OoSiEJjBnm__^@KX)En1DGg zg?}`r!7y`$$UL%jS8BkR{I zZ{#b$IJkboXz9Bby)POq`wM{sMTRIJipG(Xh10SD&n})$8%NTGA>|phta1$7U1W(< zQD9i-hmG$xUX>O>u*iDA05BS3MTRhU2Nx!Oyzub+PkCd{TZJvho>47{uD3jk4NSfi zeqs^St+32VcAPCTOoGj^s|=RTu`BqKz1N4yoqE5Vxm$NH`osGBJ;tWNLUf2K4Jl#B vlZB~sI8FuoN!(d*fMkLAwSu#Nek|c|tUAgbXGsygme?<)5 delta 2659 zcmZ`)U2Gf25#GDwk;h+27HN{EekfD2bdD`4Rw6sKT}yVP*s>$nk`hTo8=B!QCCWTf z-aFNjz?e#5Abn_os0YM;C{Xv!hJ?a_U(^-|g8l#v@^XX>NIt}^ff@)3^nw2AOP@Ns zBxTirm*DK&%+BoWd^@x2`=7LTe(UwR5R8Y7X!d&#LjR;6wc)KY&wsbtnTT*mL5e-Q zM{SHZGTxE(tAThx-5X#1ZTJEcN!ez#CEmh#XSP+1#-nOmyp4UkvisFoJjQr;wq5Or zcQD?QJ)m~RI~niIcByh)Hhf&L^&mbtH(3ki<*YQ|dMwUO8Sip2XB4;a2n#r7%yZ4+ zVQOLgii;H;N*G76lj_#0rfEJ5oZ<(0)n<*Ws4AMYUDSDd5yc4nmcxk;I1!TX;q@@ZEJijNF{_FuiFp~wjU1WWnT8K_59z-lo;++ zqPPwB(hQ_sO8X6Q=bUdYwaOjFpZMZ_!E$||VRDAxq>e2Q<;So#pU-L75-0LkaPIzR z!e2SA-gsY(+B?7%IbdkwFn7rKgLr%}1_DbWH4A4tPt=5x)RQTpasoyrp!ECsGK6>& z>D53HDsaZC)6c_HF9y8)TGi+ip&%HFeTWmN+W5+Ts?MedY7P~urSho5TNL&BntX0= zje9vOj%5+jB)z1c*b8WmrsS2OI18fUf}gu!U-zupD{2lEY>HR${hA*~a^3Qqt|*Mb z1$`Fh^h_$L8>5bhQFO>$yK&d?cJVE+`d5gO6F@94!D-0NY(l4roUnuo$wk?230Lrv zCH^#-UBH$!tLu>M?2={IaB6{oL`$kz%K#b4J@kY{aAvx1X}jl(ZP*Qd^N`&IVw5UEMW%gq?KxDwnzgI%TdLL zF!U&zvPed#n!!MmZ#fsBOj(&(^+uOFQl!bR;6n9>;IHL?tf0sK$jytZ7q|SKC4c9g zx=sJFmG>XIL*Mz@&5jeBzLTbO@`W8WG~fEkUz}S5mr4Vd%nzp?)K9ORd+7GRvMTh( zy}*WZ>)1%?*ofJC{z349Y4dM49ojf+eC2kGGdvtUa0BuS`Y4M=<}4AilGH2@Tx|k1 zlc13kdW}*Po7&jH=?jqDgnL}DX>Oe}+B|{c4mbs&U@LIzJ6!^56V2`RQuU??>$X}; zh4)2N>=|wx#gJaDX@uGl@o>A^km9JV{~31;Eeg}<8YfGm%RxZhSoQe#$pVYHlHwg4 zWR4s+{_HtgWDwG_x4a6@VjWkjh`2!p@Uc>2X5%1u=}M!~?u(Y}k@oN>a=1Q>N7N zKx*r&n1o?=u;r*p?(HAPxu4x6-yt0tRT6YpUS~u%I8GVV}L$U`J zkVZ<_MWnr>a!Z4hV~6!=SF_1%Y8I|U+F~UU_T_Z-05qh{Tpam;5hDkG_{4MN@(g4>VJg7k5KzR&_D?d7+=(_ z78|+K+~;S@h|YJyX5WQxX1>jseUl}5sv%N!VU6egfcKaMJU0Y z=ASX!=K|snmwD=@d=T-{XOT}MKaX#6p)&8`hPhiu%ZSc*ocB6^fAs7AKb|s=jFh_0 z7oRaPwGLNSmYZtU)0~SX~fe#xkbYpryy7iS^Uq*h@d9Y{y&s8EH`o2o|oZP(WPYg zWoH_)tGrk%-iGf5TjgrS+gb7U>RwRub)2Jg1yP!ZeTA`)UR)oOjy3p92jN1=i2Sg~ zv!&{0wO;#|^lf;emOX+gpNq*&ic4G|kd=nxaLXlu6+}>)q!Y0Y7CL?A;XJI-4BRVa zx!VgWsy>$F2YD|XC2Afmcg0}MVz=)&Tq-u~(^)ACcXR-Cn5K;!27E4Qc%zP#1J-kd zTVc=1*c8$%R-mEa?J4Ip)@@ZlP;xbh(Ud9%E$|l^dBi@K4Aj*rjk}T?g==+kln*B! s>oe{|Xq-E7e;!`dv@wHg2`ktJOUorCY3SVjB>4MOQO=4#9_F;!Z$m|N{Qv*} delta 327 zcmX>g_<@i2G%qg~0}!11`aivPBCjOlqKWDuhU}?Kt64z83=B~mObqS}DV!|~DO{;6 ztC^vqoM2IIpePSWbmAI0mP&q2fsMahm?np@WKLeq%qvmM1616?aDzv*lk3D_IzWHkS*VurQWvUL)?z u!Z=~`2Wd_w#$}s-$H)WalwSa5J*aNcq43q&8UYD7k3t{29dlC^dP5!WIA@&K-RK diff --git a/backend/modules/auth/api.py b/backend/modules/auth/api.py index d7eea09..696c8c6 100644 --- a/backend/modules/auth/api.py +++ b/backend/modules/auth/api.py @@ -3,7 +3,7 @@ from fastapi import APIRouter, Cookie, Depends, HTTPException, status, Request, from fastapi.security import OAuth2PasswordRequestForm from jose import JWTError from modules.auth.models import User -from modules.auth.schemas import UserCreate, UserResponse, Token +from modules.auth.schemas import UserCreate, UserResponse, Token, RefreshTokenRequest, LogoutRequest from modules.auth.services import create_user from modules.auth.security import TokenType, get_current_user, oauth2_scheme, create_access_token, create_refresh_token, verify_token, authenticate_user, blacklist_tokens from sqlalchemy.orm import Session @@ -20,9 +20,9 @@ def register(user: UserCreate, db: Annotated[Session, Depends(get_db)]): return create_user(user.username, user.password, user.name, db) @router.post("/login", response_model=Token) -def login(response: Response, form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: Annotated[Session, Depends(get_db)]): +def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: Annotated[Session, Depends(get_db)]): """ - Authenticate user and return JWT token. + Authenticate user and return JWT tokens in the response body. """ user = authenticate_user(form_data.username, form_data.password, db) if not user: @@ -34,40 +34,34 @@ def login(response: Response, form_data: Annotated[OAuth2PasswordRequestForm, De access_token = create_access_token(data={"sub": user.username}, expires_delta=timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)) refresh_token = create_refresh_token(data={"sub": user.username}) - max_age = settings.REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60 - - response.set_cookie( - key="refresh_token", value=refresh_token, httponly=True, secure=True, samesite="Lax", max_age=max_age - ) - return {"access_token": access_token, "token_type": "bearer"} + return {"access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer"} @router.post("/refresh") -def refresh_token(request: Request, db: Annotated[Session, Depends(get_db)]): - refresh_token = request.cookies.get("refresh_token") +def refresh_token(payload: RefreshTokenRequest, db: Annotated[Session, Depends(get_db)]): + print("Refreshing token...") + refresh_token = payload.refresh_token if not refresh_token: - raise unauthorized_exception("Refresh token missing") - + raise unauthorized_exception("Refresh token missing in request body") user_data = verify_token(refresh_token, expected_token_type=TokenType.REFRESH, db=db) if not user_data: raise unauthorized_exception("Invalid refresh token") - new_access_token = create_access_token(data={"sub": user_data.username}) return {"access_token": new_access_token, "token_type": "bearer"} @router.post("/logout") -def logout(response: Response, db: Annotated[Session, Depends(get_db)], current_user: Annotated[User, Depends(get_current_user)], access_token: str = Depends(oauth2_scheme), refresh_token: Optional[str] = Cookie(None, alias="refresh_token")): +def logout(payload: LogoutRequest, db: Annotated[Session, Depends(get_db)], current_user: Annotated[User, Depends(get_current_user)], access_token: str = Depends(oauth2_scheme)): try: + refresh_token = payload.refresh_token if not refresh_token: - raise unauthorized_exception("Refresh token not found") + raise unauthorized_exception("Refresh token not found in request body") blacklist_tokens( access_token=access_token, refresh_token=refresh_token, db=db ) - response.delete_cookie(key="refresh_token") return {"message": "Logged out successfully"} except JWTError: diff --git a/backend/modules/auth/schemas.py b/backend/modules/auth/schemas.py index 0fdfad6..9668549 100644 --- a/backend/modules/auth/schemas.py +++ b/backend/modules/auth/schemas.py @@ -11,6 +11,12 @@ class TokenData(BaseModel): username: str | None = None scopes: list[str] = [] +class RefreshTokenRequest(BaseModel): + refresh_token: str + +class LogoutRequest(BaseModel): + refresh_token: str + class UserRole(str, PyEnum): ADMIN = "admin" USER = "user" diff --git a/backend/modules/auth/security.py b/backend/modules/auth/security.py index a14c6cb..521be25 100644 --- a/backend/modules/auth/security.py +++ b/backend/modules/auth/security.py @@ -58,6 +58,7 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None): expire = datetime.now(timezone.utc) + expires_delta else: expire = datetime.now(timezone.utc) + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) + # expire = datetime.now(timezone.utc) + timedelta(seconds=5) to_encode.update({"exp": expire, "token_type": TokenType.ACCESS}) return jwt.encode( to_encode, diff --git a/interfaces/nativeapp/src/api/calendar.ts b/interfaces/nativeapp/src/api/calendar.ts index 7e9bb64..9a72d49 100644 --- a/interfaces/nativeapp/src/api/calendar.ts +++ b/interfaces/nativeapp/src/api/calendar.ts @@ -3,6 +3,7 @@ import apiClient from './client'; import { CalendarEvent, CalendarEventCreate, CalendarEventUpdate } from '../types/calendar'; export const getCalendarEvents = async (start?: Date, end?: Date): Promise => { + console.log(`Getting calendar events from ${start} - ${end}`); try { const params: Record = {}; if (start instanceof Date) { diff --git a/interfaces/nativeapp/src/api/client.ts b/interfaces/nativeapp/src/api/client.ts index d8b279b..5999b98 100644 --- a/interfaces/nativeapp/src/api/client.ts +++ b/interfaces/nativeapp/src/api/client.ts @@ -8,13 +8,35 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://192.168.255.221:8000/api'; // Use your machine's IP // const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://192.168.1.9:8000/api'; // Use your machine's IP // const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://localhost:8000/api'; // Use your machine's IP -const TOKEN_KEY = 'maia_access_token'; +const ACCESS_TOKEN_KEY = 'maia_access_token'; // Renamed for clarity +const REFRESH_TOKEN_KEY = 'maia_refresh_token'; // Key for refresh token console.log("Using API Base URL:", API_BASE_URL); -// Helper functions for storage (assuming they are defined above or imported) -// const getToken = async (): Promise => { ... }; -// const deleteToken = async () => { ... }; +// Helper functions for storage +const storeToken = async (key: string, token: string): Promise => { + if (Platform.OS === 'web') { + await AsyncStorage.setItem(key, token); + } else { + await SecureStore.setItemAsync(key, token); + } +}; + +const getToken = async (key: string): Promise => { + if (Platform.OS === 'web') { + return await AsyncStorage.getItem(key); + } else { + return await SecureStore.getItemAsync(key).catch(() => null); + } +}; + +const deleteToken = async (key: string): Promise => { + if (Platform.OS === 'web') { + await AsyncStorage.removeItem(key); + } else { + await SecureStore.deleteItemAsync(key).catch(() => {}); // Ignore delete error + } +}; const apiClient = axios.create({ @@ -23,16 +45,14 @@ const apiClient = axios.create({ 'Content-Type': 'application/json', }, timeout: 10000, - ...(Platform.OS === 'web' ? { withCredentials: true } : {}), + // Remove withCredentials from default config if not needed globally + // ...(Platform.OS === 'web' ? { withCredentials: true } : {}), }); -// --- Request Interceptor remains the same --- +// --- Request Interceptor --- apiClient.interceptors.request.use( async (config) => { - // Using AsyncStorage for web token retrieval here too for consistency - const token = Platform.OS === 'web' - ? await AsyncStorage.getItem(TOKEN_KEY) - : await SecureStore.getItemAsync(TOKEN_KEY).catch(() => null); // Handle potential SecureStore error + const token = await getToken(ACCESS_TOKEN_KEY); // Use helper if (token) { config.headers.Authorization = `Bearer ${token}`; @@ -46,7 +66,6 @@ apiClient.interceptors.request.use( } ); - // --- Modified Response Interceptor --- apiClient.interceptors.response.use( (response) => { @@ -56,105 +75,126 @@ apiClient.interceptors.response.use( async (error: AxiosError) => { // Explicitly type error as AxiosError const originalRequest = error.config; - // Check if the error has a response object AND an original request config - if (error.response && originalRequest) { // <-- Added check for originalRequest - // Server responded with an error status code (4xx, 5xx) + if (error.response && originalRequest) { console.error('[API Client] Response Error Status:', error.response.status); console.error('[API Client] Response Error Data:', error.response.data); - // Handle 401 specifically if (error.response.status === 401) { console.warn('[API Client] Unauthorized (401). Token might be expired or invalid.'); + // Prevent refresh loops if the refresh endpoint itself returns 401 if (originalRequest.url === '/auth/refresh') { - console.error('[API Client] Refresh token attempt failed with 401. Not retrying.'); - // Clear token and reject without retry - if (Platform.OS === 'web') { - await AsyncStorage.removeItem(TOKEN_KEY); - } else { - await SecureStore.deleteItemAsync(TOKEN_KEY).catch(() => {}); // Ignore delete error - } + console.error('[API Client] Refresh token attempt failed with 401. Clearing tokens.'); + await deleteToken(ACCESS_TOKEN_KEY); + await deleteToken(REFRESH_TOKEN_KEY); // Clear refresh token too delete apiClient.defaults.headers.common['Authorization']; - return Promise.reject(error); // Reject immediately + // TODO: Trigger logout flow in UI + return Promise.reject(error); } - // Proceed with refresh logic only if it wasn't the refresh endpoint that failed - // and if originalRequest exists (already checked above) - if (!originalRequest._retry) { // Now TS knows _retry exists due to declaration file - originalRequest._retry = true; + // Check if we haven't already tried to refresh for this request + // Need to declare _retry on AxiosRequestConfig interface or use a different check + // Using a simple check here, consider a more robust solution if needed + if (!(originalRequest as any)._retry) { + (originalRequest as any)._retry = true; try { + const storedRefreshToken = await getToken(REFRESH_TOKEN_KEY); + if (!storedRefreshToken) { + console.error('[API Client] No refresh token found to attempt refresh.'); + await deleteToken(ACCESS_TOKEN_KEY); // Clear potentially invalid access token + // TODO: Trigger logout flow in UI + return Promise.reject(error); // Reject if no refresh token + } + console.log('[API Client] Attempting token refresh...'); - const refreshResponse = await apiClient.post('/auth/refresh', {}, { - headers: { - 'Content-Type': 'application/json', - }, - }); + // Send refresh token in the body, remove withCredentials + const refreshResponse = await apiClient.post('/auth/refresh', + { refresh_token: storedRefreshToken }, // Send token in body + { + // No withCredentials needed + headers: { 'Content-Type': 'application/json' }, + } + ); - if (refreshResponse.status === 200) { - const newToken = refreshResponse.data?.access_token; + if (refreshResponse.status === 200) { + const newAccessToken = refreshResponse.data?.access_token; // Expecting only access token - if (newToken) { + if (newAccessToken) { console.log('[API Client] Token refreshed successfully.'); - // Save the new token - if (Platform.OS === 'web') { - await AsyncStorage.setItem(TOKEN_KEY, newToken); - } else { - await SecureStore.setItemAsync(TOKEN_KEY, newToken); - } + await storeToken(ACCESS_TOKEN_KEY, newAccessToken); // Store new access token - // Update the Authorization header for future requests - apiClient.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; - // Safely update original request headers + // Update the default Authorization header for subsequent requests + apiClient.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`; + + // Update the Authorization header in the original request config if (originalRequest.headers) { - originalRequest.headers['Authorization'] = `Bearer ${newToken}`; + originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`; } - // Retry the original request (originalRequest is guaranteed to exist here) + // Retry the original request with the new access token return apiClient(originalRequest); } else { console.error('[API Client] Invalid token structure received during refresh:', refreshResponse.data); - throw new Error('Invalid token received from server.'); + throw new Error('Invalid access token received from server during refresh.'); } + } else { + // Handle non-200 responses from refresh endpoint if necessary + console.error(`[API Client] Token refresh endpoint returned status ${refreshResponse.status}`); + throw new Error(`Refresh failed with status ${refreshResponse.status}`); } } catch (refreshError: any) { console.error('[API Client] Token refresh failed:', refreshError); + // Clear tokens if refresh fails + await deleteToken(ACCESS_TOKEN_KEY); + await deleteToken(REFRESH_TOKEN_KEY); + delete apiClient.defaults.headers.common['Authorization']; + // TODO: Trigger logout flow in UI + // Propagate the refresh error instead of the original 401 + return Promise.reject(refreshError); } + } else { + console.warn('[API Client] Already retried this request. Not attempting refresh again.'); } - // Clear potentially invalid token due to 401 - console.log('[API Client] Clearing potentially invalid token due to 401.'); - if (Platform.OS === 'web') { - await AsyncStorage.removeItem(TOKEN_KEY); - } else { - await SecureStore.deleteItemAsync(TOKEN_KEY).catch(() => {}); // Ignore delete error - } + // If retry flag was already set, or if refresh attempt failed and fell through, + // we might still end up here. Ensure tokens are cleared if a 401 persists. + console.log('[API Client] Clearing tokens due to persistent 401 or failed refresh.'); + await deleteToken(ACCESS_TOKEN_KEY); + await deleteToken(REFRESH_TOKEN_KEY); delete apiClient.defaults.headers.common['Authorization']; + // TODO: Trigger logout flow in UI - // How to trigger logout? Propagating error is simplest for now. - } + } // End of 401 handling } else if (error.request) { - // The request was made but no response was received - // (e.g., network error, CORS block preventing response reading, server timeout) console.error('[API Client] Network Error or No Response:', error.message); - // Log the request object for debugging if needed - // console.error('[API Client] Error Request Object:', error.request); - // If CORS is suspected, this is often where the error ends up. if (error.message.toLowerCase().includes('network error') && Platform.OS === 'web') { console.warn('[API Client] Hint: A "Network Error" on web often masks a CORS issue. Check browser console & backend CORS config.'); } - } else { - // Something happened in setting up the request that triggered an Error console.error('[API Client] Request Setup Error (Interceptor):', error.message); } - // Log the config that failed (optional, can be verbose) - // console.error("[API Client] Failing Request Config:", error.config); - - // Always reject the promise to propagate the error return Promise.reject(error); } ); -export default apiClient; \ No newline at end of file +export default apiClient; + +// Add functions to manage tokens globally if needed by UI components +export const storeTokens = async (accessToken: string, refreshToken?: string) => { + await storeToken(ACCESS_TOKEN_KEY, accessToken); + if (refreshToken) { + await storeToken(REFRESH_TOKEN_KEY, refreshToken); + } + apiClient.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`; // Update client instance +}; + +export const clearTokens = async () => { + await deleteToken(ACCESS_TOKEN_KEY); + await deleteToken(REFRESH_TOKEN_KEY); + delete apiClient.defaults.headers.common['Authorization']; // Clear client instance header +}; + +export const getRefreshToken = () => getToken(REFRESH_TOKEN_KEY); +export const getAccessToken = () => getToken(ACCESS_TOKEN_KEY); \ No newline at end of file diff --git a/interfaces/nativeapp/src/contexts/AuthContext.tsx b/interfaces/nativeapp/src/contexts/AuthContext.tsx index a0bcc6e..5529d4f 100644 --- a/interfaces/nativeapp/src/contexts/AuthContext.tsx +++ b/interfaces/nativeapp/src/contexts/AuthContext.tsx @@ -1,15 +1,11 @@ // src/contexts/AuthContext.tsx import React, { createContext, useState, useEffect, useContext, useMemo, useCallback } from 'react'; import { Platform, ActivityIndicator, View, StyleSheet } from 'react-native'; // Import Platform -import * as SecureStore from 'expo-secure-store'; -import AsyncStorage from '@react-native-async-storage/async-storage'; // Use AsyncStorage for web localStorage import apiClient from '../api/client'; import { useTheme } from 'react-native-paper'; - -const TOKEN_KEY = 'maia_access_token'; // Use the same key +import { getAccessToken, getRefreshToken, storeTokens, clearTokens } from '../api/client'; interface AuthContextData { - authToken: string | null; isAuthenticated: boolean; isLoading: boolean; login: (username: string, password: string) => Promise; @@ -17,7 +13,6 @@ interface AuthContextData { } const AuthContext = createContext({ - authToken: null, isAuthenticated: false, isLoading: true, login: async () => { throw new Error('AuthContext not initialized'); }, @@ -28,104 +23,42 @@ interface AuthProviderProps { children: React.ReactNode; } -// Helper functions for platform-specific storage -const storeToken = async (token: string) => { - if (Platform.OS === 'web') { - try { - // Use AsyncStorage for web (polyfilled to localStorage) - await AsyncStorage.setItem(TOKEN_KEY, token); - } catch (e) { - console.error("Failed to save token to web storage", e); - } - } else { - await SecureStore.setItemAsync(TOKEN_KEY, token); - } -}; - -const getToken = async (): Promise => { - if (Platform.OS === 'web') { - try { - return await AsyncStorage.getItem(TOKEN_KEY); - } catch (e) { - console.error("Failed to get token from web storage", e); - return null; - } - } else { - // SecureStore might throw if not available, handle gracefully - try { - return await SecureStore.getItemAsync(TOKEN_KEY); - } catch (e) { - console.error("Failed to get token from secure store", e); - // If SecureStore fails on native, treat as no token found - return null; - } - } -}; - -const deleteToken = async () => { - if (Platform.OS === 'web') { - try { - await AsyncStorage.removeItem(TOKEN_KEY); - } catch (e) { - console.error("Failed to remove token from web storage", e); - } - } else { - // Avoid potential crash if SecureStore is unavailable - try { - await SecureStore.deleteItemAsync(TOKEN_KEY); - } catch (e) { - console.error("Failed to delete token from secure store", e); - } - } -}; - - export const AuthProvider: React.FC = ({ children }) => { - const [authToken, setAuthToken] = useState(null); const [isLoading, setIsLoading] = useState(true); + const [isAuthenticatedState, setIsAuthenticatedState] = useState(false); - const loadToken = useCallback(async () => { - console.log("[AuthContext] loadToken: Starting..."); // Log: Start + const checkAuthStatus = useCallback(async () => { + const token = await getAccessToken(); + const hasToken = !!token; + if (hasToken !== isAuthenticatedState) { + setIsAuthenticatedState(hasToken); + } + return hasToken; + }, [isAuthenticatedState]); + + const loadInitialAuth = useCallback(async () => { setIsLoading(true); try { - console.log("[AuthContext] loadToken: Calling getToken()..."); // Log: Before await - const storedToken = await getToken(); // Use helper - console.log("[AuthContext] loadToken: getToken() returned:", storedToken); // Log: After await - - if (storedToken) { - console.log('[AuthContext] loadToken: Token found. Setting state and headers.'); // Log: Token Found Path - setAuthToken(storedToken); - apiClient.defaults.headers.common['Authorization'] = `Bearer ${storedToken}`; - } else { - console.log('[AuthContext] loadToken: No token found. Clearing state and headers.'); // Log: No Token Path - setAuthToken(null); - delete apiClient.defaults.headers.common['Authorization']; - } - console.log('[AuthContext] loadToken: Try block finished successfully.'); // Log: Try Success + console.log("[AuthContext] loadInitialAuth: Checking initial auth status"); + await checkAuthStatus(); + console.log("[AuthContext] loadInitialAuth: Initial check complete."); } catch (error) { - // **Log the actual error object** - console.error("[AuthContext] loadToken: Caught error:", error); // Log: Catch Block - setAuthToken(null); // Ensure logged out state on error - delete apiClient.defaults.headers.common['Authorization']; + console.error("[AuthContext] loadInitialAuth: Error loading initial token:", error); + await clearTokens(); + setIsAuthenticatedState(false); } finally { - console.log("[AuthContext] loadToken: Entering finally block."); // Log: Finally Start setIsLoading(false); - console.log("[AuthContext] loadToken: setIsLoading(false) called."); // Log: Finally End } - }, []); + }, [checkAuthStatus]); useEffect(() => { - console.log("[AuthContext] useEffect: Component mounted, calling loadToken."); // Log: useEffect call - loadToken(); - }, [loadToken]); + loadInitialAuth(); + }, [loadInitialAuth]); const login = useCallback(async (username: string, password: string) => { - console.log("[AuthContext] login: Function called with:", username); // Log: Function entry + console.log("[AuthContext] login: Function called with:", username); try { console.log("[AuthContext] login: Preparing to call apiClient.post for /auth/login"); - console.log("[AuthContext] login: Data being sent:", { username: username, password: password }); - - // const response = await apiClient.post(`/auth/login?grant_type=password&username=${username}&password=${password}`); const response = await apiClient.post( '/auth/login', 'grant_type=password&username=' + encodeURIComponent(username) + '&password=' + encodeURIComponent(password) + '&scope=&client_id=&client_secret=', @@ -137,53 +70,61 @@ export const AuthProvider: React.FC = ({ children }) => { } ); - console.log("[AuthContext] login: apiClient.post successful, response status:", response?.status); // Log success + console.log("[AuthContext] login: apiClient.post successful, response status:", response?.status); + const { access_token, refresh_token } = response.data; + console.log("[AuthContext] login: Response data received."); - const { access_token } = response.data; - - if (!access_token || typeof access_token !== 'string') { + if (!access_token || typeof access_token !== 'string' || !refresh_token) { console.error("[AuthContext] login: Invalid token structure received:", response.data); throw new Error('Invalid token received from server.'); } - console.log('[AuthContext] login: Login successful, received token.'); - setAuthToken(access_token); - apiClient.defaults.headers.common['Authorization'] = `Bearer ${access_token}`; - await storeToken(access_token); // Use helper + console.log('[AuthContext] login: Login successful, storing tokens.'); + await storeTokens(access_token, refresh_token); + setIsAuthenticatedState(true); } catch (error: any) { - // --- Log the error object *itself* --- console.error("[AuthContext] login: Caught Error Object:", error); - - // --- Check if it's an Axios error with config details --- if (error.isAxiosError) { console.error("[AuthContext] login: Axios Error Details:"); console.error(" Request Config:", error.config); - console.error(" Response:", error.response); // This will likely still be undefined + console.error(" Response:", error.response?.status, error.response?.data); console.error(" Message:", error.message); } - - // Original logging (might be redundant now but keep for context) - console.error("Login failed:", error.response?.data || error.message); - throw error; // Re-throw + await clearTokens(); + setIsAuthenticatedState(false); + throw error; } }, []); const logout = useCallback(async () => { - console.log('Logging out.'); - setAuthToken(null); - delete apiClient.defaults.headers.common['Authorization']; - await deleteToken(); // Use helper - await apiClient.post("/auth/logout"); + console.log('[AuthContext] logout: Logging out.'); + const refreshToken = await getRefreshToken(); + if (!refreshToken) { + console.warn('[AuthContext] logout: No refresh token found to send to backend.'); + } + + try { + if (refreshToken) { + console.log('[AuthContext] logout: Calling backend /auth/logout'); + await apiClient.post("/auth/logout", { refresh_token: refreshToken }); + console.log('[AuthContext] logout: Backend logout call successful (or ignored error).'); + } + } catch (error: any) { + console.error('[AuthContext] logout: Error calling backend logout:', error.response?.data || error.message); + } finally { + await clearTokens(); + setIsAuthenticatedState(false); + console.log('[AuthContext] logout: Local tokens cleared and state updated.'); + } }, []); const contextValue = useMemo(() => ({ - authToken, - isAuthenticated: !!authToken, + isAuthenticated: isAuthenticatedState, isLoading, login, logout, - }), [authToken, isLoading, login, logout]); + }), [isAuthenticatedState, isLoading, login, logout]); return ( diff --git a/interfaces/nativeapp/src/screens/ChatScreen.tsx b/interfaces/nativeapp/src/screens/ChatScreen.tsx index ff1982b..7d179c0 100644 --- a/interfaces/nativeapp/src/screens/ChatScreen.tsx +++ b/interfaces/nativeapp/src/screens/ChatScreen.tsx @@ -1,9 +1,20 @@ // src/screens/ChatScreen.tsx import React, { useState, useCallback, useRef, useEffect } from 'react'; -import { View, StyleSheet, FlatList, KeyboardAvoidingView, Platform, TextInput as RNTextInput, NativeSyntheticEvent, TextInputKeyPressEventData } from 'react-native'; -import { Text, useTheme, TextInput, Button, IconButton, PaperProvider } from 'react-native-paper'; +import { + View, + StyleSheet, + FlatList, + KeyboardAvoidingView, + Platform, + TextInput as RNTextInput, // Keep if needed for specific props, otherwise can remove + NativeSyntheticEvent, + TextInputKeyPressEventData, + ActivityIndicator // Import ActivityIndicator +} from 'react-native'; +import { Text, useTheme, TextInput, IconButton } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; import apiClient from '../api/client'; // Import the apiClient +import { useRoute, RouteProp } from '@react-navigation/native'; // Import useRoute and RouteProp // Define the structure for a message interface Message { @@ -26,73 +37,49 @@ interface ChatHistoryResponse { timestamp: string; // Backend sends ISO string } +// Define the type for the navigation route parameters +type RootStackParamList = { + Chat: { // Assuming 'Chat' is the name of the route for this screen + initialQuestion?: string; // Make initialQuestion optional + }; + // Add other routes here if needed +}; + +type ChatScreenRouteProp = RouteProp; + const ChatScreen = () => { const theme = useTheme(); + const route = useRoute(); // Get route params + const initialQuestion = route.params?.initialQuestion; // Extract initialQuestion + const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const [isHistoryLoading, setIsHistoryLoading] = useState(true); // Add state for history loading + const [isLoading, setIsLoading] = useState(false); // Loading state for sending messages + const [isHistoryLoading, setIsHistoryLoading] = useState(true); // Loading state for initial history fetch const flatListRef = useRef(null); - // --- Load messages from backend API on mount --- - useEffect(() => { - const loadHistory = async () => { - setIsHistoryLoading(true); - try { - console.log("[ChatScreen] Fetching chat history from /nlp/history"); - const response = await apiClient.get('/nlp/history'); - console.log("[ChatScreen] Received history:", response.data); - - if (response.data && Array.isArray(response.data)) { - // Map backend response to frontend Message format - const historyMessages = response.data.map((msg) => ({ - id: msg.id.toString(), // Convert backend ID to string for keyExtractor - text: msg.text, - sender: msg.sender, - timestamp: new Date(msg.timestamp), // Convert ISO string to Date - })); - setMessages(historyMessages); - } else { - console.warn("[ChatScreen] Received invalid history data:", response.data); - setMessages([]); // Set to empty array if data is invalid - } - } catch (error: any) { - console.error("Failed to load chat history from backend:", error.response?.data || error.message || error); - // Optionally, show an error message to the user - // For now, just start with an empty chat - setMessages([]); - } finally { - setIsHistoryLoading(false); - } - }; - loadHistory(); - }, []); // Empty dependency array ensures this runs only once on mount - - // Function to handle sending a message - const handleSend = useCallback(async () => { - const trimmedText = inputText.trim(); - if (!trimmedText || isLoading) return; // Prevent sending while loading + // --- Function to send a message to the backend --- (Extracted logic) + const sendMessageToApi = useCallback(async (textToSend: string) => { + if (!textToSend) return; // Don't send empty messages const userMessage: Message = { id: Date.now().toString() + '-user', // Temporary frontend ID - text: trimmedText, + text: textToSend, sender: 'user', timestamp: new Date(), }; // Add user message optimistically setMessages(prevMessages => [...prevMessages, userMessage]); - - setInputText(''); setIsLoading(true); - // Scroll to bottom after sending user message + // Scroll to bottom after adding user message setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100); // --- Call Backend API --- try { - console.log(`[ChatScreen] Sending to /nlp/process-command: ${trimmedText}`); - const response = await apiClient.post('/nlp/process-command', { user_input: trimmedText }); + console.log(`[ChatScreen] Sending to /nlp/process-command: ${textToSend}`); + const response = await apiClient.post('/nlp/process-command', { user_input: textToSend }); console.log("[ChatScreen] Received response:", response.data); const aiResponses: Message[] = []; @@ -100,7 +87,7 @@ const ChatScreen = () => { response.data.responses.forEach((responseText, index) => { aiResponses.push({ id: `${Date.now()}-ai-${index}`, // Temporary frontend ID - text: responseText || "...", + text: responseText || "...", // Handle potentially empty strings sender: 'ai', timestamp: new Date(), }); @@ -109,7 +96,7 @@ const ChatScreen = () => { console.warn("[ChatScreen] Received invalid or empty responses array:", response.data); aiResponses.push({ id: Date.now().toString() + '-ai-fallback', - text: "Sorry, I didn't get a valid response.", + text: "Sorry, I couldn't process that properly.", sender: 'ai', timestamp: new Date(), }); @@ -133,13 +120,92 @@ const ChatScreen = () => { setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100); } // --- End API Call --- + // NOTE: Removed `messages` from dependency array to prevent potential loops. + // State updates within useCallback using the functional form `setMessages(prev => ...)` + // don't require the state itself as a dependency. + }, []); - }, [inputText, isLoading, messages]); // Add isLoading and messages to dependency array + // --- Load messages from backend API on mount & handle initial question --- + useEffect(() => { + let isMounted = true; // Flag to prevent state updates on unmounted component + const loadHistoryAndSendInitial = async () => { + console.log("[ChatScreen] Component mounted. Loading history..."); + setIsHistoryLoading(true); + let historyLoadedSuccessfully = false; + try { + const response = await apiClient.get('/nlp/history'); + if (isMounted) { + console.log("[ChatScreen] Received history:", response.data); + if (response.data && Array.isArray(response.data)) { + const historyMessages = response.data.map((msg) => ({ + id: msg.id.toString(), + text: msg.text, + sender: msg.sender, + timestamp: new Date(msg.timestamp), + })); + setMessages(historyMessages); + historyLoadedSuccessfully = true; // Mark history as loaded + } else { + console.warn("[ChatScreen] Received invalid history data:", response.data); + setMessages([]); + } + } + } catch (error: any) { + if (isMounted) { + console.error("Failed to load chat history:", error.response?.data || error.message || error); + setMessages([]); // Clear messages on error + } + } finally { + if (isMounted) { + setIsHistoryLoading(false); + console.log("[ChatScreen] History loading finished. History loaded:", historyLoadedSuccessfully); + // Send initial question *after* history load attempt, if provided + if (initialQuestion) { + console.log("[ChatScreen] Initial question provided:", initialQuestion); + // Check if the initial question is already the last message from history (simple check) + const lastMessageText = messages[messages.length - 1]?.text; + if (lastMessageText !== initialQuestion) { + console.log("[ChatScreen] Sending initial question now."); + // Use a timeout to ensure history state update is processed before sending + setTimeout(() => sendMessageToApi(initialQuestion), 0); + } else { + console.log("[ChatScreen] Initial question seems to match last history message, not sending again."); + } + } else { + console.log("[ChatScreen] No initial question provided."); + } + } + } + }; + + loadHistoryAndSendInitial(); + + return () => { + isMounted = false; // Cleanup function to set flag on unmount + console.log("[ChatScreen] Component unmounted."); + }; + // Run only once on mount. `initialQuestion` is stable after mount. + // `sendMessageToApi` is memoized by useCallback. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [initialQuestion, sendMessageToApi]); + + // Function to handle sending a message via input button + const handleSend = useCallback(async () => { + const trimmedText = inputText.trim(); + if (!trimmedText || isLoading) return; + + setInputText(''); // Clear input immediately + await sendMessageToApi(trimmedText); // Use the extracted function + + }, [inputText, isLoading, sendMessageToApi]); + + // Function to handle Enter key press for sending const handleKeyPress = (e: NativeSyntheticEvent) => { + // Check if Enter is pressed without Shift key if (e.nativeEvent.key === 'Enter' && !(e.nativeEvent as any).shiftKey) { - e.preventDefault(); // Prevent new line - handleSend(); + e.preventDefault(); // Prevent default behavior (like newline) + handleSend(); // Trigger send action } }; @@ -164,6 +230,12 @@ const ChatScreen = () => { flex: 1, backgroundColor: theme.colors.background, }, + loadingContainer: { // Centering container for loading indicator + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: theme.colors.background, + }, keyboardAvoidingContainer: { // Style for KAV flex: 1, }, @@ -181,39 +253,33 @@ const ChatScreen = () => { paddingVertical: 8, // Add some vertical padding borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: theme.colors.outlineVariant, - backgroundColor: theme.colors.background, // Or theme.colors.surface + backgroundColor: theme.colors.surface, // Use surface color for input area }, textInput: { flex: 1, // Take available horizontal space marginRight: 8, - backgroundColor: theme.colors.surface, - paddingTop: 10, // Keep the vertical alignment fix for placeholder - paddingHorizontal: 10, - // Add some vertical padding inside the input itself - paddingVertical: Platform.OS === 'ios' ? 10 : 5, // Adjust padding for different platforms if needed + backgroundColor: theme.colors.surface, // Match container background + // Remove explicit padding if mode="outlined" handles it well maxHeight: 100, // Optional: prevent input from getting too tall with multiline }, sendButton: { - marginVertical: 4, // Adjust vertical alignment if needed - // Ensure button doesn't shrink - height: 40, // Match TextInput height approx. - justifyContent: 'center', + margin: 0, // Remove default margins if IconButton has them }, messageBubble: { maxWidth: '80%', - padding: 10, - borderRadius: 15, + padding: 12, // Slightly larger padding + borderRadius: 18, // More rounded corners marginBottom: 10, }, userBubble: { alignSelf: 'flex-end', backgroundColor: theme.colors.primary, - borderBottomRightRadius: 5, + borderBottomRightRadius: 5, // Keep the chat bubble tail effect }, aiBubble: { alignSelf: 'flex-start', backgroundColor: theme.colors.surfaceVariant, - borderBottomLeftRadius: 5, + borderBottomLeftRadius: 5, // Keep the chat bubble tail effect }, timestamp: { fontSize: 10, @@ -223,13 +289,12 @@ const ChatScreen = () => { } }); - // Optionally, show a loading indicator while history loads + // Show a loading indicator while history loads if (isHistoryLoading) { return ( - - - Loading chat history... - + + + Loading chat history... ); } @@ -237,13 +302,9 @@ const ChatScreen = () => { return ( {/* List container takes available space */} @@ -252,9 +313,11 @@ const ChatScreen = () => { data={messages} renderItem={renderMessage} keyExtractor={(item) => item.id} - contentContainerStyle={styles.messageList} // Padding inside the scrollable content - onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: false })} - onLayout={() => flatListRef.current?.scrollToEnd({ animated: false })} + contentContainerStyle={styles.messageList} + // Optimization: remove onContentSizeChange/onLayout if not strictly needed for scrolling + // onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: false })} + // onLayout={() => flatListRef.current?.scrollToEnd({ animated: false })} + // Consider initialScrollIndex or other props if performance is an issue /> @@ -264,13 +327,14 @@ const ChatScreen = () => { style={styles.textInput} value={inputText} onChangeText={setInputText} - placeholder="Type your message..." - mode="outlined" // Keep outlined or flat as preferred + placeholder="Ask MAIA..." + mode="outlined" multiline - onKeyPress={handleKeyPress} + onKeyPress={handleKeyPress} // Use onKeyPress for web/desktop-like Enter behavior blurOnSubmit={false} // Keep false for multiline + send button - disabled={isLoading} - dense // Try making the input slightly smaller vertically + disabled={isLoading} // Disable input while AI is responding + outlineStyle={{ borderRadius: 20 }} // Make input more rounded + dense // Reduce vertical padding /> { mode="contained" iconColor={theme.colors.onPrimary} containerColor={theme.colors.primary} - style={styles.sendButton} // Apply style for alignment + style={styles.sendButton} + animated // Add subtle animation /> diff --git a/interfaces/nativeapp/src/screens/DashboardScreen.tsx b/interfaces/nativeapp/src/screens/DashboardScreen.tsx index 47c79e7..e271202 100644 --- a/interfaces/nativeapp/src/screens/DashboardScreen.tsx +++ b/interfaces/nativeapp/src/screens/DashboardScreen.tsx @@ -1,18 +1,212 @@ // src/screens/DashboardScreen.tsx -import React from 'react'; -import { View, StyleSheet } from 'react-native'; -import { Text, useTheme } from 'react-native-paper'; +import React, { useState, useEffect } from 'react'; // Added useEffect +import { View, StyleSheet, ScrollView } from 'react-native'; // Added ScrollView +import { Text, TextInput, Button, useTheme, Card, List, Divider } from 'react-native-paper'; // Added Card, List, Divider +import { useNavigation } from '@react-navigation/native'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { format, addDays, startOfDay, isSameDay, parseISO, endOfDay } from 'date-fns'; // Added date-fns imports +import { getCalendarEvents } from '../api/calendar'; +import { CalendarEvent } from '../types/calendar'; + + +// Placeholder for the TODO component +const TodoComponent = () => ( + + TODO Component Placeholder + +); + +// --- Calendar Preview Component Implementation --- +const CalendarPreview = () => { + const theme = useTheme(); + const [eventsByDay, setEventsByDay] = useState<{ [key: string]: CalendarEvent[] }>({}); + const today = startOfDay(new Date()); + const days = [today, addDays(today, 1), addDays(today, 2)]; + + useEffect(() => { + const fetchAndProcessEvents = async () => { + try { + // Fetch events for the entire 3-day range once + const endDate = endOfDay(addDays(today, 2)); // Calculate end date to include the whole day + const allEvents = await getCalendarEvents(today, endDate); // Fetch events until the end of the third day + + // Process events: Group by day + const groupedEvents: { [key: string]: CalendarEvent[] } = {}; + days.forEach(day => { + const dayStr = format(day, 'yyyy-MM-dd'); + // Filter events for the current day and sort them + groupedEvents[dayStr] = allEvents + .filter(event => isSameDay(parseISO(event.start), day)) + .sort((a, b) => parseISO(a.start).getTime() - parseISO(b.start).getTime()); + }); + setEventsByDay(groupedEvents); + } catch (error) { + console.error("Failed to fetch calendar events:", error); + // Optionally, set an error state here to display to the user + } + }; + fetchAndProcessEvents(); + }, []); // Run once on mount + + const formatDateHeader = (date: Date): string => { + if (isSameDay(date, today)) return `Today, ${format(date, 'MMMM d')}`; + if (isSameDay(date, addDays(today, 1))) return `Tomorrow, ${format(date, 'MMMM d')}`; + return format(date, 'EEEE, MMMM d'); + }; + + const styles = StyleSheet.create({ + card: { + marginVertical: 8, + backgroundColor: theme.colors.background, + }, + dayHeader: { + fontSize: 16, + fontWeight: 'bold', + paddingLeft: 16, + paddingTop: 12, + paddingBottom: 8, + color: theme.colors.primary, + }, + listItem: { + paddingVertical: 4, // Reduce padding slightly + }, + eventTime: { + fontSize: 14, + color: theme.colors.onSurfaceVariant, // Ensure contrast + }, + eventTitle: { + fontSize: 15, + color: theme.colors.onSurface, + }, + noEventsText: { + paddingLeft: 16, + paddingBottom: 12, + fontStyle: 'italic', + color: theme.colors.onSurfaceDisabled, + }, + divider: { + marginHorizontal: 16, + } + }); + + return ( + + + {days.map((day, index) => { + const dayStr = format(day, 'yyyy-MM-dd'); + const dailyEvents = eventsByDay[dayStr] || []; + return ( + + {formatDateHeader(day)} + {dailyEvents.length > 0 ? ( + dailyEvents.map((event, eventIndex) => ( + + } // Simple indicator + /> + {eventIndex < dailyEvents.length - 1 && } + + )) + ) : ( + No events scheduled. + )} + {/* Add divider between days, except after the last day */} + {index < days.length - 1 && } + + ); + })} + + + ); +}; +// --- End Calendar Preview Component --- + +// Define the type for the navigation stack parameters +// Ensure this matches the navigator's configuration +type RootStackParamList = { + Dashboard: undefined; // No params expected for Dashboard itself + Chat: { initialQuestion?: string }; // Chat screen expects an optional initialQuestion + // Add other screens in your stack here +}; + +// Define the specific navigation prop type for DashboardScreen +type DashboardScreenNavigationProp = StackNavigationProp; const DashboardScreen = () => { const theme = useTheme(); + // Use the specific navigation prop type + const navigation = useNavigation(); + const [question, setQuestion] = useState(''); + + const handleQuestionSubmit = () => { + const trimmedQuestion = question.trim(); + if (trimmedQuestion) { + // Navigate to ChatScreen, passing the question as a param + navigation.navigate('Chat', { initialQuestion: trimmedQuestion }); + // console.log('Navigating to ChatScreen with question:', question); // Keep for debugging if needed + setQuestion(''); // Clear input after submission + } + }; + const styles = StyleSheet.create({ - container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 16, backgroundColor: theme.colors.background }, - text: { fontSize: 20, color: theme.colors.text } + container: { + flex: 1, + // alignItems: 'center', // Keep removed + justifyContent: 'flex-start', + padding: 16, + backgroundColor: theme.colors.background + }, + title: { + fontSize: 24, + fontWeight: 'bold', + marginBottom: 20, + color: theme.colors.primary, // Use theme color + alignSelf: 'center' // Center the title + }, + inputContainer: { + marginBottom: 20, + }, + textInput: { + marginBottom: 10, + }, + scrollViewContent: { + paddingBottom: 20, // Add padding at the bottom of the scroll view + } }); + return ( - - Dashboard - + // Wrap content in ScrollView to handle potential overflow + + + Dashboard + + {/* AI Question Input */} + + + + + + {/* Calendar Preview */} + + + {/* TODO Component */} + + + ); }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..19e4604 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4859 @@ +{ + "name": "MAIA", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@react-navigation/stack": "^7.2.10" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "license": "MIT", + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.27.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "peer": true + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "peer": true + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "peer": true + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.26.8", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.26.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.26.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.26.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.26.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.26.6", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "peer": true + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "peer": true + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.26.10", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.26.8", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.27.0", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.40.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-typescript": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.25.9", + "license": "MIT", + "peer": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "license": "MIT", + "peer": true + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse--for-generate-function-map": { + "name": "@babel/traverse", + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "peer": true, + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "license": "ISC", + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "peer": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.78.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.78.2", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.25.1", + "invariant": "^2.2.4", + "jscodeshift": "^17.0.0", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-native/dev-middleware": "0.78.2", + "@react-native/metro-babel-transformer": "0.78.2", + "chalk": "^4.0.0", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "metro": "^0.81.3", + "metro-config": "^0.81.3", + "metro-core": "^0.81.3", + "readline": "^1.3.0", + "semver": "^7.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@react-native-community/cli": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli": { + "optional": true + } + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.78.2", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.78.2", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.16.2", + "ws": "^6.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@react-native/babel-preset": "0.78.2", + "hermes-parser": "0.25.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.78.2", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^19.0.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-navigation/core": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.8.5.tgz", + "integrity": "sha512-xDUXs6NI6ASiZgf53I7NPG0iJVGClPL5O3r8ddOCkS6fhVmPRun64m2zxUWnPcxtheFNTFfQ1IXH+gcenTcv/w==", + "peer": true, + "dependencies": { + "@react-navigation/routers": "^7.3.5", + "escape-string-regexp": "^4.0.0", + "nanoid": "3.3.8", + "query-string": "^7.1.3", + "react-is": "^18.2.0", + "use-latest-callback": "^0.2.1", + "use-sync-external-store": "^1.2.2" + }, + "peerDependencies": { + "react": ">= 18.2.0" + } + }, + "node_modules/@react-navigation/elements": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.3.8.tgz", + "integrity": "sha512-2ZVBtPfrkmOxzvIyDu3fPZ6aS4HcXL+TvzPDGa1znY2OP1Llo6wH14AmJHQFDquiInp2656hRMM1BkfJ3yPwew==", + "dependencies": { + "color": "^4.2.3" + }, + "peerDependencies": { + "@react-native-masked-view/masked-view": ">= 0.2.0", + "@react-navigation/native": "^7.1.6", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0" + }, + "peerDependenciesMeta": { + "@react-native-masked-view/masked-view": { + "optional": true + } + } + }, + "node_modules/@react-navigation/native": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.6.tgz", + "integrity": "sha512-XcfygfHDfAgf2iC4rNBc67Yy0M1aYRGNeNKqja5AJPFZoBQhAEAxKCwHsH4g3qU0zIbzLCthoSl5107dBjoeZw==", + "peer": true, + "dependencies": { + "@react-navigation/core": "^7.8.5", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "3.3.8", + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*" + } + }, + "node_modules/@react-navigation/routers": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-7.3.5.tgz", + "integrity": "sha512-SBh/3G7pURIQfIwG4OnAfLvq0E4+l1Ii6577z22cIhWIrTOHFXg0rMxC7ft/amzxYn+iG2nYa4dONRd+xIs+yg==", + "peer": true, + "dependencies": { + "nanoid": "3.3.8" + } + }, + "node_modules/@react-navigation/stack": { + "version": "7.2.10", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-7.2.10.tgz", + "integrity": "sha512-8exYxg/3goQkmtAJFIPpKbFOiMmNRSf99qs5ssX1gQ2JEhwloBl7Bw0snccB1JJ7rghjD5bogj+zcQdC8KSYeg==", + "dependencies": { + "@react-navigation/elements": "^2.3.8", + "color": "^4.2.3" + }, + "peerDependencies": { + "@react-navigation/native": "^7.1.6", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-gesture-handler": ">= 2.0.0", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "peer": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "peer": true + }, + "node_modules/@types/node": { + "peer": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "license": "MIT", + "peer": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "license": "MIT", + "peer": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "license": "ISC", + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "license": "MIT", + "peer": true + }, + "node_modules/ast-types": { + "version": "0.16.1", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "license": "MIT", + "peer": true + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.13", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.4", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.4" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.25.1", + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-parser": "0.25.1" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "license": "MIT", + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT", + "peer": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "peer": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT", + "peer": true + }, + "node_modules/camelcase": { + "version": "5.3.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001714", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0", + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chrome-launcher": { + "peer": true + }, + "node_modules/chromium-edge-launcher": { + "peer": true + }, + "node_modules/ci-info": { + "version": "3.9.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "license": "MIT", + "peer": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "license": "MIT", + "peer": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT", + "peer": true + }, + "node_modules/connect": { + "version": "3.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/core-js-compat": { + "version": "3.41.0", + "license": "MIT", + "peer": true, + "dependencies": { + "browserslist": "^4.24.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT", + "peer": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.138", + "license": "ISC", + "peer": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT", + "peer": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "peer": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT", + "peer": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "license": "MIT", + "peer": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "license": "MIT", + "peer": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "license": "MIT", + "peer": true + }, + "node_modules/flow-parser": { + "version": "0.268.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC", + "peer": true + }, + "node_modules/fsevents": { + "optional": true, + "peer": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "peer": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC", + "peer": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "peer": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "license": "MIT", + "peer": true + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "peer": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "peer": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "peer": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC", + "peer": true + }, + "node_modules/invariant": { + "version": "2.2.4", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "license": "MIT", + "peer": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "license": "MIT", + "peer": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isobject": { + "version": "3.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscodeshift": { + "version": "17.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@babel/register": "^7.24.6", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.7", + "neo-async": "^2.5.0", + "picocolors": "^1.0.1", + "recast": "^0.23.11", + "tmp": "^0.2.3", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/signal-exit": { + "version": "4.1.0", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "5.0.1", + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "license": "MIT", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "license": "MIT", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "license": "MIT", + "peer": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "license": "MIT", + "peer": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/metro": { + "peer": true + }, + "node_modules/metro-config": { + "peer": true + }, + "node_modules/metro-core": { + "peer": true + }, + "node_modules/metro-runtime": { + "version": "0.81.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/metro-source-map": { + "version": "0.81.4", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.81.4", + "nullthrows": "^1.1.1", + "ob1": "0.81.4", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.81.4", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.81.4", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "license": "MIT", + "peer": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "license": "MIT", + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT", + "peer": true + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "license": "MIT", + "peer": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "license": "MIT", + "peer": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "license": "MIT", + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "license": "MIT", + "peer": true + }, + "node_modules/ob1": { + "version": "0.81.4", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "peer": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT", + "peer": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "license": "ISC", + "peer": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "peer": true, + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "19.1.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "6.1.1", + "license": "MIT", + "peer": true, + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.10", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/react-freeze": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "peer": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "license": "MIT", + "peer": true + }, + "node_modules/react-native": { + "version": "0.78.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native/assets-registry": "0.78.2", + "@react-native/codegen": "0.78.2", + "@react-native/community-cli-plugin": "0.78.2", + "@react-native/gradle-plugin": "0.78.2", + "@react-native/js-polyfills": "0.78.2", + "@react-native/normalize-colors": "0.78.2", + "@react-native/virtualized-lists": "0.78.2", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "commander": "^12.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.81.3", + "metro-source-map": "^0.81.3", + "nullthrows": "^1.1.1", + "pretty-format": "^29.7.0", + "promise": "^8.3.0", + "react-devtools-core": "^6.0.1", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.25.0", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.3", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^19.0.0", + "react": "^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.25.0.tgz", + "integrity": "sha512-NPjJi6mislXxvjxQPU9IYwBjb1Uejp8GvAbE1Lhh+xMIMEvmgAvVIp5cz1P+xAbV6uYcRRArm278+tEInGOqWg==", + "peer": true, + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-safe-area-context": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.4.0.tgz", + "integrity": "sha512-JaEThVyJcLhA+vU0NU8bZ0a1ih6GiF4faZ+ArZLqpYbL6j7R3caRqj+mE3lEtKCuHgwjLg3bCxLL1GPUJZVqUA==", + "peer": true, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.10.0.tgz", + "integrity": "sha512-Tw21NGuXm3PbiUGtZd0AnXirUixaAbPXDjNR0baBH7/WJDaDTTELLcQ7QRXuqAWbmr/EVCrKj1348ei1KFIr8A==", + "peer": true, + "dependencies": { + "react-freeze": "^1.0.0", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "license": "BSD", + "peer": true + }, + "node_modules/recast": { + "version": "0.23.11", + "license": "MIT", + "peer": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "license": "MIT", + "peer": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "license": "MIT", + "peer": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "license": "MIT", + "peer": true + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "license": "MIT", + "peer": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "license": "MIT", + "peer": true + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "license": "MIT", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "license": "MIT", + "peer": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/scheduler": { + "version": "0.25.0", + "license": "MIT", + "peer": true + }, + "node_modules/selfsigned": { + "peer": true + }, + "node_modules/semver": { + "version": "7.7.1", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC", + "peer": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "license": "MIT", + "peer": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC", + "peer": true + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "license": "MIT", + "peer": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "license": "MIT", + "peer": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "license": "MIT", + "peer": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "peer": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD", + "peer": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.7.1", + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-latest-callback": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz", + "integrity": "sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==", + "peer": true, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "peer": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "license": "MIT", + "peer": true + }, + "node_modules/walker": { + "version": "1.0.8", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "peer": true + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "license": "MIT", + "peer": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC", + "peer": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "6.2.3", + "license": "MIT", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "license": "ISC", + "peer": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b1bb7c2 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@react-navigation/stack": "^7.2.10" + } +}