diff --git a/.easignore b/.easignore new file mode 100644 index 0000000..8d9b441 --- /dev/null +++ b/.easignore @@ -0,0 +1,6 @@ +# Trimmed from the EAS build upload. Never exclude a workspace package: EAS runs +# `pnpm install --frozen-lockfile` at the root, and a missing package makes the +# lockfile diverge (ERR_PNPM_OUTDATED_LOCKFILE). +docs/ +docker/ +.github/ diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4e7da9f..501fce4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,5 +12,5 @@ labels: bug **Environment** -- App: web / mobile / admin / api +- App: mobile / api - Version or commit: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bb525c..4dd59dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,16 +9,54 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - DATABASE_URL: postgresql://wantere:wantere@localhost:5432/wantere?schema=public - REDIS_URL: redis://localhost:6379 - JWT_SECRET: ci-secret-value-that-is-long-enough-32 - JWT_REFRESH_SECRET: ci-refresh-secret-long-enough-32-chars - jobs: - quality: + mobile: + name: Mobile runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + cache: pnpm + + - run: pnpm install --frozen-lockfile + + # `pnpm --filter` runs each package script directly, which bypasses the + # `dependsOn: ["^build"]` of turbo.json: the shared packages compile to + # dist/ and nothing would build them. Same list as the EAS hook. + - name: Build the shared packages + run: >- + pnpm exec turbo run build + --filter=@p2p-local/config --filter=@p2p-local/design-tokens + --filter=@p2p-local/types --filter=@p2p-local/validation + + - run: pnpm --filter @p2p-local/mobile... lint + + - run: pnpm --filter @p2p-local/mobile... typecheck + + - run: pnpm --filter @p2p-local/mobile test + + # Informative: expo-doctor reaches the Expo registry and reports drift in + # transitive versions we do not control. + - name: Check the Expo project + run: pnpm --filter @p2p-local/mobile exec expo-doctor + continue-on-error: true + + api: + name: API + runs-on: ubuntu-latest + + env: + DATABASE_URL: postgresql://wantere:wantere@localhost:5432/wantere?schema=public + REDIS_URL: redis://localhost:6379 + JWT_SECRET: ci-secret-value-that-is-long-enough-32 + JWT_REFRESH_SECRET: ci-refresh-secret-long-enough-32-chars + services: postgres: image: postgis/postgis:17-3.5 @@ -57,7 +95,7 @@ jobs: - run: pnpm install --frozen-lockfile - name: Apply database migrations - run: pnpm --filter @wantere/api db:deploy + run: pnpm --filter @p2p-local/api db:deploy - run: pnpm lint @@ -66,6 +104,8 @@ jobs: - run: pnpm test - name: Run end-to-end tests - run: pnpm --filter @wantere/api test:e2e + run: pnpm --filter @p2p-local/api test:e2e - - run: pnpm build + # The mobile bundle is built by EAS, not here: `expo export` is slow and + # reaches the network for no verification CI does not already have. + - run: pnpm build --filter=!@p2p-local/mobile diff --git a/.github/workflows/eas-build.yml b/.github/workflows/eas-build.yml new file mode 100644 index 0000000..65e160c --- /dev/null +++ b/.github/workflows/eas-build.yml @@ -0,0 +1,45 @@ +name: EAS build + +# Manual only: a build consumes quota and takes 15 to 30 minutes, which makes it +# unusable on every pull request. +on: + workflow_dispatch: + inputs: + profile: + description: Profil EAS + type: choice + options: [preview, production] + default: preview + platform: + description: Plateforme + type: choice + options: [android, ios, all] + default: android + +jobs: + build: + name: Build ${{ inputs.platform }} (${{ inputs.profile }}) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + cache: pnpm + + # Requires an EXPO_TOKEN repository secret, created from an Expo access + # token that can build this project. + - uses: expo/expo-github-action@v8 + with: + eas-version: latest + token: ${{ secrets.EXPO_TOKEN }} + + - run: pnpm install --frozen-lockfile + + - name: Trigger the build + working-directory: apps/mobile + run: eas build --platform ${{ inputs.platform }} --profile ${{ inputs.profile }} --non-interactive --no-wait diff --git a/.gitignore b/.gitignore index 2927e63..25b5b69 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,8 @@ dist build coverage .turbo -.next -out .expo *.tsbuildinfo -next-env.d.ts expo-env.d.ts apps/api/src/generated diff --git a/.prettierignore b/.prettierignore index 7f4a84d..8cd0159 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,6 @@ pnpm-lock.yaml node_modules dist -.next .expo coverage packages/api-client/src/generated diff --git a/.prettierrc b/.prettierrc index 41c6f22..30339a6 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1 @@ -"@wantere/prettier-config" +"@p2p-local/prettier-config" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index dd94997..10e36e2 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,7 +2,7 @@ ## Our pledge -We want participation in Wantere to be a harassment-free experience for +We want participation in P2P Local to be a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5dbe74e..2b829c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,15 +3,18 @@ ## Setup ```bash -cp apps/api/.env.example apps/api/.env -cp apps/web/.env.example apps/web/.env -cp apps/admin/.env.example apps/admin/.env -cp apps/mobile/.env.example apps/mobile/.env - pnpm install +pnpm --filter @p2p-local/mobile dev +``` + +The V1 mobile application needs nothing else: no server, no environment +variable. To work on the API: + +```bash +cp apps/api/.env.example apps/api/.env pnpm docker:up pnpm db:migrate && pnpm db:seed -pnpm dev +pnpm --filter @p2p-local/api dev ``` ## Before opening a pull request @@ -32,16 +35,36 @@ pnpm api:generate ## Conventions -- Conventional Commits: `feat(api): add offer negotiation`, `fix(web): ...`. +- Conventional Commits: `feat(mobile): add the district picker`, `fix(api): ...`. - Code is organised by domain, not by technical layer. A new business concept - gets its own module under `apps/api/src/modules`. -- NestJS owns the business rules. The web and mobile applications consume the - API; they do not reimplement validation or authorization. + gets its own module under `apps/api/src/modules`, or its own folder under + `apps/mobile/features`. +- The V1 mobile app has no backend. Listings live on the device behind + `ListingRepository`; screens never touch AsyncStorage directly. Every read and + write goes through the repository interface, so a server implementation can + replace it without rewriting a screen. +- The API owns the business rules for anything it serves. Clients consume it; + they do not reimplement validation or authorization. - Comments explain decisions, constraints or workarounds — not what the code already says. - Public API responses must never expose a member's exact location, phone number or internal moderation state. + This rule covers the API. The mobile app does not display a phone number + either: it only builds a `wa.me` link at the moment of the tap. That the + author of a listing becomes reachable at all is a contradiction with the + promise made during framing, and it is an open team decision — see + [docs/design/README.md](docs/design/README.md). + +## Mobile application + +- Add an Expo dependency with `npx expo install `, never with a version + written by hand: only `expo install` knows what the SDK is compatible with. + `npx expo install --check` reports drift, `--fix` corrects it. +- `npx expo-doctor` must pass before opening a pull request. +- Application icons are generated: edit `apps/mobile/assets/source/*.svg`, run + `pnpm --filter @p2p-local/mobile assets:build`, and commit the resulting PNGs. + ## Database changes Update `apps/api/prisma/schema.prisma`, then: @@ -58,7 +81,9 @@ hand-written migration, since Prisma cannot express it. - Unit tests live next to the code as `*.spec.ts`. - End-to-end tests live in `apps/api/test` and run against a real Postgres and Redis. +- On mobile, pure functions (formatting, WhatsApp links) and the storage + repository are tested. Screen rendering is not tested in V1. Test what carries risk: authorization, money-adjacent rules, privacy of -locations, search behaviour. Tests asserting that a service is defined are not -useful. +locations and phone numbers, search behaviour. Tests asserting that a service is +defined are not useful. diff --git a/LICENSE b/LICENSE index 54539b3..9db8ad7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 Wantere contributors +Copyright (c) 2026 P2P Local contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 0823312..ada819b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Wantere +# P2P Local -Wantere est une plateforme communautaire pour acheter, vendre, donner et +P2P Local est une plateforme communautaire pour acheter, vendre, donner et échanger des biens près de chez soi. Elle est pensée d'abord pour le Sénégal, mais rien dans son architecture ne suppose un pays unique. @@ -9,12 +9,20 @@ rattachée à un quartier, les prix sont visibles, le don et le troc sont trait au même niveau que la vente, et la modération fait partie du domaine métier plutôt que d'être ajoutée après coup. +`P2P Local` est un nom de code. Il tient la place d'un nom définitif qui reste à +choisir, et il est isolé dans la configuration pour pouvoir être remplacé en une +seule passe. + ## État du projet -Les fondations sont en place : authentification, profils, catégories, annonces -avec recherche géolocalisée, favoris, signalements et notifications. Les -conversations, les offres, les commandes, les achats groupés et l'observatoire -des prix sont prévus dans l'architecture mais pas encore implémentés — voir +La V1 est une **application mobile qui fonctionne sans backend** : les annonces +sont enregistrées sur l'appareil, la publication ne demande aucun compte, et la +mise en relation passe par WhatsApp. C'est un socle destiné à être enrichi, pas +une application finie. + +L'API existe, elle est testée, et elle **n'est pas consommée par la V1**. Elle +reste versionnée parce que le jour où les annonces devront circuler entre +plusieurs téléphones, c'est elle qui prendra le relais — voir [docs/architecture.md](docs/architecture.md). ## Stack @@ -22,63 +30,68 @@ des prix sont prévus dans l'architecture mais pas encore implémentés — voir | Domaine | Choix | | -------- | ------------------------------------------------------------ | | Monorepo | Turborepo, pnpm workspaces, TypeScript strict | +| Mobile | Expo SDK 57, Expo Router, TanStack Query, Zustand, AsyncStorage | | API | NestJS, PostgreSQL + PostGIS, Prisma, Redis, BullMQ, OpenAPI | -| Web | Next.js App Router, Tailwind CSS, TanStack Query | -| Mobile | Expo, Expo Router, TanStack Query, Zustand | -| Admin | Next.js App Router, Tailwind CSS, TanStack Query | ## Structure du dépôt ``` apps/ - api/ Monolithe modulaire NestJS, source de vérité des règles métier - web/ Site public - mobile/ Application Expo - admin/ Back-office + mobile/ Application Expo — la V1 + api/ Monolithe modulaire NestJS, hors périmètre de la V1 packages/ - api-client/ Client fetch généré depuis le document OpenAPI - validation/ Schémas Zod partagés entre les clients + api-client/ Client fetch généré depuis le document OpenAPI. + Aucune application ne le consomme aujourd'hui ; il est + conservé avec l'API dont il est le pendant généré. + validation/ Schémas Zod partagés types/ Enums du domaine et primitives communes - config/ Constantes produit (limites, pagination, devises) - design-tokens/ Couleurs, espacements, typographie, thème Tailwind + config/ Constantes produit (limites, pagination, devises, quartiers) + design-tokens/ Couleurs, espacements, typographie eslint-config/ Configurations ESLint flat typescript-config/ prettier-config/ -docker/ Postgres, Redis et MinIO en local -docs/ Notes d'architecture +docker/ Postgres, Redis et MinIO en local, pour l'API +docs/ Notes d'architecture et références de conception ``` ## Prérequis -- Node.js 22 ou plus récent (voir `.nvmrc`) +- Node.js 24 ou plus récent (voir `.nvmrc`) - pnpm 11 -- Docker, pour Postgres et Redis +- Expo Go sur un téléphone, ou un émulateur Android / simulateur iOS +- Docker, uniquement pour travailler sur l'API ## Démarrage +```bash +pnpm install +pnpm --filter @p2p-local/mobile dev +``` + +Le bundler Expo affiche un QR code ; l'application s'ouvre dans Expo Go. Aucune +variable d'environnement n'est nécessaire : la V1 ne contacte aucun serveur. + +### Travailler sur l'API + ```bash cp apps/api/.env.example apps/api/.env -cp apps/web/.env.example apps/web/.env -cp apps/admin/.env.example apps/admin/.env -cp apps/mobile/.env.example apps/mobile/.env pnpm install pnpm docker:up pnpm db:migrate pnpm db:seed -pnpm dev +pnpm --filter @p2p-local/api dev ``` -`pnpm dev` démarre l'API sur le port 4000, le site sur 3000, le back-office sur -3001 et le bundler Expo. Swagger est servi sur en -dehors de la production. +L'API démarre sur le port 4000. Swagger est servi sur + en dehors de la production. ## Variables d'environnement -Chaque application fournit un `.env.example` ; aucun secret n'est versionné. -L'API valide son environnement au démarrage et refuse de se lancer s'il est -invalide. +L'application mobile n'a aucune variable d'environnement en V1. L'API fournit un +`.env.example` ; aucun secret n'est versionné. Elle valide son environnement au +démarrage et refuse de se lancer s'il est invalide. | Variable | Utilisée par | Remarques | | ---------------------------------- | ------------ | ---------------------------------- | @@ -86,8 +99,25 @@ invalide. | `REDIS_URL` | api | Files, rate limiting, throttle OTP | | `JWT_SECRET`, `JWT_REFRESH_SECRET` | api | 32 caractères minimum | | `CORS_ORIGINS` | api | Liste séparée par des virgules | -| `NEXT_PUBLIC_API_URL` | web, admin | Origine de l'API, sans le préfixe | -| `EXPO_PUBLIC_API_URL` | mobile | Origine de l'API, sans le préfixe | + +## Builds EAS + +L'application est liée à un projet EAS. Trois profils sont définis dans +`apps/mobile/eas.json` : + +| Profil | Sortie | Usage | +| ------------- | ------------------------ | -------------------------------------- | +| `development` | APK avec client de dév | développement sur appareil réel | +| `preview` | APK, distribution interne | partager une version à tester | +| `production` | App Bundle Android | publication sur le Play Store | + +```bash +cd apps/mobile +npx eas-cli build --platform android --profile preview +``` + +Le workflow `.github/workflows/eas-build.yml` déclenche un build à la demande. +Il exige un secret de dépôt `EXPO_TOKEN`, créé depuis un jeton d'accès Expo. ## Base de données @@ -108,10 +138,13 @@ vivent dans une migration écrite à la main. pnpm lint pnpm typecheck pnpm test -pnpm --filter @wantere/api test:e2e # nécessite Postgres et Redis +pnpm --filter @p2p-local/api test:e2e # nécessite Postgres et Redis pnpm build ``` +Côté mobile, `npx expo-doctor` depuis `apps/mobile` vérifie la cohérence du +projet Expo. Une dépendance Expo s'ajoute toujours avec `npx expo install`. + ## Client API Le client partagé est généré depuis le document OpenAPI de l'API : @@ -121,7 +154,7 @@ pnpm api:generate ``` Cette commande exporte `apps/api/openapi.json` et régénère -`@wantere/api-client`. Les deux sont versionnés pour que les applications +`@p2p-local/api-client`. Les deux sont versionnés pour que les applications compilent sans API démarrée. ## Contribuer diff --git a/apps/admin/.env.example b/apps/admin/.env.example deleted file mode 100644 index 3eec15e..0000000 --- a/apps/admin/.env.example +++ /dev/null @@ -1 +0,0 @@ -NEXT_PUBLIC_API_URL=http://localhost:4000 diff --git a/apps/admin/eslint.config.mjs b/apps/admin/eslint.config.mjs deleted file mode 100644 index df01424..0000000 --- a/apps/admin/eslint.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@wantere/eslint-config/next'; diff --git a/apps/admin/next.config.ts b/apps/admin/next.config.ts deleted file mode 100644 index de8320b..0000000 --- a/apps/admin/next.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { NextConfig } from 'next'; - -const config: NextConfig = { - reactStrictMode: true, - transpilePackages: ['@wantere/api-client', '@wantere/config', '@wantere/types'], -}; - -export default config; diff --git a/apps/admin/package.json b/apps/admin/package.json deleted file mode 100644 index 93aeff7..0000000 --- a/apps/admin/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@wantere/admin", - "version": "0.1.0", - "private": true, - "license": "MIT", - "scripts": { - "dev": "next dev --port 3001", - "build": "next build", - "start": "next start --port 3001", - "lint": "eslint src", - "typecheck": "tsc -p tsconfig.json --noEmit" - }, - "dependencies": { - "@tanstack/react-query": "^5.102.8", - "@wantere/api-client": "workspace:*", - "@wantere/config": "workspace:*", - "@wantere/design-tokens": "workspace:*", - "@wantere/types": "workspace:*", - "clsx": "^2.1.1", - "next": "^16.3.4", - "react": "19.2.3", - "react-dom": "19.2.3", - "tailwind-merge": "^3.6.0" - }, - "devDependencies": { - "@tailwindcss/postcss": "^4.3.3", - "@types/node": "^26.4.1", - "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.7", - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", - "eslint": "^10.10.0", - "tailwindcss": "^4.3.3", - "typescript": "~6.0.3" - } -} diff --git a/apps/admin/postcss.config.mjs b/apps/admin/postcss.config.mjs deleted file mode 100644 index a34a3d5..0000000 --- a/apps/admin/postcss.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - plugins: { - '@tailwindcss/postcss': {}, - }, -}; diff --git a/apps/admin/src/app/(console)/layout.tsx b/apps/admin/src/app/(console)/layout.tsx deleted file mode 100644 index 52d365f..0000000 --- a/apps/admin/src/app/(console)/layout.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import Link from 'next/link'; -import type { ReactNode } from 'react'; - -const navigation = [ - { href: '/', label: 'Vue d’ensemble' }, - { href: '/moderation', label: 'Modération' }, -] as const; - -export default function ConsoleLayout({ children }: { children: ReactNode }) { - return ( -
- -
{children}
-
- ); -} diff --git a/apps/admin/src/app/(console)/moderation/page.tsx b/apps/admin/src/app/(console)/moderation/page.tsx deleted file mode 100644 index 5b15a07..0000000 --- a/apps/admin/src/app/(console)/moderation/page.tsx +++ /dev/null @@ -1,73 +0,0 @@ -'use client'; - -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; -import { apiPath, request } from '@/lib/api'; -import type { Paginated } from '@wantere/types'; - -interface Report { - id: string; - targetType: string; - targetId: string; - reason: string; - comment: string | null; - status: string; - createdAt: string; -} - -export default function ModerationPage() { - const queryClient = useQueryClient(); - - const reports = useQuery({ - queryKey: ['reports'], - queryFn: () => request>(apiPath('/reports?pageSize=50')), - }); - - const review = useMutation({ - mutationFn: ({ id, status }: { id: string; status: 'RESOLVED' | 'DISMISSED' }) => - request(apiPath(`/reports/${id}`), { method: 'PATCH', body: JSON.stringify({ status }) }), - onSuccess: () => queryClient.invalidateQueries({ queryKey: ['reports'] }), - }); - - return ( -
-

Modération

- - {reports.isError ? ( -

- Connectez-vous avec un compte modérateur pour consulter la file. -

- ) : null} - - - - - - - - - - - {reports.data?.items.map((report) => ( - - - - - - - ))} - -
CibleMotifStatut -
- {report.targetType} · {report.targetId.slice(0, 8)} - {report.reason}{report.status} - -
-
- ); -} diff --git a/apps/admin/src/app/(console)/page.tsx b/apps/admin/src/app/(console)/page.tsx deleted file mode 100644 index 5bb250e..0000000 --- a/apps/admin/src/app/(console)/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -export default function OverviewPage() { - return ( -
-

Vue d’ensemble

-

- Les indicateurs seront ajoutés au fur et à mesure de l’ouverture des domaines métier. -

-
- ); -} diff --git a/apps/admin/src/app/layout.tsx b/apps/admin/src/app/layout.tsx deleted file mode 100644 index 291ba75..0000000 --- a/apps/admin/src/app/layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import type { Metadata } from 'next'; -import type { ReactNode } from 'react'; -import { QueryProvider } from '@/providers/query-provider'; -import '@/styles/globals.css'; - -export const metadata: Metadata = { - title: 'Wantere Admin', -}; - -export default function RootLayout({ children }: { children: ReactNode }) { - return ( - - - {children} - - - ); -} diff --git a/apps/admin/src/app/login/page.tsx b/apps/admin/src/app/login/page.tsx deleted file mode 100644 index 2144f2f..0000000 --- a/apps/admin/src/app/login/page.tsx +++ /dev/null @@ -1,69 +0,0 @@ -'use client'; - -import { useRouter } from 'next/navigation'; -import { useState } from 'react'; -import { apiPath, request } from '@/lib/api'; -import { session, type AuthTokens } from '@/features/auth/session'; - -export default function LoginPage() { - const router = useRouter(); - const [phone, setPhone] = useState(''); - const [code, setCode] = useState(''); - const [step, setStep] = useState<'phone' | 'code'>('phone'); - const [error, setError] = useState(null); - - async function submit(event: React.FormEvent) { - event.preventDefault(); - setError(null); - - try { - if (step === 'phone') { - await request(apiPath('/auth/login'), { method: 'POST', body: JSON.stringify({ phone }) }); - setStep('code'); - return; - } - - const tokens = await request(apiPath('/auth/verify'), { - method: 'POST', - body: JSON.stringify({ phone, code, platform: 'web' }), - }); - - session.write(tokens); - router.push('/'); - } catch (cause) { - setError(cause instanceof Error ? cause.message : 'Connexion impossible'); - } - } - - return ( -
-

Connexion

- - setPhone(event.target.value)} - disabled={step === 'code'} - /> - - {step === 'code' ? ( - setCode(event.target.value)} - /> - ) : null} - - {error ?

{error}

: null} - - -
- ); -} diff --git a/apps/admin/src/features/auth/session.ts b/apps/admin/src/features/auth/session.ts deleted file mode 100644 index 33e54ff..0000000 --- a/apps/admin/src/features/auth/session.ts +++ /dev/null @@ -1,30 +0,0 @@ -const ACCESS_TOKEN_KEY = 'wantere.admin.accessToken'; -const REFRESH_TOKEN_KEY = 'wantere.admin.refreshToken'; - -export interface AuthTokens { - accessToken: string; - refreshToken: string; -} - -export const session = { - read(): AuthTokens | null { - if (typeof window === 'undefined') { - return null; - } - - const accessToken = window.localStorage.getItem(ACCESS_TOKEN_KEY); - const refreshToken = window.localStorage.getItem(REFRESH_TOKEN_KEY); - - return accessToken && refreshToken ? { accessToken, refreshToken } : null; - }, - - write(tokens: AuthTokens): void { - window.localStorage.setItem(ACCESS_TOKEN_KEY, tokens.accessToken); - window.localStorage.setItem(REFRESH_TOKEN_KEY, tokens.refreshToken); - }, - - clear(): void { - window.localStorage.removeItem(ACCESS_TOKEN_KEY); - window.localStorage.removeItem(REFRESH_TOKEN_KEY); - }, -}; diff --git a/apps/admin/src/lib/api.ts b/apps/admin/src/lib/api.ts deleted file mode 100644 index 709e3a9..0000000 --- a/apps/admin/src/lib/api.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { configureApiClient, request } from '@wantere/api-client'; -import { API_PREFIX } from '@wantere/config'; -import { session } from '@/features/auth/session'; - -configureApiClient({ - baseUrl: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:4000', - getAccessToken: () => session.read()?.accessToken ?? null, - onUnauthorized: () => { - session.clear(); - if (typeof window !== 'undefined' && window.location.pathname !== '/login') { - // A hard navigation, so every cached query and in-memory state is dropped - // along with the expired session. - // eslint-disable-next-line @next/next/no-location-assign-relative-destination - window.location.assign('/login'); - } - }, -}); - -export function apiPath(path: string): string { - return `/${API_PREFIX}${path}`; -} - -export { request }; diff --git a/apps/admin/src/lib/cn.ts b/apps/admin/src/lib/cn.ts deleted file mode 100644 index 2509dbc..0000000 --- a/apps/admin/src/lib/cn.ts +++ /dev/null @@ -1,6 +0,0 @@ -import clsx, { type ClassValue } from 'clsx'; -import { twMerge } from 'tailwind-merge'; - -export function cn(...inputs: ClassValue[]): string { - return twMerge(clsx(inputs)); -} diff --git a/apps/admin/src/providers/query-provider.tsx b/apps/admin/src/providers/query-provider.tsx deleted file mode 100644 index af548f9..0000000 --- a/apps/admin/src/providers/query-provider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; - -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { useState, type ReactNode } from 'react'; - -export function QueryProvider({ children }: { children: ReactNode }) { - const [client] = useState( - () => - new QueryClient({ - defaultOptions: { - queries: { - staleTime: 30_000, - retry: 1, - refetchOnWindowFocus: false, - }, - }, - }), - ); - - return {children}; -} diff --git a/apps/admin/src/styles/globals.css b/apps/admin/src/styles/globals.css deleted file mode 100644 index 16a9fc3..0000000 --- a/apps/admin/src/styles/globals.css +++ /dev/null @@ -1,11 +0,0 @@ -@import 'tailwindcss'; -@import '@wantere/design-tokens/css'; - -:root { - color-scheme: light; -} - -body { - background-color: var(--color-neutral-50); - color: var(--color-neutral-900); -} diff --git a/apps/admin/tsconfig.json b/apps/admin/tsconfig.json deleted file mode 100644 index e36421e..0000000 --- a/apps/admin/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "@wantere/typescript-config/nextjs.json", - "compilerOptions": { - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/apps/api/eslint.config.js b/apps/api/eslint.config.js index 14e8734..23da957 100644 --- a/apps/api/eslint.config.js +++ b/apps/api/eslint.config.js @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/nest'; +export { default } from '@p2p-local/eslint-config/nest'; diff --git a/apps/api/openapi.json b/apps/api/openapi.json index 501df9e..44340c6 100644 --- a/apps/api/openapi.json +++ b/apps/api/openapi.json @@ -1267,7 +1267,7 @@ } }, "info": { - "title": "Wantere API", + "title": "P2P Local API", "description": "Local commerce and exchange platform", "version": "1.0", "contact": {} diff --git a/apps/api/package.json b/apps/api/package.json index 2f7d5e8..3d9f511 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/api", + "name": "@p2p-local/api", "version": "0.1.0", "private": true, "license": "MIT", @@ -31,8 +31,8 @@ "@nestjs/throttler": "^6.5.0", "@prisma/adapter-pg": "^7.10.0", "@prisma/client": "^7.10.0", - "@wantere/config": "workspace:*", - "@wantere/types": "workspace:*", + "@p2p-local/config": "workspace:*", + "@p2p-local/types": "workspace:*", "argon2": "^0.45.1", "bullmq": "^6.3.4", "class-transformer": "^0.5.1", @@ -55,8 +55,8 @@ "@types/jest": "^30.0.0", "@types/node": "^26.4.1", "@types/supertest": "^7.2.1", - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "cross-env": "^10.1.0", "dotenv": "^17.2.3", "eslint": "^10.10.0", diff --git a/apps/api/src/bootstrap.ts b/apps/api/src/bootstrap.ts index 2727fea..0fb0948 100644 --- a/apps/api/src/bootstrap.ts +++ b/apps/api/src/bootstrap.ts @@ -4,7 +4,7 @@ import { ConfigService } from '@nestjs/config'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { Logger } from 'nestjs-pino'; import helmet from 'helmet'; -import { API_VERSION } from '@wantere/config'; +import { API_VERSION } from '@p2p-local/config'; import { AppModule } from './app.module'; import type { Env } from './config/env'; @@ -27,7 +27,7 @@ export async function createApp(): Promise { export function buildOpenApiDocument(app: INestApplication) { const config = new DocumentBuilder() - .setTitle('Wantere API') + .setTitle('P2P Local API') .setDescription('Local commerce and exchange platform') .setVersion('1.0') .addBearerAuth() diff --git a/apps/api/src/common/decorators/roles.decorator.ts b/apps/api/src/common/decorators/roles.decorator.ts index 8165ee0..e14fdba 100644 --- a/apps/api/src/common/decorators/roles.decorator.ts +++ b/apps/api/src/common/decorators/roles.decorator.ts @@ -1,5 +1,5 @@ import { SetMetadata } from '@nestjs/common'; -import type { UserRole } from '@wantere/types'; +import type { UserRole } from '@p2p-local/types'; export const ROLES_KEY = 'auth:roles'; diff --git a/apps/api/src/common/dto/pagination.dto.ts b/apps/api/src/common/dto/pagination.dto.ts index a3506ac..d27249b 100644 --- a/apps/api/src/common/dto/pagination.dto.ts +++ b/apps/api/src/common/dto/pagination.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsOptional, Max, Min } from 'class-validator'; -import { PAGINATION } from '@wantere/config'; +import { PAGINATION } from '@p2p-local/config'; export class PaginationQueryDto { @ApiPropertyOptional({ minimum: 1, default: PAGINATION.defaultPage }) diff --git a/apps/api/src/common/guards/jwt-auth.guard.ts b/apps/api/src/common/guards/jwt-auth.guard.ts index ea431d6..573d0b0 100644 --- a/apps/api/src/common/guards/jwt-auth.guard.ts +++ b/apps/api/src/common/guards/jwt-auth.guard.ts @@ -2,7 +2,7 @@ import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from import { Reflector } from '@nestjs/core'; import { JwtService } from '@nestjs/jwt'; import type { Request } from 'express'; -import type { UserRole } from '@wantere/types'; +import type { UserRole } from '@p2p-local/types'; import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; export interface AuthenticatedUser { diff --git a/apps/api/src/common/guards/roles.guard.ts b/apps/api/src/common/guards/roles.guard.ts index c1f654a..2fdf03a 100644 --- a/apps/api/src/common/guards/roles.guard.ts +++ b/apps/api/src/common/guards/roles.guard.ts @@ -1,7 +1,7 @@ import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import type { Request } from 'express'; -import type { UserRole } from '@wantere/types'; +import type { UserRole } from '@p2p-local/types'; import { ROLES_KEY } from '../decorators/roles.decorator'; import type { AuthenticatedUser } from './jwt-auth.guard'; diff --git a/apps/api/src/modules/auth/auth.module.ts b/apps/api/src/modules/auth/auth.module.ts index 2b937c9..2e8e938 100644 --- a/apps/api/src/modules/auth/auth.module.ts +++ b/apps/api/src/modules/auth/auth.module.ts @@ -1,7 +1,7 @@ import { Global, Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtModule } from '@nestjs/jwt'; -import { TOKENS } from '@wantere/config'; +import { TOKENS } from '@p2p-local/config'; import type { Env } from '../../config/env'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; diff --git a/apps/api/src/modules/auth/dto/auth.dto.ts b/apps/api/src/modules/auth/dto/auth.dto.ts index 651440e..715af95 100644 --- a/apps/api/src/modules/auth/dto/auth.dto.ts +++ b/apps/api/src/modules/auth/dto/auth.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsIn, IsOptional, IsString, Length, Matches, MaxLength } from 'class-validator'; -import { OTP } from '@wantere/config'; +import { OTP } from '@p2p-local/config'; const E164 = /^\+[1-9]\d{7,14}$/; diff --git a/apps/api/src/modules/auth/phone-verification.service.ts b/apps/api/src/modules/auth/phone-verification.service.ts index 3e65238..9ba88de 100644 --- a/apps/api/src/modules/auth/phone-verification.service.ts +++ b/apps/api/src/modules/auth/phone-verification.service.ts @@ -1,7 +1,7 @@ import { BadRequestException, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; import { randomInt } from 'node:crypto'; import * as argon2 from 'argon2'; -import { OTP } from '@wantere/config'; +import { OTP } from '@p2p-local/config'; import { PrismaService } from '../../database/prisma.service'; import { RedisService } from '../../infrastructure/redis/redis.service'; import { OTP_PROVIDER, type OtpProvider } from '../../infrastructure/otp/otp.provider'; diff --git a/apps/api/src/modules/auth/session.service.ts b/apps/api/src/modules/auth/session.service.ts index 8fff855..00fa5e3 100644 --- a/apps/api/src/modules/auth/session.service.ts +++ b/apps/api/src/modules/auth/session.service.ts @@ -3,8 +3,8 @@ import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { randomBytes } from 'node:crypto'; import * as argon2 from 'argon2'; -import { TOKENS } from '@wantere/config'; -import type { UserRole } from '@wantere/types'; +import { TOKENS } from '@p2p-local/config'; +import type { UserRole } from '@p2p-local/types'; import { PrismaService } from '../../database/prisma.service'; import type { Env } from '../../config/env'; diff --git a/apps/api/src/modules/listings/dto/create-listing.dto.ts b/apps/api/src/modules/listings/dto/create-listing.dto.ts index 964a203..d2cb876 100644 --- a/apps/api/src/modules/listings/dto/create-listing.dto.ts +++ b/apps/api/src/modules/listings/dto/create-listing.dto.ts @@ -15,8 +15,8 @@ import { MaxLength, Min, } from 'class-validator'; -import { LISTING_LIMITS } from '@wantere/config'; -import { LISTING_CONDITIONS, LISTING_TYPES } from '@wantere/types'; +import { LISTING_LIMITS } from '@p2p-local/config'; +import { LISTING_CONDITIONS, LISTING_TYPES } from '@p2p-local/types'; export class CreateListingDto { @ApiProperty() diff --git a/apps/api/src/modules/listings/dto/search-listings.dto.ts b/apps/api/src/modules/listings/dto/search-listings.dto.ts index 3ad34bf..91ffde4 100644 --- a/apps/api/src/modules/listings/dto/search-listings.dto.ts +++ b/apps/api/src/modules/listings/dto/search-listings.dto.ts @@ -13,7 +13,7 @@ import { MaxLength, Min, } from 'class-validator'; -import { LISTING_CONDITIONS, LISTING_TYPES } from '@wantere/types'; +import { LISTING_CONDITIONS, LISTING_TYPES } from '@p2p-local/types'; import { PaginationQueryDto } from '../../../common/dto/pagination.dto'; const SORTS = ['recent', 'price_asc', 'price_desc', 'distance'] as const; diff --git a/apps/api/src/modules/listings/listing.serializer.ts b/apps/api/src/modules/listings/listing.serializer.ts index 882c0e1..26a053e 100644 --- a/apps/api/src/modules/listings/listing.serializer.ts +++ b/apps/api/src/modules/listings/listing.serializer.ts @@ -1,4 +1,4 @@ -import type { PublicLocation } from '@wantere/types'; +import type { PublicLocation } from '@p2p-local/types'; export interface ListingSummary { id: string; diff --git a/apps/api/src/modules/listings/listings.service.ts b/apps/api/src/modules/listings/listings.service.ts index 6c626a9..4f9dc5c 100644 --- a/apps/api/src/modules/listings/listings.service.ts +++ b/apps/api/src/modules/listings/listings.service.ts @@ -4,8 +4,8 @@ import { Injectable, NotFoundException, } from '@nestjs/common'; -import { DEFAULT_CURRENCY } from '@wantere/config'; -import { requiresPrice, type ListingType } from '@wantere/types'; +import { DEFAULT_CURRENCY } from '@p2p-local/config'; +import { requiresPrice, type ListingType } from '@p2p-local/types'; import { PrismaService } from '../../database/prisma.service'; import { StorageService } from '../../infrastructure/storage/storage.service'; import { LocationsService } from '../locations/locations.service'; @@ -143,7 +143,7 @@ export class ListingsService { })), seller: { id: listing.seller.id, - displayName: listing.seller.profile?.displayName ?? 'Membre Wantere', + displayName: listing.seller.profile?.displayName ?? 'Membre P2P Local', avatarUrl: listing.seller.profile?.avatarKey ? this.storage.publicUrl(listing.seller.profile.avatarKey) : null, diff --git a/apps/api/src/modules/locations/locations.service.spec.ts b/apps/api/src/modules/locations/locations.service.spec.ts index 90d1bf8..548d9ad 100644 --- a/apps/api/src/modules/locations/locations.service.spec.ts +++ b/apps/api/src/modules/locations/locations.service.spec.ts @@ -1,5 +1,5 @@ import { Test } from '@nestjs/testing'; -import { PUBLIC_LOCATION_PRECISION_DEGREES } from '@wantere/config'; +import { PUBLIC_LOCATION_PRECISION_DEGREES } from '@p2p-local/config'; import { LocationsService } from './locations.service'; import { PrismaService } from '../../database/prisma.service'; diff --git a/apps/api/src/modules/locations/locations.service.ts b/apps/api/src/modules/locations/locations.service.ts index cb1ed91..9fb53db 100644 --- a/apps/api/src/modules/locations/locations.service.ts +++ b/apps/api/src/modules/locations/locations.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { DEFAULT_COUNTRY, PUBLIC_LOCATION_PRECISION_DEGREES } from '@wantere/config'; -import type { PublicLocation } from '@wantere/types'; +import { DEFAULT_COUNTRY, PUBLIC_LOCATION_PRECISION_DEGREES } from '@p2p-local/config'; +import type { PublicLocation } from '@p2p-local/types'; import { PrismaService } from '../../database/prisma.service'; export interface LocationInput { diff --git a/apps/api/src/modules/notifications/notifications.service.ts b/apps/api/src/modules/notifications/notifications.service.ts index 101f5ea..f250fa2 100644 --- a/apps/api/src/modules/notifications/notifications.service.ts +++ b/apps/api/src/modules/notifications/notifications.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bullmq'; import type { Queue } from 'bullmq'; -import type { NotificationChannel } from '@wantere/types'; +import type { NotificationChannel } from '@p2p-local/types'; import { PrismaService } from '../../database/prisma.service'; import type { Prisma } from '../../generated/prisma/client'; import { paginate, type PaginationQueryDto } from '../../common/dto/pagination.dto'; diff --git a/apps/api/src/modules/reports/dto/create-report.dto.ts b/apps/api/src/modules/reports/dto/create-report.dto.ts index d53aaa4..8b80994 100644 --- a/apps/api/src/modules/reports/dto/create-report.dto.ts +++ b/apps/api/src/modules/reports/dto/create-report.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsEnum, IsOptional, IsString, IsUUID, MaxLength } from 'class-validator'; -import { REPORT_REASONS, REPORT_TARGETS } from '@wantere/types'; +import { REPORT_REASONS, REPORT_TARGETS } from '@p2p-local/types'; export class CreateReportDto { @ApiProperty({ enum: REPORT_TARGETS }) diff --git a/apps/api/src/modules/users/users.service.ts b/apps/api/src/modules/users/users.service.ts index 1ce15bf..04f8044 100644 --- a/apps/api/src/modules/users/users.service.ts +++ b/apps/api/src/modules/users/users.service.ts @@ -26,7 +26,7 @@ export class UsersService { return { id: user.id, - displayName: user.profile?.displayName ?? 'Membre Wantere', + displayName: user.profile?.displayName ?? 'Membre P2P Local', bio: user.profile?.bio ?? null, city: user.profile?.city ?? null, avatarUrl: user.profile?.avatarKey ? this.storage.publicUrl(user.profile.avatarKey) : null, diff --git a/apps/api/test/setup.ts b/apps/api/test/setup.ts index f11bcc2..3d7f542 100644 --- a/apps/api/test/setup.ts +++ b/apps/api/test/setup.ts @@ -1,7 +1,7 @@ import 'reflect-metadata'; import { ValidationPipe, VersioningType, type INestApplication } from '@nestjs/common'; import { Test } from '@nestjs/testing'; -import { API_PREFIX } from '@wantere/config'; +import { API_PREFIX } from '@p2p-local/config'; import { AppModule } from '../src/app.module'; import { PrismaService } from '../src/database/prisma.service'; import { RedisService } from '../src/infrastructure/redis/redis.service'; diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 423313e..4775af4 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/nestjs.json", + "extends": "@p2p-local/typescript-config/nestjs.json", "compilerOptions": { "paths": { "@/*": ["./src/*"] diff --git a/apps/mobile/.env.example b/apps/mobile/.env.example deleted file mode 100644 index a1d1b65..0000000 --- a/apps/mobile/.env.example +++ /dev/null @@ -1 +0,0 @@ -EXPO_PUBLIC_API_URL=http://localhost:4000 diff --git a/apps/mobile/app.json b/apps/mobile/app.json index ad0d561..400cdf5 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -1,27 +1,69 @@ { "expo": { - "name": "Wantere", - "slug": "wantere", + "name": "P2P Local", + "slug": "p2p-local", "version": "0.1.0", "orientation": "portrait", - "scheme": "wantere", + "scheme": "p2plocal", "userInterfaceStyle": "light", - "platforms": ["ios", "android"], - "newArchEnabled": true, + "platforms": [ + "ios", + "android" + ], + "icon": "./assets/icon.png", + "primaryColor": "#0f7f4d", + "backgroundColor": "#ffffff", "ios": { "supportsTablet": true, - "bundleIdentifier": "com.wantere.app" + "bundleIdentifier": "org.codeforsenegal.p2plocal", + "infoPlist": { + "NSCameraUsageDescription": "L'application utilise l'appareil photo pour la photo de votre annonce.", + "NSPhotoLibraryUsageDescription": "L'application accède à vos photos pour illustrer votre annonce." + } }, "android": { - "package": "com.wantere.app", - "edgeToEdgeEnabled": true + "package": "org.codeforsenegal.p2plocal", + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#0f7f4d" + }, + "permissions": [ + "android.permission.RECORD_AUDIO", + "android.permission.RECORD_AUDIO" + ] }, - "plugins": ["expo-router", "expo-secure-store"], + "plugins": [ + "expo-router", + [ + "expo-image-picker", + { + "photosPermission": "L'application accède à vos photos pour illustrer votre annonce.", + "cameraPermission": "L'application utilise l'appareil photo pour la photo de votre annonce." + } + ], + [ + "expo-splash-screen", + { + "image": "./assets/splash-icon.png", + "imageWidth": 200, + "resizeMode": "contain", + "backgroundColor": "#ffffff" + } + ] + ], "experiments": { "typedRoutes": true }, "extra": { - "apiUrl": "http://localhost:4000/api/v1" + "eas": { + "projectId": "30a30237-579b-4046-ace2-ff2dab825bac" + } + }, + "runtimeVersion": { + "policy": "appVersion" + }, + "updates": { + "url": "https://u.expo.dev/30a30237-579b-4046-ace2-ff2dab825bac" } } } diff --git a/apps/mobile/app/(tabs)/_layout.tsx b/apps/mobile/app/(tabs)/_layout.tsx index fe6c245..e75c7a7 100644 --- a/apps/mobile/app/(tabs)/_layout.tsx +++ b/apps/mobile/app/(tabs)/_layout.tsx @@ -1,5 +1,5 @@ import { Tabs } from 'expo-router'; -import { colors } from '@wantere/design-tokens'; +import { colors } from '@p2p-local/design-tokens'; export default function TabsLayout() { return ( @@ -11,9 +11,9 @@ export default function TabsLayout() { }} > - - - + + + ); } diff --git a/apps/mobile/app/(tabs)/campagne.tsx b/apps/mobile/app/(tabs)/campagne.tsx new file mode 100644 index 0000000..124ef6f --- /dev/null +++ b/apps/mobile/app/(tabs)/campagne.tsx @@ -0,0 +1,25 @@ +import { ScrollView, StyleSheet, Text } from 'react-native'; +import { colors, fontSize, spacing } from '@p2p-local/design-tokens'; + +/** + * A campaign is a time-boxed editorial page, never a special code path through + * the listings. The copy is a placeholder until the team writes the real one. + */ +export default function CampaignScreen() { + return ( + + Campagne + + Cette page présentera la campagne en cours : ce qu’elle demande, la période, et les + quartiers concernés. + + Le contenu reste à écrire. + + ); +} + +const styles = StyleSheet.create({ + screen: { padding: spacing[6], gap: spacing[3], backgroundColor: colors.neutral[0] }, + title: { fontSize: fontSize.xl, fontWeight: '600', color: colors.neutral[900] }, + body: { fontSize: fontSize.base, color: colors.neutral[600] }, +}); diff --git a/apps/mobile/app/(tabs)/echanges.tsx b/apps/mobile/app/(tabs)/echanges.tsx new file mode 100644 index 0000000..05476f2 --- /dev/null +++ b/apps/mobile/app/(tabs)/echanges.tsx @@ -0,0 +1,75 @@ +import { Alert, FlatList, Pressable, StyleSheet, Text, View } from 'react-native'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; +import { ListingCard } from '@/components/listing-card'; +import { + useListings, + useMarkAsCompleted, + useRemoveListing, +} from '@/features/listings/use-listings'; + +export default function MyListingsScreen() { + // Every listing on this device was published from it, so "mine" is the whole + // document until listings can come from a server. + const listings = useListings({}); + const complete = useMarkAsCompleted(); + const remove = useRemoveListing(); + + return ( + item.id} + renderItem={({ item }) => ( + + + + {item.status === 'ACTIVE' ? ( + complete.mutate(item.id)}> + Marquer comme donné + + ) : null} + + Alert.alert( + 'Supprimer cette annonce ?', + 'Elle sera effacée immédiatement, avec sa photo. Cette action est irréversible.', + [ + { text: 'Annuler', style: 'cancel' }, + { + text: 'Supprimer', + style: 'destructive', + onPress: () => remove.mutate(item.id), + }, + ], + ) + } + > + Supprimer + + + + )} + ListEmptyComponent={ + Vous n’avez pas encore publié d’annonce. + } + /> + ); +} + +const styles = StyleSheet.create({ + list: { padding: spacing[4], gap: spacing[4], backgroundColor: colors.neutral[50] }, + row: { gap: spacing[2] }, + actions: { flexDirection: 'row', gap: spacing[2] }, + action: { + paddingVertical: spacing[2], + paddingHorizontal: spacing[3], + borderRadius: radius.md, + borderWidth: 1, + borderColor: colors.neutral[300], + backgroundColor: colors.neutral[0], + }, + actionLabel: { fontSize: fontSize.sm, color: colors.neutral[700] }, + danger: { color: colors.danger[500] }, + empty: { color: colors.neutral[500], textAlign: 'center', marginTop: spacing[10] }, +}); diff --git a/apps/mobile/app/(tabs)/favorites.tsx b/apps/mobile/app/(tabs)/favorites.tsx deleted file mode 100644 index 4e3086d..0000000 --- a/apps/mobile/app/(tabs)/favorites.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { StyleSheet, Text, View } from 'react-native'; -import { colors, spacing } from '@wantere/design-tokens'; - -export default function FavoritesScreen() { - return ( - - Connectez-vous pour retrouver vos annonces favorites. - - ); -} - -const styles = StyleSheet.create({ - container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: spacing[6] }, - text: { color: colors.neutral[500], textAlign: 'center' }, -}); diff --git a/apps/mobile/app/(tabs)/index.tsx b/apps/mobile/app/(tabs)/index.tsx index e15de80..e95847e 100644 --- a/apps/mobile/app/(tabs)/index.tsx +++ b/apps/mobile/app/(tabs)/index.tsx @@ -1,38 +1,94 @@ -import { ActivityIndicator, FlatList, StyleSheet, Text, View } from 'react-native'; -import { colors, spacing } from '@wantere/design-tokens'; -import { useListings } from '@/features/listings/use-listings'; +import { useEffect } from 'react'; +import { Link } from 'expo-router'; +import { ActivityIndicator, FlatList, StyleSheet, Text, TextInput, View } from 'react-native'; +import { neighborhoodName } from '@p2p-local/config'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; import { ListingCard } from '@/components/listing-card'; +import { TypeFilter } from '@/components/type-filter'; +import { useListings } from '@/features/listings/use-listings'; +import { useListingRepository } from '@/features/listings/listing-repository.context'; +import { useSearchFilters } from '@/stores/search-filters.store'; export default function HomeScreen() { - const listings = useListings(); + const { query, type, neighborhoodId, setQuery, setType } = useSearchFilters(); + const repository = useListingRepository(); + const listings = useListings({ query, type, neighborhoodId }); - if (listings.isPending) { - return ( - - - - ); - } + useEffect(() => { + // Expired and long-completed listings move out of the way on launch. + void repository.archiveExpired(); + }, [repository]); return ( - item.id} - renderItem={({ item }) => } - ListEmptyComponent={ - - {listings.isError - ? 'Les annonces sont indisponibles pour le moment.' - : 'Aucune annonce publiée près de vous.'} - - } - /> + + + + {neighborhoodName(neighborhoodId)} ▾ + + + + + + {listings.isPending ? ( + + ) : ( + item.id} + renderItem={({ item }) => } + ListEmptyComponent={ + + Aucune annonce dans ce quartier pour le moment.{'\n\n'} + Les annonces sont enregistrées sur cet appareil : celles publiées depuis un autre + téléphone n’apparaissent pas ici. + + } + /> + )} + + + + Publier une annonce + + ); } const styles = StyleSheet.create({ + screen: { flex: 1, backgroundColor: colors.neutral[50] }, + header: { paddingHorizontal: spacing[4], paddingTop: spacing[3], gap: spacing[2] }, + neighborhood: { fontSize: fontSize.base, fontWeight: '600', color: colors.brand[700] }, + search: { + borderWidth: 1, + borderColor: colors.neutral[300], + borderRadius: radius.md, + paddingHorizontal: spacing[3], + paddingVertical: spacing[2], + backgroundColor: colors.neutral[0], + color: colors.neutral[900], + }, + loader: { marginTop: spacing[10] }, list: { padding: spacing[4], gap: spacing[3] }, - centered: { flex: 1, alignItems: 'center', justifyContent: 'center' }, - empty: { color: colors.neutral[500], textAlign: 'center', marginTop: spacing[10] }, + empty: { + color: colors.neutral[500], + textAlign: 'center', + marginTop: spacing[10], + fontSize: fontSize.sm, + }, + publish: { + margin: spacing[4], + padding: spacing[4], + borderRadius: radius.lg, + backgroundColor: colors.brand[600], + color: colors.neutral[0], + textAlign: 'center', + fontWeight: '700', + overflow: 'hidden', + }, }); diff --git a/apps/mobile/app/(tabs)/profil.tsx b/apps/mobile/app/(tabs)/profil.tsx new file mode 100644 index 0000000..1edb64d --- /dev/null +++ b/apps/mobile/app/(tabs)/profil.tsx @@ -0,0 +1,72 @@ +import { useState } from 'react'; +import { Alert, Pressable, ScrollView, StyleSheet, Text, TextInput } from 'react-native'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; +import { useContactProfile } from '@/features/contact/contact-profile'; + +export default function ProfileScreen() { + const { profile, isLoading, save } = useContactProfile(); + // Edits win, the stored profile fills the gap: deriving avoids an effect that + // would write state back into the component on every load. + const [edits, setEdits] = useState<{ firstName?: string; phone?: string }>({}); + const firstName = edits.firstName ?? profile?.firstName ?? ''; + const phone = edits.phone ?? profile?.phone ?? ''; + + const setFirstName = (value: string) => setEdits((current) => ({ ...current, firstName: value })); + const setPhone = (value: string) => setEdits((current) => ({ ...current, phone: value })); + + async function submit() { + try { + await save({ firstName, phone }); + Alert.alert('Enregistré', 'Vos coordonnées sont gardées sur cet appareil.'); + } catch { + Alert.alert('Coordonnées invalides', 'Vérifiez le prénom et le numéro (ex. 77 123 45 67).'); + } + } + + return ( + + Prénom + + + Numéro WhatsApp + + + + Votre numéro n’est jamais affiché dans une annonce ni dans un message partagé. Il sert + uniquement à ouvrir WhatsApp quand quelqu’un vous contacte. + + + + Enregistrer + + + ); +} + +const styles = StyleSheet.create({ + screen: { padding: spacing[4], gap: spacing[2], backgroundColor: colors.neutral[0] }, + label: { fontSize: fontSize.sm, fontWeight: '600', color: colors.neutral[700], marginTop: spacing[3] }, + input: { + borderWidth: 1, + borderColor: colors.neutral[300], + borderRadius: radius.md, + padding: spacing[3], + color: colors.neutral[900], + }, + note: { fontSize: fontSize.xs, color: colors.neutral[500], marginTop: spacing[3] }, + primary: { + marginTop: spacing[5], + padding: spacing[4], + borderRadius: radius.lg, + backgroundColor: colors.brand[600], + alignItems: 'center', + }, + primaryLabel: { color: colors.neutral[0], fontWeight: '700' }, +}); diff --git a/apps/mobile/app/(tabs)/profile.tsx b/apps/mobile/app/(tabs)/profile.tsx deleted file mode 100644 index 624af82..0000000 --- a/apps/mobile/app/(tabs)/profile.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { StyleSheet, Text, View } from 'react-native'; -import { colors, spacing } from '@wantere/design-tokens'; - -export default function ProfileScreen() { - return ( - - Le compte membre arrive avec l’authentification par SMS. - - ); -} - -const styles = StyleSheet.create({ - container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: spacing[6] }, - text: { color: colors.neutral[500], textAlign: 'center' }, -}); diff --git a/apps/mobile/app/(tabs)/search.tsx b/apps/mobile/app/(tabs)/search.tsx deleted file mode 100644 index 72f0982..0000000 --- a/apps/mobile/app/(tabs)/search.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { FlatList, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native'; -import { colors, fontSize, radius, spacing } from '@wantere/design-tokens'; -import { useCategories } from '@/features/categories/use-categories'; -import { useListings } from '@/features/listings/use-listings'; -import { useSearchFilters } from '@/stores/search-filters.store'; -import { ListingCard } from '@/components/listing-card'; - -export default function SearchScreen() { - const { query, setQuery, categoryId, setCategory } = useSearchFilters(); - const categories = useCategories(); - - const listings = useListings({ - q: query.length >= 2 ? query : undefined, - categoryId: categoryId ?? undefined, - }); - - return ( - - - - - {categories.data?.map((category) => { - const selected = category.id === categoryId; - return ( - setCategory(selected ? null : category.id)} - style={[styles.chip, selected && styles.chipSelected]} - > - - {category.name} - - - ); - })} - - - item.id} - renderItem={({ item }) => } - ListEmptyComponent={Aucun résultat.} - /> - - ); -} - -const styles = StyleSheet.create({ - container: { flex: 1, padding: spacing[4] }, - input: { - borderWidth: 1, - borderColor: colors.neutral[200], - borderRadius: radius.md, - paddingHorizontal: spacing[3], - paddingVertical: spacing[3], - backgroundColor: colors.neutral[0], - }, - chips: { flexGrow: 0, marginTop: spacing[3] }, - chip: { - borderWidth: 1, - borderColor: colors.neutral[200], - borderRadius: radius.full, - paddingHorizontal: spacing[3], - paddingVertical: spacing[2], - marginRight: spacing[2], - backgroundColor: colors.neutral[0], - }, - chipSelected: { backgroundColor: colors.brand[600], borderColor: colors.brand[600] }, - chipLabel: { fontSize: fontSize.sm, color: colors.neutral[700] }, - chipLabelSelected: { color: colors.neutral[0] }, - list: { paddingVertical: spacing[4], gap: spacing[3] }, - empty: { color: colors.neutral[500], textAlign: 'center', marginTop: spacing[8] }, -}); diff --git a/apps/mobile/app/_layout.tsx b/apps/mobile/app/_layout.tsx index fedbaf2..70df1ff 100644 --- a/apps/mobile/app/_layout.tsx +++ b/apps/mobile/app/_layout.tsx @@ -11,6 +11,16 @@ export default function RootLayout() { + {/* Modal routes rather than Modal components: the Android back + button then works without any extra code. */} + + diff --git a/apps/mobile/app/listing/[id].tsx b/apps/mobile/app/listing/[id].tsx index aa82393..21dbc0d 100644 --- a/apps/mobile/app/listing/[id].tsx +++ b/apps/mobile/app/listing/[id].tsx @@ -1,57 +1,129 @@ import { useLocalSearchParams } from 'expo-router'; -import { useQuery } from '@tanstack/react-query'; -import { ActivityIndicator, ScrollView, StyleSheet, Text, View } from 'react-native'; -import { colors, fontSize, spacing } from '@wantere/design-tokens'; -import { apiPath, request } from '@/lib/api'; -import { formatPrice } from '@/lib/format'; -import type { ListingSummary } from '@/features/listings/use-listings'; - -interface ListingDetail extends ListingSummary { - description: string; - seller: { id: string; displayName: string }; -} +import { Image } from 'expo-image'; +import { ActivityIndicator, Pressable, ScrollView, Share, StyleSheet, Text, View } from 'react-native'; +import { neighborhoodName } from '@p2p-local/config'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; +import { useListing } from '@/features/listings/use-listings'; +import { canBeContacted } from '@/features/listings/listing-lifecycle'; +import { + buildContactMessage, + buildShareText, + buildWhatsAppUrl, + openWhatsApp, +} from '@/features/contact/whatsapp'; +import { useContactProfile } from '@/features/contact/contact-profile'; +import { formatAge, formatListingBadge } from '@/lib/format'; +import { photoUri } from '@/lib/photos'; export default function ListingScreen() { const { id } = useLocalSearchParams<{ id: string }>(); - - const listing = useQuery({ - queryKey: ['listing', id], - queryFn: () => request(apiPath(`/listings/${id}`)), - enabled: Boolean(id), - }); + const listing = useListing(id); + const { profile } = useContactProfile(); if (listing.isPending) { - return ( - - - - ); + return ; } - if (listing.isError || !listing.data) { - return ( - - Annonce introuvable. - - ); + if (!listing.data) { + return Cette annonce n’existe plus.; + } + + const item = listing.data; + const badge = formatListingBadge(item.type, item.price); + // Expiry is reconciled by archiveExpired() on launch, so the status is what + // the screen reads; the clock is checked in the handler, not during render. + const contactable = item.status === 'ACTIVE'; + + async function contact() { + if (!canBeContacted(item, Date.now())) return; + // The number is never rendered: it goes straight into the link. + const message = buildContactMessage({ + firstName: profile?.firstName ?? 'un voisin', + listingTitle: item.title, + }); + await openWhatsApp(buildWhatsAppUrl(item.authorPhone, message)); } return ( - - {listing.data.title} - {formatPrice(listing.data.price, listing.data.type)} - {listing.data.location?.displayName} - {listing.data.description} - Publié par {listing.data.seller.displayName} + + + {item.photoFileName ? ( + + ) : null} + + + {item.status === 'COMPLETED' ? 'Complété' : badge} + {item.title} + + {neighborhoodName(item.neighborhoodId)} · {formatAge(item.createdAt)} + + {item.description ? {item.description} : null} + + + + {contactable ? 'Contacter sur WhatsApp' : 'Annonce clôturée'} + + + + + L’application ne vous demandera jamais d’acompte ni de code Wave ou Orange Money par + message. + + + + Share.share({ + message: buildShareText({ + title: item.title, + badge, + neighborhoodName: neighborhoodName(item.neighborhoodId), + }), + }) + } + > + Partager + ); } const styles = StyleSheet.create({ - container: { padding: spacing[4], gap: spacing[2] }, - centered: { flex: 1, alignItems: 'center', justifyContent: 'center' }, + screen: { padding: spacing[4], gap: spacing[2], backgroundColor: colors.neutral[0] }, + loader: { marginTop: spacing[10] }, + missing: { margin: spacing[6], color: colors.neutral[500], textAlign: 'center' }, + photo: { + height: 220, + borderRadius: radius.lg, + backgroundColor: colors.neutral[100], + overflow: 'hidden', + }, + image: { width: '100%', height: '100%' }, + badge: { fontSize: fontSize.sm, fontWeight: '700', color: colors.brand[600], marginTop: spacing[3] }, title: { fontSize: fontSize.xl, fontWeight: '600', color: colors.neutral[900] }, - price: { fontSize: fontSize.lg, fontWeight: '600', color: colors.brand[600] }, - description: { marginTop: spacing[3], color: colors.neutral[800], lineHeight: 22 }, - muted: { color: colors.neutral[500] }, + meta: { fontSize: fontSize.sm, color: colors.neutral[500] }, + description: { fontSize: fontSize.base, color: colors.neutral[700], marginTop: spacing[2] }, + primary: { + marginTop: spacing[5], + padding: spacing[4], + borderRadius: radius.lg, + backgroundColor: colors.brand[600], + alignItems: 'center', + }, + disabled: { backgroundColor: colors.neutral[300] }, + primaryLabel: { color: colors.neutral[0], fontWeight: '700' }, + safety: { fontSize: fontSize.xs, color: colors.neutral[500], textAlign: 'center' }, + secondary: { + marginTop: spacing[2], + padding: spacing[3], + borderRadius: radius.md, + borderWidth: 1, + borderColor: colors.brand[600], + alignItems: 'center', + }, + secondaryLabel: { color: colors.brand[700], fontWeight: '600' }, }); diff --git a/apps/mobile/app/neighborhood.tsx b/apps/mobile/app/neighborhood.tsx new file mode 100644 index 0000000..e066264 --- /dev/null +++ b/apps/mobile/app/neighborhood.tsx @@ -0,0 +1,44 @@ +import { router } from 'expo-router'; +import { FlatList, Pressable, StyleSheet, Text } from 'react-native'; +import { SENEGAL_NEIGHBORHOODS } from '@p2p-local/config'; +import { colors, fontSize, spacing } from '@p2p-local/design-tokens'; +import { useSearchFilters } from '@/stores/search-filters.store'; + +export default function NeighborhoodScreen() { + const { neighborhoodId, setNeighborhood } = useSearchFilters(); + + return ( + item.id} + renderItem={({ item }) => ( + { + setNeighborhood(item.id); + router.back(); + }} + style={styles.row} + > + + {item.name} + + {item.department} + + )} + /> + ); +} + +const styles = StyleSheet.create({ + list: { backgroundColor: colors.neutral[0] }, + row: { + paddingVertical: spacing[3], + paddingHorizontal: spacing[4], + borderBottomWidth: 1, + borderBottomColor: colors.neutral[100], + }, + name: { fontSize: fontSize.base, color: colors.neutral[900] }, + selected: { color: colors.brand[600], fontWeight: '700' }, + department: { fontSize: fontSize.xs, color: colors.neutral[500] }, +}); diff --git a/apps/mobile/app/publish.tsx b/apps/mobile/app/publish.tsx new file mode 100644 index 0000000..ce972c0 --- /dev/null +++ b/apps/mobile/app/publish.tsx @@ -0,0 +1,176 @@ +import { useState } from 'react'; +import { router } from 'expo-router'; +import { Image } from 'expo-image'; +import { + Alert, + Pressable, + ScrollView, + StyleSheet, + Text, + TextInput, + View, +} from 'react-native'; +import { SENEGAL_NEIGHBORHOODS, DEFAULT_NEIGHBORHOOD_ID } from '@p2p-local/config'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; +import { requiresPrice, type ListingType } from '@p2p-local/types'; +import { LISTING_TYPE_LABELS, TypeFilter } from '@/components/type-filter'; +import { draftListingSchema } from '@/features/listings/listing.schema'; +import { usePublishListing } from '@/features/listings/use-listings'; +import { useContactProfile } from '@/features/contact/contact-profile'; +import { photoUri, pickPhotoFromLibrary, takePhoto } from '@/lib/photos'; + +export default function PublishScreen() { + const [photoFileName, setPhotoFileName] = useState(null); + const [type, setType] = useState('DONATION'); + const [neighborhoodId, setNeighborhoodId] = useState(DEFAULT_NEIGHBORHOOD_ID); + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [price, setPrice] = useState(''); + + const publish = usePublishListing(); + const { profile } = useContactProfile(); + + async function submit() { + if (profile === null) { + Alert.alert( + 'Votre numéro WhatsApp', + 'Renseignez votre prénom et votre numéro dans l’onglet Profil : ils servent à vous joindre, et ne sont jamais affichés sur vos annonces.', + ); + return; + } + + const parsed = draftListingSchema.safeParse({ + title, + description, + type, + price: type !== null && requiresPrice(type) ? Number(price.replace(/\D/g, '')) : null, + neighborhoodId, + photoFileName, + }); + + if (!parsed.success) { + Alert.alert('Annonce incomplète', parsed.error.issues[0]?.message ?? 'Vérifiez les champs.'); + return; + } + + await publish.mutateAsync({ draft: parsed.data, author: profile }); + router.back(); + } + + return ( + + Photo + + {photoFileName ? ( + + ) : null} + setPhotoFileName((await takePhoto()) ?? photoFileName)} + > + Prendre une photo + + setPhotoFileName((await pickPhotoFromLibrary()) ?? photoFileName)} + > + Choisir dans la galerie + + + + Type + + + Quartier + + {SENEGAL_NEIGHBORHOODS.map((neighborhood) => ( + setNeighborhoodId(neighborhood.id)} + style={[styles.chip, neighborhood.id === neighborhoodId && styles.chipSelected]} + > + + {neighborhood.name} + + + ))} + + + Titre + + + {type !== null && requiresPrice(type) ? ( + <> + Prix coûtant (FCFA) + + + ) : null} + + Description + + + + + {publish.isPending ? 'Publication…' : `Publier — ${type ? LISTING_TYPE_LABELS[type] : ''}`} + + + + ); +} + +const styles = StyleSheet.create({ + form: { padding: spacing[4], gap: spacing[2], backgroundColor: colors.neutral[0] }, + label: { fontSize: fontSize.sm, fontWeight: '600', color: colors.neutral[700], marginTop: spacing[3] }, + photoRow: { gap: spacing[2] }, + photo: { width: '100%', height: 180, borderRadius: radius.md, backgroundColor: colors.neutral[100] }, + input: { + borderWidth: 1, + borderColor: colors.neutral[300], + borderRadius: radius.md, + padding: spacing[3], + color: colors.neutral[900], + }, + multiline: { minHeight: 96, textAlignVertical: 'top' }, + chips: { gap: spacing[2], paddingVertical: spacing[2] }, + chip: { + paddingVertical: spacing[2], + paddingHorizontal: spacing[3], + borderRadius: radius.full, + borderWidth: 1, + borderColor: colors.neutral[300], + }, + chipSelected: { backgroundColor: colors.brand[600], borderColor: colors.brand[600] }, + chipLabel: { fontSize: fontSize.sm, color: colors.neutral[700] }, + chipLabelSelected: { color: colors.neutral[0], fontWeight: '600' }, + secondary: { + borderWidth: 1, + borderColor: colors.brand[600], + borderRadius: radius.md, + padding: spacing[3], + alignItems: 'center', + }, + secondaryLabel: { color: colors.brand[700], fontWeight: '600' }, + primary: { + marginTop: spacing[6], + padding: spacing[4], + borderRadius: radius.lg, + backgroundColor: colors.brand[600], + alignItems: 'center', + }, + primaryLabel: { color: colors.neutral[0], fontWeight: '700' }, +}); diff --git a/apps/mobile/assets/adaptive-icon.png b/apps/mobile/assets/adaptive-icon.png new file mode 100644 index 0000000..8193852 Binary files /dev/null and b/apps/mobile/assets/adaptive-icon.png differ diff --git a/apps/mobile/assets/icon.png b/apps/mobile/assets/icon.png new file mode 100644 index 0000000..65f6145 Binary files /dev/null and b/apps/mobile/assets/icon.png differ diff --git a/apps/mobile/assets/splash-icon.png b/apps/mobile/assets/splash-icon.png new file mode 100644 index 0000000..b598dd9 Binary files /dev/null and b/apps/mobile/assets/splash-icon.png differ diff --git a/apps/mobile/components/listing-card.tsx b/apps/mobile/components/listing-card.tsx index 36569cd..fe0ce8c 100644 --- a/apps/mobile/components/listing-card.tsx +++ b/apps/mobile/components/listing-card.tsx @@ -1,26 +1,33 @@ import { Link } from 'expo-router'; -import { Image, Pressable, StyleSheet, Text, View } from 'react-native'; -import { colors, fontSize, radius, spacing } from '@wantere/design-tokens'; -import { formatPrice } from '@/lib/format'; -import type { ListingSummary } from '@/features/listings/use-listings'; +import { Image } from 'expo-image'; +import { Pressable, StyleSheet, Text, View } from 'react-native'; +import { neighborhoodName } from '@p2p-local/config'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; +import { formatAge, formatListingBadge } from '@/lib/format'; +import { photoUri } from '@/lib/photos'; +import type { LocalListing } from '@/features/listings/listing.types'; + +export function ListingCard({ listing }: { listing: LocalListing }) { + const completed = listing.status === 'COMPLETED'; -export function ListingCard({ listing }: { listing: ListingSummary }) { return ( - + - {listing.coverUrl ? ( - + {listing.photoFileName ? ( + ) : null} {listing.title} - {formatPrice(listing.price, listing.type)} - {listing.location ? ( - {listing.location.displayName} - ) : null} + + {completed ? 'Complété' : formatListingBadge(listing.type, listing.price)} + + + {neighborhoodName(listing.neighborhoodId)} · {formatAge(listing.createdAt)} + @@ -37,6 +44,7 @@ const styles = StyleSheet.create({ borderColor: colors.neutral[200], padding: spacing[3], }, + completed: { opacity: 0.55 }, thumbnail: { width: 88, height: 88, @@ -47,6 +55,6 @@ const styles = StyleSheet.create({ image: { width: '100%', height: '100%' }, body: { flex: 1, gap: spacing[1] }, title: { fontSize: fontSize.base, fontWeight: '500', color: colors.neutral[900] }, - price: { fontSize: fontSize.base, fontWeight: '600', color: colors.brand[600] }, - location: { fontSize: fontSize.xs, color: colors.neutral[500] }, + badge: { fontSize: fontSize.sm, fontWeight: '600', color: colors.brand[600] }, + meta: { fontSize: fontSize.xs, color: colors.neutral[500] }, }); diff --git a/apps/mobile/components/type-filter.tsx b/apps/mobile/components/type-filter.tsx new file mode 100644 index 0000000..1b2a3be --- /dev/null +++ b/apps/mobile/components/type-filter.tsx @@ -0,0 +1,52 @@ +import { Pressable, ScrollView, StyleSheet, Text } from 'react-native'; +import { LISTING_TYPES, type ListingType } from '@p2p-local/types'; +import { colors, fontSize, radius, spacing } from '@p2p-local/design-tokens'; + +const LABELS: Record = { + DONATION: 'Donner', + BARTER: 'Troquer', + SALE: 'Prix coûtant', + REQUEST: 'Besoin', +}; + +export function TypeFilter({ + value, + onChange, +}: { + value: ListingType | null; + onChange: (type: ListingType | null) => void; +}) { + return ( + + {LISTING_TYPES.map((type) => { + const selected = value === type; + return ( + onChange(selected ? null : type)} + style={[styles.chip, selected && styles.selected]} + > + {LABELS[type]} + + ); + })} + + ); +} + +export { LABELS as LISTING_TYPE_LABELS }; + +const styles = StyleSheet.create({ + row: { gap: spacing[2], paddingVertical: spacing[2] }, + chip: { + paddingVertical: spacing[2], + paddingHorizontal: spacing[3], + borderRadius: radius.full, + borderWidth: 1, + borderColor: colors.neutral[300], + backgroundColor: colors.neutral[0], + }, + selected: { backgroundColor: colors.brand[600], borderColor: colors.brand[600] }, + label: { fontSize: fontSize.sm, color: colors.neutral[700] }, + selectedLabel: { color: colors.neutral[0], fontWeight: '600' }, +}); diff --git a/apps/mobile/eas.json b/apps/mobile/eas.json new file mode 100644 index 0000000..4aade13 --- /dev/null +++ b/apps/mobile/eas.json @@ -0,0 +1,30 @@ +{ + "cli": { + "version": ">= 16.0.0", + "appVersionSource": "remote", + "requireCommit": true + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "channel": "development", + "android": { "buildType": "apk" }, + "ios": { "simulator": true } + }, + "preview": { + "distribution": "internal", + "channel": "preview", + "android": { "buildType": "apk" } + }, + "production": { + "distribution": "store", + "channel": "production", + "autoIncrement": true, + "android": { "buildType": "app-bundle" } + } + }, + "submit": { + "production": {} + } +} diff --git a/apps/mobile/eslint.config.mjs b/apps/mobile/eslint.config.mjs index 62aa021..a4fb561 100644 --- a/apps/mobile/eslint.config.mjs +++ b/apps/mobile/eslint.config.mjs @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/react-native'; +export { default } from '@p2p-local/eslint-config/react-native'; diff --git a/apps/mobile/features/categories/use-categories.ts b/apps/mobile/features/categories/use-categories.ts deleted file mode 100644 index 7e848f4..0000000 --- a/apps/mobile/features/categories/use-categories.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import { apiPath, request } from '@/lib/api'; - -export interface CategoryNode { - id: string; - name: string; - slug: string; - icon: string | null; - children: CategoryNode[]; -} - -export function useCategories() { - return useQuery({ - queryKey: ['categories'], - queryFn: () => request(apiPath('/categories')), - staleTime: 5 * 60_000, - }); -} diff --git a/apps/mobile/features/contact/contact-profile.ts b/apps/mobile/features/contact/contact-profile.ts new file mode 100644 index 0000000..2d81ba6 --- /dev/null +++ b/apps/mobile/features/contact/contact-profile.ts @@ -0,0 +1,45 @@ +import { useCallback, useEffect, useState } from 'react'; +import { deviceStore, storageKeys } from '@/lib/storage'; +import { listingAuthorSchema } from '@/features/listings/listing.schema'; +import type { ListingAuthor } from '@/features/listings/listing.types'; + +/** + * First name and WhatsApp number, typed once and kept on the device. It is what + * a listing copies at publication, and what pre-fills a contact message. + */ +export function useContactProfile() { + const [profile, setProfile] = useState(null); + const [isLoading, setLoading] = useState(true); + + useEffect(() => { + let cancelled = false; + + void (async () => { + const raw = await deviceStore.getItem(storageKeys.contactProfile); + if (cancelled) return; + + if (raw !== null) { + try { + const parsed = listingAuthorSchema.safeParse(JSON.parse(raw)); + if (parsed.success) setProfile(parsed.data); + } catch { + // A malformed profile is simply asked for again. + } + } + setLoading(false); + })(); + + return () => { + cancelled = true; + }; + }, []); + + const save = useCallback(async (input: { firstName: string; phone: string }) => { + const author = listingAuthorSchema.parse(input); + await deviceStore.setItem(storageKeys.contactProfile, JSON.stringify(author)); + setProfile(author); + return author; + }, []); + + return { profile, isLoading, save }; +} diff --git a/apps/mobile/features/contact/whatsapp.spec.ts b/apps/mobile/features/contact/whatsapp.spec.ts new file mode 100644 index 0000000..25714c4 --- /dev/null +++ b/apps/mobile/features/contact/whatsapp.spec.ts @@ -0,0 +1,42 @@ +import { buildContactMessage, buildShareText, buildWhatsAppUrl, toWaMeNumber } from './whatsapp'; + +describe('toWaMeNumber', () => { + it('keeps digits only', () => { + expect(toWaMeNumber('+221771234567')).toBe('221771234567'); + }); +}); + +describe('buildWhatsAppUrl', () => { + it('carries the message, encoded', () => { + const url = buildWhatsAppUrl('+221771234567', 'Bonjour, je suis Aïssatou.'); + expect(url).toBe('https://wa.me/221771234567?text=Bonjour%2C%20je%20suis%20A%C3%AFssatou.'); + }); +}); + +describe('buildContactMessage', () => { + it('names the listing so the recipient can place the contact', () => { + expect(buildContactMessage({ firstName: 'Aïssatou', listingTitle: 'Manuel de maths' })).toBe( + 'Bonjour, je suis Aïssatou. Je vous contacte pour votre annonce : Manuel de maths.', + ); + }); + + it('does not carry a phone number', () => { + const message = buildContactMessage({ firstName: 'Aïssatou', listingTitle: 'Manuel' }); + expect(message).not.toMatch(/\d{6,}/); + }); +}); + +describe('buildShareText', () => { + it('describes the listing without ever leaking a number', () => { + const text = buildShareText({ + title: 'Manuel de maths 3e', + badge: 'Gratuit / don', + neighborhoodName: 'Parcelles Assainies', + }); + + expect(text).toContain('Manuel de maths 3e'); + expect(text).toContain('Parcelles Assainies'); + // The guard that matters: a shared listing must not be a phone directory. + expect(text).not.toMatch(/\d{6,}/); + }); +}); diff --git a/apps/mobile/features/contact/whatsapp.ts b/apps/mobile/features/contact/whatsapp.ts new file mode 100644 index 0000000..b6f2eff --- /dev/null +++ b/apps/mobile/features/contact/whatsapp.ts @@ -0,0 +1,43 @@ +import { Linking } from 'react-native'; + +/** + * The only module that touches a phone number. + * + * A number shown in clear invites scraping, cold calling and the Wave/Orange + * Money scams that follow — and it exposes women first. Nothing here returns a + * number for display: it goes into a URL and nowhere else. + */ +export function toWaMeNumber(e164: string): string { + // wa.me wants digits only: no plus sign, no spaces. + return e164.replace(/\D/g, ''); +} + +export function buildContactMessage(input: { firstName: string; listingTitle: string }): string { + return `Bonjour, je suis ${input.firstName}. Je vous contacte pour votre annonce : ${input.listingTitle}.`; +} + +export function buildWhatsAppUrl(e164: string, message: string): string { + return `https://wa.me/${toWaMeNumber(e164)}?text=${encodeURIComponent(message)}`; +} + +/** What gets pasted into a neighbourhood group. Never a phone number. */ +export function buildShareText(input: { + title: string; + badge: string; + neighborhoodName: string; +}): string { + return `${input.title} — ${input.badge}\n${input.neighborhoodName}\nPartagé depuis P2P Local.`; +} + +export async function openWhatsApp(url: string): Promise { + // Never probe with the whatsapp:// scheme: since Android 11 package + // visibility makes canOpenURL answer false even when WhatsApp is installed. + // An https://wa.me link always opens — WhatsApp catches it, the browser + // takes over otherwise. + try { + await Linking.openURL(url); + return true; + } catch { + return false; + } +} diff --git a/apps/mobile/features/listings/async-storage-listing-repository.spec.ts b/apps/mobile/features/listings/async-storage-listing-repository.spec.ts new file mode 100644 index 0000000..da0dca4 --- /dev/null +++ b/apps/mobile/features/listings/async-storage-listing-repository.spec.ts @@ -0,0 +1,103 @@ +import { createMemoryStore, storageKeys } from '@/lib/storage'; +import { AsyncStorageListingRepository } from './async-storage-listing-repository'; +import { ListingNotFoundError } from './listing-repository'; +import type { DraftListing } from './listing.schema'; + +const NOW = new Date('2026-09-18T12:00:00.000Z').getTime(); + +const author = { firstName: 'Moussa', phone: '+221771234567' }; + +const draft: DraftListing = { + title: 'Manuel de maths 3e', + description: 'En bon état', + type: 'DONATION', + price: null, + neighborhoodId: 'medina', + photoFileName: null, +}; + +function repository(initial: Record = {}) { + let counter = 0; + return new AsyncStorageListingRepository( + createMemoryStore(initial), + () => NOW, + () => `id-${++counter}`, + ); +} + +describe('creating a listing', () => { + it('reads back exactly what was written', async () => { + const repo = repository(); + const created = await repo.create(draft, author); + + expect(await repo.findById(created.id)).toEqual(created); + expect(created.status).toBe('ACTIVE'); + expect(created.ownerKey).not.toBe(created.id); + expect(new Date(created.expiresAt).getTime()).toBeGreaterThan(NOW); + }); + + it('survives concurrent writes', async () => { + const repo = repository(); + await Promise.all([ + repo.create(draft, author), + repo.create({ ...draft, title: 'Cahiers' }, author), + repo.create({ ...draft, title: 'Sac' }, author), + ]); + + expect(await repo.list()).toHaveLength(3); + }); +}); + +describe('filtering', () => { + it('matches on type, district and title, ignoring accents and case', async () => { + const repo = repository(); + await repo.create(draft, author); + await repo.create( + { ...draft, title: 'Sac à dos', type: 'SALE', price: 3000, neighborhoodId: 'grand-yoff' }, + author, + ); + + expect(await repo.list({ type: 'SALE' })).toHaveLength(1); + expect(await repo.list({ neighborhoodId: 'medina' })).toHaveLength(1); + expect(await repo.list({ query: 'MATHS' })).toHaveLength(1); + expect(await repo.list({ query: 'sac a dos' })).toHaveLength(1); + }); +}); + +describe('the lifecycle', () => { + it('keeps a completed listing visible, then archives it', async () => { + const repo = repository(); + const created = await repo.create(draft, author); + await repo.markAsCompleted(created.id); + + expect(await repo.list()).toHaveLength(1); + + const later = new AsyncStorageListingRepository( + // Same document, read three days later. + createMemoryStore({ + [storageKeys.listings]: JSON.stringify([ + { ...created, status: 'COMPLETED', completedAt: new Date(NOW).toISOString() }, + ]), + }), + () => NOW + 3 * 24 * 3_600_000, + ); + + expect(await later.list()).toHaveLength(0); + expect(await later.archiveExpired()).toBe(1); + }); + + it('raises when updating a listing that is gone', async () => { + const repo = repository(); + await expect(repo.markAsCompleted('missing')).rejects.toBeInstanceOf(ListingNotFoundError); + }); +}); + +describe('a corrupted document', () => { + it('reads as empty instead of taking the home screen down', async () => { + const broken = repository({ [storageKeys.listings]: '{ not json' }); + expect(await broken.list()).toEqual([]); + + const wrongShape = repository({ [storageKeys.listings]: JSON.stringify([{ id: 1 }]) }); + expect(await wrongShape.list()).toEqual([]); + }); +}); diff --git a/apps/mobile/features/listings/async-storage-listing-repository.ts b/apps/mobile/features/listings/async-storage-listing-repository.ts new file mode 100644 index 0000000..7f30d62 --- /dev/null +++ b/apps/mobile/features/listings/async-storage-listing-repository.ts @@ -0,0 +1,159 @@ +import { deviceStore, storageKeys, type KeyValueStore } from '@/lib/storage'; +import { newId } from '@/lib/ids'; +import { storedListingsSchema, type DraftListing } from './listing.schema'; +import { archiveDue, expiryFor, isVisible } from './listing-lifecycle'; +import { + ListingNotFoundError, + type ListingPatch, + type ListingRepository, +} from './listing-repository'; +import type { ListingAuthor, ListingFilter, LocalListing } from './listing.types'; + +function normalise(value: string): string { + return value + .toLowerCase() + .normalize('NFD') + .replace(/[̀-ͯ]/g, ''); +} + +/** + * One JSON document under one key. + * + * A device holds a handful of listings, so a key per listing would be + * optimisation without a problem to solve. Writes are chained behind a single + * promise: two taps in a row must not lose one another's result. + */ +export class AsyncStorageListingRepository implements ListingRepository { + private queue: Promise = Promise.resolve(); + + constructor( + private readonly store: KeyValueStore = deviceStore, + private readonly now: () => number = Date.now, + private readonly generateId: () => string = newId, + ) {} + + async list(filter: ListingFilter = {}): Promise { + const now = this.now(); + const all = await this.read(); + const status = filter.status ?? 'VISIBLE'; + const query = filter.query ? normalise(filter.query.trim()) : ''; + + return all + .filter((listing) => (status === 'VISIBLE' ? isVisible(listing, now) : listing.status === status)) + .filter((listing) => !filter.type || listing.type === filter.type) + .filter( + (listing) => !filter.neighborhoodId || listing.neighborhoodId === filter.neighborhoodId, + ) + .filter((listing) => !query || normalise(listing.title).includes(query)) + .sort((a, b) => b.createdAt.localeCompare(a.createdAt)); + } + + async findById(id: string): Promise { + const all = await this.read(); + return all.find((listing) => listing.id === id) ?? null; + } + + async create(input: DraftListing, author: ListingAuthor): Promise { + const createdAt = new Date(this.now()).toISOString(); + const listing: LocalListing = { + id: this.generateId(), + ownerKey: this.generateId(), + source: 'device', + title: input.title, + description: input.description, + type: input.type, + price: input.price, + neighborhoodId: input.neighborhoodId, + photoFileName: input.photoFileName, + authorFirstName: author.firstName, + authorPhone: author.phone, + status: 'ACTIVE', + createdAt, + updatedAt: createdAt, + completedAt: null, + expiresAt: expiryFor(createdAt), + }; + + await this.write((all) => [listing, ...all]); + return listing; + } + + async update(id: string, patch: ListingPatch): Promise { + return this.replace(id, (listing) => ({ + ...listing, + ...patch, + updatedAt: new Date(this.now()).toISOString(), + })); + } + + async markAsCompleted(id: string): Promise { + const at = new Date(this.now()).toISOString(); + return this.replace(id, (listing) => ({ + ...listing, + status: 'COMPLETED', + completedAt: at, + updatedAt: at, + })); + } + + async remove(id: string): Promise { + await this.write((all) => all.filter((listing) => listing.id !== id)); + } + + async archiveExpired(): Promise { + const now = this.now(); + let archived = 0; + + await this.write((all) => + all.map((listing) => { + if (!archiveDue(listing, now)) return listing; + archived += 1; + return { ...listing, status: 'ARCHIVED', updatedAt: new Date(now).toISOString() }; + }), + ); + + return archived; + } + + private async replace( + id: string, + change: (listing: LocalListing) => LocalListing, + ): Promise { + let updated: LocalListing | null = null; + + await this.write((all) => + all.map((listing) => { + if (listing.id !== id) return listing; + updated = change(listing); + return updated; + }), + ); + + if (updated === null) throw new ListingNotFoundError(id); + return updated; + } + + private async read(): Promise { + const raw = await this.store.getItem(storageKeys.listings); + if (raw === null) return []; + + try { + // A payload written by an older build, or corrupted, must not take the + // home screen down with it. + const parsed = storedListingsSchema.safeParse(JSON.parse(raw)); + return parsed.success ? parsed.data : []; + } catch { + return []; + } + } + + private write(change: (all: LocalListing[]) => LocalListing[]): Promise { + const next = this.queue.then(async () => { + const all = await this.read(); + await this.store.setItem(storageKeys.listings, JSON.stringify(change(all))); + }); + + this.queue = next.catch(() => undefined); + return next; + } +} diff --git a/apps/mobile/features/listings/listing-lifecycle.spec.ts b/apps/mobile/features/listings/listing-lifecycle.spec.ts new file mode 100644 index 0000000..e90522e --- /dev/null +++ b/apps/mobile/features/listings/listing-lifecycle.spec.ts @@ -0,0 +1,55 @@ +import { archiveDue, canBeContacted, isVisible } from './listing-lifecycle'; +import type { LocalListing } from './listing.types'; + +const now = new Date('2026-09-18T12:00:00.000Z').getTime(); +const at = (hoursAgo: number) => new Date(now - hoursAgo * 3_600_000).toISOString(); + +function listing(overrides: Partial = {}): LocalListing { + return { + id: 'a', + ownerKey: 'k', + source: 'device', + title: 'Manuel', + description: '', + type: 'DONATION', + price: null, + neighborhoodId: 'medina', + photoFileName: null, + authorFirstName: 'Moussa', + authorPhone: '+221771234567', + status: 'ACTIVE', + createdAt: at(1), + updatedAt: at(1), + completedAt: null, + expiresAt: new Date(now + 3_600_000).toISOString(), + ...overrides, + }; +} + +describe('an active listing', () => { + it('is visible and can be contacted until it expires', () => { + expect(isVisible(listing(), now)).toBe(true); + expect(canBeContacted(listing(), now)).toBe(true); + }); + + it('is due for archiving once past its expiry', () => { + const expired = listing({ expiresAt: at(1) }); + expect(isVisible(expired, now)).toBe(false); + expect(archiveDue(expired, now)).toBe(true); + }); +}); + +describe('a completed listing', () => { + it('stays visible for the grace period, but cannot be contacted', () => { + const completed = listing({ status: 'COMPLETED', completedAt: at(2) }); + expect(isVisible(completed, now)).toBe(true); + expect(canBeContacted(completed, now)).toBe(false); + expect(archiveDue(completed, now)).toBe(false); + }); + + it('is archived once the grace period is over', () => { + const completed = listing({ status: 'COMPLETED', completedAt: at(72) }); + expect(isVisible(completed, now)).toBe(false); + expect(archiveDue(completed, now)).toBe(true); + }); +}); diff --git a/apps/mobile/features/listings/listing-lifecycle.ts b/apps/mobile/features/listings/listing-lifecycle.ts new file mode 100644 index 0000000..de7466c --- /dev/null +++ b/apps/mobile/features/listings/listing-lifecycle.ts @@ -0,0 +1,36 @@ +import { COMPLETED_LISTING_GRACE_HOURS, LISTING_TTL_DAYS } from '@p2p-local/config'; +import type { LocalListing } from './listing.types'; + +const HOUR = 3_600_000; +const DAY = 24 * HOUR; + +export function expiryFor(createdAt: string): string { + return new Date(new Date(createdAt).getTime() + LISTING_TTL_DAYS * DAY).toISOString(); +} + +/** + * A completed listing stays visible, greyed out, for a couple of days: showing + * what the neighbourhood actually passed on is part of the product, not noise. + */ +export function isWithinCompletedGrace(listing: LocalListing, now: number): boolean { + if (listing.completedAt === null) return false; + return now - new Date(listing.completedAt).getTime() < COMPLETED_LISTING_GRACE_HOURS * HOUR; +} + +/** Listings nobody should see any more, without deleting anything. */ +export function archiveDue(listing: LocalListing, now: number): boolean { + if (listing.status === 'ARCHIVED') return false; + if (listing.status === 'COMPLETED') return !isWithinCompletedGrace(listing, now); + return new Date(listing.expiresAt).getTime() <= now; +} + +export function isVisible(listing: LocalListing, now: number): boolean { + if (listing.status === 'ARCHIVED') return false; + if (listing.status === 'COMPLETED') return isWithinCompletedGrace(listing, now); + return new Date(listing.expiresAt).getTime() > now; +} + +/** A completed listing can no longer be contacted. */ +export function canBeContacted(listing: LocalListing, now: number): boolean { + return listing.status === 'ACTIVE' && isVisible(listing, now); +} diff --git a/apps/mobile/features/listings/listing-repository.context.tsx b/apps/mobile/features/listings/listing-repository.context.tsx new file mode 100644 index 0000000..9984f64 --- /dev/null +++ b/apps/mobile/features/listings/listing-repository.context.tsx @@ -0,0 +1,31 @@ +import { createContext, useContext, useMemo, type ReactNode } from 'react'; +import { AsyncStorageListingRepository } from './async-storage-listing-repository'; +import type { ListingRepository } from './listing-repository'; + +const ListingRepositoryContext = createContext(null); + +/** + * The one place that decides where listings live. Swapping the device for a + * server is this line, not a rewrite of the screens. + */ +export function ListingRepositoryProvider({ + children, + repository, +}: { + children: ReactNode; + repository?: ListingRepository; +}) { + const value = useMemo(() => repository ?? new AsyncStorageListingRepository(), [repository]); + + return ( + {children} + ); +} + +export function useListingRepository(): ListingRepository { + const repository = useContext(ListingRepositoryContext); + if (repository === null) { + throw new Error('useListingRepository must be used inside ListingRepositoryProvider'); + } + return repository; +} diff --git a/apps/mobile/features/listings/listing-repository.ts b/apps/mobile/features/listings/listing-repository.ts new file mode 100644 index 0000000..b5bfafd --- /dev/null +++ b/apps/mobile/features/listings/listing-repository.ts @@ -0,0 +1,35 @@ +import type { DraftListing } from './listing.schema'; +import type { ListingAuthor, ListingFilter, LocalListing } from './listing.types'; + +export type ListingPatch = Partial< + Pick +>; + +/** + * The seam between the screens and wherever listings live. + * + * Three rules keep it useful the day a server appears: + * - every method is asynchronous, even those that need not be, so an HTTP + * implementation substitutes without changing a signature; + * - filtering happens here, never in a screen, because a filter becomes a + * query string once a server answers; + * - no screen imports the store. The implementation is injected through a + * React context. + */ +export interface ListingRepository { + list(filter?: ListingFilter): Promise; + findById(id: string): Promise; + create(input: DraftListing, author: ListingAuthor): Promise; + update(id: string, patch: ListingPatch): Promise; + markAsCompleted(id: string): Promise; + remove(id: string): Promise; + /** Moves anything past its date to ARCHIVED. Returns how many moved. */ + archiveExpired(): Promise; +} + +export class ListingNotFoundError extends Error { + constructor(id: string) { + super(`Listing ${id} not found`); + this.name = 'ListingNotFoundError'; + } +} diff --git a/apps/mobile/features/listings/listing.schema.ts b/apps/mobile/features/listings/listing.schema.ts new file mode 100644 index 0000000..e39c0c3 --- /dev/null +++ b/apps/mobile/features/listings/listing.schema.ts @@ -0,0 +1,54 @@ +import { z } from 'zod'; +import { LISTING_LIMITS } from '@p2p-local/config'; +import { LISTING_TYPES, requiresPrice } from '@p2p-local/types'; +import { senegalMobileSchema } from '@p2p-local/validation'; + +export const listingTypeSchema = z.enum(LISTING_TYPES); + +/** What the publish form collects. Four fields, plus a price when it applies. */ +export const draftListingSchema = z + .object({ + title: z.string().trim().min(LISTING_LIMITS.titleMin).max(LISTING_LIMITS.titleMax), + // 600 characters, not the API's 5000: this is a phone keyboard. + description: z.string().trim().max(600).default(''), + type: listingTypeSchema, + price: z.number().int().min(0).max(LISTING_LIMITS.maxPrice).nullable().default(null), + neighborhoodId: z.string().min(1), + photoFileName: z.string().nullable().default(null), + }) + .refine((value) => !requiresPrice(value.type) || value.price !== null, { + message: 'Indiquez le prix coûtant', + path: ['price'], + }) + .refine((value) => requiresPrice(value.type) || value.price === null, { + message: 'Un don ou un troc n’a pas de prix', + path: ['price'], + }); + +export type DraftListing = z.infer; + +export const storedListingSchema = z.object({ + id: z.string().min(1), + ownerKey: z.string().min(1), + source: z.literal('device'), + title: z.string(), + description: z.string(), + type: listingTypeSchema, + price: z.number().nullable(), + neighborhoodId: z.string(), + photoFileName: z.string().nullable(), + authorFirstName: z.string(), + authorPhone: z.string(), + status: z.enum(['ACTIVE', 'COMPLETED', 'ARCHIVED']), + createdAt: z.string(), + updatedAt: z.string(), + completedAt: z.string().nullable(), + expiresAt: z.string(), +}); + +export const storedListingsSchema = z.array(storedListingSchema); + +export const listingAuthorSchema = z.object({ + firstName: z.string().trim().min(1, 'Indiquez votre prénom').max(40), + phone: senegalMobileSchema, +}); diff --git a/apps/mobile/features/listings/listing.types.ts b/apps/mobile/features/listings/listing.types.ts new file mode 100644 index 0000000..9bf6056 --- /dev/null +++ b/apps/mobile/features/listings/listing.types.ts @@ -0,0 +1,46 @@ +import type { ListingType } from '@p2p-local/types'; + +/** The subset of LISTING_STATUSES a device-held listing can be in. */ +export type LocalListingStatus = 'ACTIVE' | 'COMPLETED' | 'ARCHIVED'; + +export interface LocalListing { + id: string; + /** + * Written at publication. Storage is already private to the device today, so + * this buys nothing yet; it exists so access control is in the model and in + * the UI before a server needs it, rather than bolted on afterwards. + */ + ownerKey: string; + /** Discriminant: leaves room for listings coming from a server later. */ + source: 'device'; + title: string; + description: string; + type: ListingType; + /** Integer XOF. Required for SALE, absent otherwise. */ + price: number | null; + neighborhoodId: string; + /** File name only — never an absolute URI. See lib/photos.ts. */ + photoFileName: string | null; + authorFirstName: string; + /** E.164. Never rendered; only used to build a wa.me link. */ + authorPhone: string; + status: LocalListingStatus; + createdAt: string; + updatedAt: string; + /** Set when the listing is marked as completed; drives the 48 h grace. */ + completedAt: string | null; + expiresAt: string; +} + +export interface ListingAuthor { + firstName: string; + phone: string; +} + +export interface ListingFilter { + type?: ListingType | null; + neighborhoodId?: string | null; + query?: string; + /** Defaults to the listings worth showing: ACTIVE and COMPLETED. */ + status?: LocalListingStatus | 'VISIBLE'; +} diff --git a/apps/mobile/features/listings/use-listings.ts b/apps/mobile/features/listings/use-listings.ts index b5f305d..8c0f30d 100644 --- a/apps/mobile/features/listings/use-listings.ts +++ b/apps/mobile/features/listings/use-listings.ts @@ -1,38 +1,56 @@ -import { useQuery } from '@tanstack/react-query'; -import type { Paginated } from '@wantere/types'; -import { apiPath, request } from '@/lib/api'; - -export interface ListingSummary { - id: string; - title: string; - type: string; - price: number | null; - currency: string; - coverUrl: string | null; - distanceMeters: number | null; - location: { displayName: string } | null; -} +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useListingRepository } from './listing-repository.context'; +import type { DraftListing } from './listing.schema'; +import type { ListingAuthor, ListingFilter } from './listing.types'; + +const LISTINGS = ['listings'] as const; + +export function useListings(filter: ListingFilter = {}) { + const repository = useListingRepository(); -export interface ListingQuery { - q?: string; - categoryId?: string; - latitude?: number; - longitude?: number; - radius?: number; + return useQuery({ + queryKey: [...LISTINGS, filter], + queryFn: () => repository.list(filter), + }); } -export function useListings(query: ListingQuery = {}) { +export function useListing(id: string | undefined) { + const repository = useListingRepository(); + return useQuery({ - queryKey: ['listings', query], - queryFn: () => { - const params = new URLSearchParams(); - for (const [key, value] of Object.entries(query)) { - if (value !== undefined && value !== '') { - params.set(key, String(value)); - } - } - const suffix = params.toString(); - return request>(apiPath(`/listings${suffix ? `?${suffix}` : ''}`)); - }, + queryKey: [...LISTINGS, 'detail', id], + queryFn: () => repository.findById(id as string), + enabled: Boolean(id), + }); +} + +export function usePublishListing() { + const repository = useListingRepository(); + const client = useQueryClient(); + + return useMutation({ + mutationFn: ({ draft, author }: { draft: DraftListing; author: ListingAuthor }) => + repository.create(draft, author), + onSuccess: () => client.invalidateQueries({ queryKey: LISTINGS }), + }); +} + +export function useMarkAsCompleted() { + const repository = useListingRepository(); + const client = useQueryClient(); + + return useMutation({ + mutationFn: (id: string) => repository.markAsCompleted(id), + onSuccess: () => client.invalidateQueries({ queryKey: LISTINGS }), + }); +} + +export function useRemoveListing() { + const repository = useListingRepository(); + const client = useQueryClient(); + + return useMutation({ + mutationFn: (id: string) => repository.remove(id), + onSuccess: () => client.invalidateQueries({ queryKey: LISTINGS }), }); } diff --git a/apps/mobile/jest.setup.js b/apps/mobile/jest.setup.js new file mode 100644 index 0000000..262ddab --- /dev/null +++ b/apps/mobile/jest.setup.js @@ -0,0 +1,5 @@ +// AsyncStorage is a native module: without this, any suite that imports it +// fails to run with "NativeModule: AsyncStorage is null". +jest.mock('@react-native-async-storage/async-storage', () => + require('@react-native-async-storage/async-storage/jest/async-storage-mock'), +); diff --git a/apps/mobile/lib/api.ts b/apps/mobile/lib/api.ts deleted file mode 100644 index c9cb8f1..0000000 --- a/apps/mobile/lib/api.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { configureApiClient, request } from '@wantere/api-client'; -import { API_PREFIX } from '@wantere/config'; -import { tokenStore } from './token-store'; - -configureApiClient({ - baseUrl: process.env.EXPO_PUBLIC_API_URL ?? 'http://localhost:4000', - getAccessToken: () => tokenStore.getAccessToken(), - onUnauthorized: () => tokenStore.clear(), -}); - -export function apiPath(path: string): string { - return `/${API_PREFIX}${path}`; -} - -export { request }; diff --git a/apps/mobile/lib/format.spec.ts b/apps/mobile/lib/format.spec.ts new file mode 100644 index 0000000..dc1e197 --- /dev/null +++ b/apps/mobile/lib/format.spec.ts @@ -0,0 +1,34 @@ +import { formatAge, formatAmount, formatListingBadge } from './format'; + +describe('formatAmount', () => { + it('groups thousands with a plain space and the local currency label', () => { + expect(formatAmount(3000)).toBe('3 000 FCFA'); + expect(formatAmount(1250000)).toBe('1 250 000 FCFA'); + expect(formatAmount(500)).toBe('500 FCFA'); + }); +}); + +describe('formatListingBadge', () => { + it('never shows a price for a donation or a barter', () => { + expect(formatListingBadge('DONATION', null)).toBe('Gratuit / don'); + expect(formatListingBadge('BARTER', null)).toBe('Troc'); + expect(formatListingBadge('REQUEST', null)).toBe('Besoin'); + }); + + it('shows the cost price for a sale', () => { + expect(formatListingBadge('SALE', 3000)).toBe('Prix coûtant : 3 000 FCFA'); + }); +}); + +describe('formatAge', () => { + const now = new Date('2026-09-18T12:00:00.000Z').getTime(); + const ago = (ms: number) => new Date(now - ms).toISOString(); + + it('reads in minutes, hours then days', () => { + expect(formatAge(ago(30_000), now)).toBe("À l'instant"); + expect(formatAge(ago(20 * 60_000), now)).toBe('Il y a 20 min'); + expect(formatAge(ago(2 * 3_600_000), now)).toBe('Il y a 2 h'); + expect(formatAge(ago(24 * 3_600_000), now)).toBe('Hier'); + expect(formatAge(ago(3 * 24 * 3_600_000), now)).toBe('Il y a 3 j'); + }); +}); diff --git a/apps/mobile/lib/format.ts b/apps/mobile/lib/format.ts index aa8a0a5..fc99d6b 100644 --- a/apps/mobile/lib/format.ts +++ b/apps/mobile/lib/format.ts @@ -1,11 +1,46 @@ -const formatter = new Intl.NumberFormat('fr-SN', { - style: 'currency', - currency: 'XOF', - maximumFractionDigits: 0, -}); - -export function formatPrice(price: number | null, type: string): string { - if (type === 'DONATION') return 'Don'; - if (type === 'BARTER') return 'Troc'; - return price === null ? 'Prix à discuter' : formatter.format(price); +import type { ListingType } from '@p2p-local/types'; + +/** + * Amounts are formatted by hand. + * + * `Intl.NumberFormat('fr-SN', { currency: 'XOF' })` cannot be relied on: the + * locale is not guaranteed in the ICU bundled with Hermes, and its output + * ("3 000 F CFA") is not what the product says ("3 000 FCFA"). + */ +export function formatAmount(amount: number): string { + const digits = Math.round(amount).toString(); + const grouped = digits.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); + return `${grouped} FCFA`; +} + +export function formatListingBadge(type: ListingType, price: number | null): string { + switch (type) { + case 'DONATION': + return 'Gratuit / don'; + case 'BARTER': + return 'Troc'; + case 'REQUEST': + return 'Besoin'; + case 'SALE': + return price === null ? 'Prix coûtant' : `Prix coûtant : ${formatAmount(price)}`; + } +} + +const MINUTE = 60_000; +const HOUR = 60 * MINUTE; +const DAY = 24 * HOUR; + +/** "Il y a 2 h". Written out rather than left to Intl.RelativeTimeFormat. */ +export function formatAge(iso: string, now: number = Date.now()): string { + const elapsed = Math.max(0, now - new Date(iso).getTime()); + + if (elapsed < HOUR) { + const minutes = Math.floor(elapsed / MINUTE); + return minutes < 1 ? "À l'instant" : `Il y a ${minutes} min`; + } + if (elapsed < DAY) { + return `Il y a ${Math.floor(elapsed / HOUR)} h`; + } + const days = Math.floor(elapsed / DAY); + return days === 1 ? 'Hier' : `Il y a ${days} j`; } diff --git a/apps/mobile/lib/ids.ts b/apps/mobile/lib/ids.ts new file mode 100644 index 0000000..2e62f21 --- /dev/null +++ b/apps/mobile/lib/ids.ts @@ -0,0 +1,6 @@ +import * as Crypto from 'expo-crypto'; + +/** Hermes does not guarantee globalThis.crypto.randomUUID, expo-crypto does. */ +export function newId(): string { + return Crypto.randomUUID(); +} diff --git a/apps/mobile/lib/photos.ts b/apps/mobile/lib/photos.ts new file mode 100644 index 0000000..735796c --- /dev/null +++ b/apps/mobile/lib/photos.ts @@ -0,0 +1,67 @@ +import * as ImagePicker from 'expo-image-picker'; +import { Directory, File, Paths } from 'expo-file-system'; +import { newId } from './ids'; + +const PHOTOS = new Directory(Paths.document, 'listing-photos'); + +function ensureDirectory(): void { + if (!PHOTOS.exists) PHOTOS.create({ intermediates: true }); +} + +/** + * Copies a picked image into the application sandbox and returns its file name. + * + * Two traps are avoided here. The picker hands back a URI in the cache + * directory, which the system may reclaim, so the file has to be copied. And + * only the file name is stored, never the absolute URI: on iOS the container + * UUID changes on every app update, which would break every stored path at + * once. + */ +export function persistPickedPhoto(pickedUri: string): string { + ensureDirectory(); + const extension = pickedUri.split('.').pop()?.toLowerCase() ?? 'jpg'; + const fileName = `${newId()}.${extension.length <= 4 ? extension : 'jpg'}`; + + new File(pickedUri).copy(new File(PHOTOS, fileName)); + return fileName; +} + +export function photoUri(fileName: string): string { + return new File(PHOTOS, fileName).uri; +} + +export function deletePhoto(fileName: string): void { + const file = new File(PHOTOS, fileName); + if (file.exists) file.delete(); +} + +// Entry-level Android, metered data: the full-resolution original has no reason +// to be kept. +const PICKER_OPTIONS: ImagePicker.ImagePickerOptions = { + mediaTypes: ['images'], + allowsEditing: true, + aspect: [4, 3], + quality: 0.6, +}; + +export async function pickPhotoFromLibrary(): Promise { + const permission = await ImagePicker.requestMediaLibraryPermissionsAsync(); + if (!permission.granted) return null; + + const result = await ImagePicker.launchImageLibraryAsync(PICKER_OPTIONS); + const asset = result.canceled ? undefined : result.assets[0]; + if (!asset) return null; + + return persistPickedPhoto(asset.uri); +} + +export async function takePhoto(): Promise { + const permission = await ImagePicker.requestCameraPermissionsAsync(); + if (!permission.granted) return null; + + const result = await ImagePicker.launchCameraAsync(PICKER_OPTIONS); + const asset = result.canceled ? undefined : result.assets[0]; + if (!asset) return null; + + return persistPickedPhoto(asset.uri); +} diff --git a/apps/mobile/lib/storage.ts b/apps/mobile/lib/storage.ts new file mode 100644 index 0000000..d0348a4 --- /dev/null +++ b/apps/mobile/lib/storage.ts @@ -0,0 +1,35 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; + +/** + * The minimum a store has to do. Declaring it here rather than importing + * AsyncStorage everywhere keeps the repository testable without a native mock. + */ +export interface KeyValueStore { + getItem(key: string): Promise; + setItem(key: string, value: string): Promise; + removeItem(key: string): Promise; +} + +export const deviceStore: KeyValueStore = AsyncStorage; + +const NAMESPACE = 'p2p-local'; + +/** + * The `.v1` suffix is the migration strategy: an incompatible change writes to + * `.v2` and leaves the old document untouched, so a bad release cannot destroy + * what someone published. + */ +export const storageKeys = { + listings: `${NAMESPACE}.listings.v1`, + contactProfile: `${NAMESPACE}.contact-profile.v1`, + neighborhood: `${NAMESPACE}.neighborhood.v1`, +} as const; + +export function createMemoryStore(initial: Record = {}): KeyValueStore { + const data = new Map(Object.entries(initial)); + return { + getItem: async (key) => data.get(key) ?? null, + setItem: async (key, value) => void data.set(key, value), + removeItem: async (key) => void data.delete(key), + }; +} diff --git a/apps/mobile/lib/token-store.ts b/apps/mobile/lib/token-store.ts deleted file mode 100644 index 72a7a50..0000000 --- a/apps/mobile/lib/token-store.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as SecureStore from 'expo-secure-store'; - -const ACCESS_TOKEN_KEY = 'wantere.accessToken'; -const REFRESH_TOKEN_KEY = 'wantere.refreshToken'; - -let cachedAccessToken: string | null = null; - -/** - * Tokens live in the keychain, never in the Zustand store: client state and - * credentials have different lifetimes and different security requirements. - */ -export const tokenStore = { - async getAccessToken(): Promise { - cachedAccessToken ??= await SecureStore.getItemAsync(ACCESS_TOKEN_KEY); - return cachedAccessToken; - }, - - getRefreshToken(): Promise { - return SecureStore.getItemAsync(REFRESH_TOKEN_KEY); - }, - - async save(tokens: { accessToken: string; refreshToken: string }): Promise { - cachedAccessToken = tokens.accessToken; - await SecureStore.setItemAsync(ACCESS_TOKEN_KEY, tokens.accessToken); - await SecureStore.setItemAsync(REFRESH_TOKEN_KEY, tokens.refreshToken); - }, - - async clear(): Promise { - cachedAccessToken = null; - await SecureStore.deleteItemAsync(ACCESS_TOKEN_KEY); - await SecureStore.deleteItemAsync(REFRESH_TOKEN_KEY); - }, -}; diff --git a/apps/mobile/package.json b/apps/mobile/package.json index a2cb386..48e4e77 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/mobile", + "name": "@p2p-local/mobile", "version": "0.1.0", "private": true, "license": "MIT", @@ -10,31 +10,53 @@ "ios": "expo start --ios", "build": "expo export --platform ios --platform android --output-dir dist", "lint": "eslint app components features lib providers stores", - "typecheck": "tsc -p tsconfig.json --noEmit" + "typecheck": "tsc -p tsconfig.json --noEmit", + "assets:build": "python3 scripts/build-app-assets.py", + "test": "jest --passWithNoTests", + "eas-build-post-install": "cd ../.. && pnpm exec turbo run build --filter=@p2p-local/config --filter=@p2p-local/design-tokens --filter=@p2p-local/types --filter=@p2p-local/validation" }, "dependencies": { + "@p2p-local/config": "workspace:*", + "@p2p-local/design-tokens": "workspace:*", + "@p2p-local/types": "workspace:*", + "@p2p-local/validation": "workspace:*", "@react-native-async-storage/async-storage": "2.2.0", "@tanstack/react-query": "^5.102.8", - "@wantere/api-client": "workspace:*", - "@wantere/config": "workspace:*", - "@wantere/design-tokens": "workspace:*", - "@wantere/types": "workspace:*", - "@wantere/validation": "workspace:*", - "expo": "^57.0.20", - "expo-router": "~57.0.19", - "expo-secure-store": "~57.0.3", + "expo": "^57.0.24", + "expo-constants": "~57.0.19", + "expo-crypto": "~57.0.0", + "expo-file-system": "~57.0.7", + "expo-image": "~57.0.0", + "expo-image-picker": "~57.0.19", + "expo-linking": "~57.0.10", + "expo-router": "~57.0.22", + "expo-splash-screen": "~57.0.0", "expo-status-bar": "~57.0.1", + "expo-updates": "~57.0.23", "react": "19.2.3", "react-native": "0.86.3", "react-native-safe-area-context": "~5.7.0", "react-native-screens": "~4.26.2", + "zod": "^4.5.4", "zustand": "^5.0.15" }, "devDependencies": { + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", + "@types/jest": "^29.5.14", "@types/react": "^19.2.18", - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", "eslint": "^10.10.0", + "jest": "^29.7.0", + "jest-expo": "~57.0.0", "typescript": "~6.0.3" + }, + "jest": { + "preset": "jest-expo", + "moduleNameMapper": { + "^@/(.*)$": "/$1" + }, + "setupFiles": [ + "/jest.setup.js" + ] } } diff --git a/apps/mobile/providers/app-providers.tsx b/apps/mobile/providers/app-providers.tsx index 121245e..e0d2b4c 100644 --- a/apps/mobile/providers/app-providers.tsx +++ b/apps/mobile/providers/app-providers.tsx @@ -1,15 +1,22 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useState, type ReactNode } from 'react'; +import { ListingRepositoryProvider } from '@/features/listings/listing-repository.context'; export function AppProviders({ children }: { children: ReactNode }) { const [client] = useState( () => new QueryClient({ defaultOptions: { - queries: { staleTime: 30_000, retry: 1 }, + // Nothing is fetched over a network in V1: a failed read is a bug, + // not a flaky connection. + queries: { staleTime: 30_000, retry: 0 }, }, }), ); - return {children}; + return ( + + {children} + + ); } diff --git a/apps/mobile/scripts/build-app-assets.py b/apps/mobile/scripts/build-app-assets.py new file mode 100644 index 0000000..f2d591f --- /dev/null +++ b/apps/mobile/scripts/build-app-assets.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +"""Generate the application icons from the shared design tokens. + +The mark is drawn, not typeset: a font would make the output depend on what is +installed on the machine, and these PNGs are committed. Running this script on +any machine with Pillow must produce the same bytes. + + python3 scripts/build-app-assets.py +""" + +from __future__ import annotations + +import json +import math +import pathlib +import re + +from PIL import Image, ImageDraw + +ROOT = pathlib.Path(__file__).resolve().parents[1] +TOKENS = ROOT.parent.parent / "packages" / "design-tokens" / "src" / "colors.ts" +ASSETS = ROOT / "assets" + +TRANSPARENT = (0, 0, 0, 0) +SUPERSAMPLE = 4 + + +def token(path: str) -> tuple[int, int, int, int]: + """Read one colour from the design tokens, so the icons cannot drift.""" + group, shade = path.split(".") + source = TOKENS.read_text() + block = re.search(rf"{group}:\s*{{(.*?)}}", source, re.S) + if block is None: + raise SystemExit(f"colour group {group} not found in {TOKENS}") + match = re.search(rf"{shade}:\s*'(#[0-9a-fA-F]{{6}})'", block.group(1)) + if match is None: + raise SystemExit(f"colour {path} not found in {TOKENS}") + value = match.group(1).lstrip("#") + return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16), 255) + + +BRAND = token("brand.600") +ACCENT = token("accent.500") +WHITE = token("neutral.0") + + +def arrow(draw: ImageDraw.ImageDraw, size: int, colour, start: float, end: float) -> None: + """One half of the exchange loop: an arc closed by a triangular head. + + Angles follow Pillow's convention: degrees, clockwise, zero pointing right. + """ + margin = size * 0.26 + box = (margin, margin, size - margin, size - margin) + stroke = size * 0.09 + draw.arc(box, start=start, end=end, fill=colour, width=int(stroke)) + + centre = size / 2 + radius = (size - 2 * margin) / 2 + half = stroke * 1.55 + tip_angle = math.radians(end + 9) + base_angle = math.radians(end) + + def point(angle: float, distance: float) -> tuple[float, float]: + return (centre + distance * math.cos(angle), centre + distance * math.sin(angle)) + + draw.polygon( + [ + point(tip_angle, radius), + point(base_angle, radius - half), + point(base_angle, radius + half), + ], + fill=colour, + ) + + +def mark(size: int, background, primary=WHITE) -> Image.Image: + """Two arrows chasing each other: an exchange between two neighbours.""" + canvas = size * SUPERSAMPLE + image = Image.new("RGBA", (canvas, canvas), TRANSPARENT) + draw = ImageDraw.Draw(image) + + if background is not None: + corner = canvas * 0.22 + draw.rounded_rectangle((0, 0, canvas - 1, canvas - 1), radius=corner, fill=background) + + # Two arcs with a gap at each end, so neither head sits on the other arc. + arrow(draw, canvas, primary, start=200, end=340) + arrow(draw, canvas, ACCENT, start=20, end=160) + + return image.resize((size, size), Image.LANCZOS) + + +def save(image: Image.Image, name: str, *, flatten) -> None: + ASSETS.mkdir(exist_ok=True) + if flatten is not None: + background = Image.new("RGBA", image.size, flatten) + image = Image.alpha_composite(background, image).convert("RGB") + image.save(ASSETS / name, "PNG", optimize=True) + print(f"assets/{name} {image.size[0]}x{image.size[1]} {image.mode}") + + +def main() -> None: + # iOS rejects an icon with an alpha channel, hence the flatten. + save(mark(1024, BRAND), "icon.png", flatten=BRAND) + # Android masks the adaptive foreground: the mark stays inside the safe area. + foreground = Image.new("RGBA", (1024, 1024), TRANSPARENT) + inner = mark(int(1024 * 0.66), None) + foreground.paste(inner, ((1024 - inner.width) // 2, (1024 - inner.height) // 2), inner) + save(foreground, "adaptive-icon.png", flatten=None) + # The splash sits on white, so the first arrow takes the brand colour + # instead of white, which would be invisible there. + save(mark(512, None, primary=BRAND), "splash-icon.png", flatten=None) + + +if __name__ == "__main__": + main() diff --git a/apps/mobile/stores/listing-draft.store.ts b/apps/mobile/stores/listing-draft.store.ts deleted file mode 100644 index 9def7e5..0000000 --- a/apps/mobile/stores/listing-draft.store.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { create } from 'zustand'; -import type { ListingType } from '@wantere/types'; - -interface ListingDraftState { - title: string; - description: string; - type: ListingType; - price: string; - categoryId: string | null; - photos: string[]; - update: (patch: Partial>) => void; - reset: () => void; -} - -const initial = { - title: '', - description: '', - type: 'SALE' as ListingType, - price: '', - categoryId: null, - photos: [] as string[], -}; - -export const useListingDraft = create((set) => ({ - ...initial, - update: (patch) => set(patch), - reset: () => set(initial), -})); diff --git a/apps/mobile/stores/search-filters.store.ts b/apps/mobile/stores/search-filters.store.ts index 725e433..81b73c9 100644 --- a/apps/mobile/stores/search-filters.store.ts +++ b/apps/mobile/stores/search-filters.store.ts @@ -1,31 +1,28 @@ import { create } from 'zustand'; -import type { ListingType } from '@wantere/types'; +import { DEFAULT_NEIGHBORHOOD_ID } from '@p2p-local/config'; +import type { ListingType } from '@p2p-local/types'; -/** Client-only state: what the user is currently filtering on, nothing fetched. */ +/** Client-only state: what is being filtered on, nothing fetched. */ interface SearchFiltersState { query: string; type: ListingType | null; - categoryId: string | null; - radiusMeters: number | null; + neighborhoodId: string; setQuery: (query: string) => void; setType: (type: ListingType | null) => void; - setCategory: (categoryId: string | null) => void; - setRadius: (radiusMeters: number | null) => void; + setNeighborhood: (neighborhoodId: string) => void; reset: () => void; } const initial = { query: '', type: null, - categoryId: null, - radiusMeters: null, + neighborhoodId: DEFAULT_NEIGHBORHOOD_ID, } as const; export const useSearchFilters = create((set) => ({ ...initial, setQuery: (query) => set({ query }), setType: (type) => set({ type }), - setCategory: (categoryId) => set({ categoryId }), - setRadius: (radiusMeters) => set({ radiusMeters }), + setNeighborhood: (neighborhoodId) => set({ neighborhoodId }), reset: () => set(initial), })); diff --git a/apps/mobile/tsconfig.json b/apps/mobile/tsconfig.json index de31338..71fb4d2 100644 --- a/apps/mobile/tsconfig.json +++ b/apps/mobile/tsconfig.json @@ -1,10 +1,23 @@ { - "extends": "@wantere/typescript-config/react-native.json", + "extends": "@p2p-local/typescript-config/react-native.json", "compilerOptions": { "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "types": [ + "jest" + ] }, - "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"], - "exclude": ["node_modules", "dist"] + "include": [ + "**/*.ts", + "**/*.tsx", + ".expo/types/**/*.ts", + "expo-env.d.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] } diff --git a/apps/web/.env.example b/apps/web/.env.example deleted file mode 100644 index 3eec15e..0000000 --- a/apps/web/.env.example +++ /dev/null @@ -1 +0,0 @@ -NEXT_PUBLIC_API_URL=http://localhost:4000 diff --git a/apps/web/eslint.config.mjs b/apps/web/eslint.config.mjs deleted file mode 100644 index df01424..0000000 --- a/apps/web/eslint.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@wantere/eslint-config/next'; diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts deleted file mode 100644 index 3bd62a4..0000000 --- a/apps/web/next.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NextConfig } from 'next'; - -const config: NextConfig = { - reactStrictMode: true, - transpilePackages: [ - '@wantere/api-client', - '@wantere/config', - '@wantere/types', - '@wantere/validation', - ], -}; - -export default config; diff --git a/apps/web/package.json b/apps/web/package.json deleted file mode 100644 index 39b1161..0000000 --- a/apps/web/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@wantere/web", - "version": "0.1.0", - "private": true, - "license": "MIT", - "scripts": { - "dev": "next dev --port 3000", - "build": "next build", - "start": "next start --port 3000", - "lint": "eslint src", - "typecheck": "tsc -p tsconfig.json --noEmit" - }, - "dependencies": { - "@hookform/resolvers": "^5.9.1", - "@tanstack/react-query": "^5.102.8", - "@wantere/api-client": "workspace:*", - "@wantere/config": "workspace:*", - "@wantere/design-tokens": "workspace:*", - "@wantere/types": "workspace:*", - "@wantere/validation": "workspace:*", - "clsx": "^2.1.1", - "next": "^16.3.4", - "react": "19.2.3", - "react-dom": "19.2.3", - "react-hook-form": "^7.87.0", - "tailwind-merge": "^3.6.0", - "zod": "^4.5.4" - }, - "devDependencies": { - "@tailwindcss/postcss": "^4.3.3", - "@types/node": "^26.4.1", - "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.7", - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", - "eslint": "^10.10.0", - "tailwindcss": "^4.3.3", - "typescript": "~6.0.3" - } -} diff --git a/apps/web/postcss.config.mjs b/apps/web/postcss.config.mjs deleted file mode 100644 index a34a3d5..0000000 --- a/apps/web/postcss.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - plugins: { - '@tailwindcss/postcss': {}, - }, -}; diff --git a/apps/web/src/app/annonces/[id]/page.tsx b/apps/web/src/app/annonces/[id]/page.tsx deleted file mode 100644 index cc11c1d..0000000 --- a/apps/web/src/app/annonces/[id]/page.tsx +++ /dev/null @@ -1,57 +0,0 @@ -'use client'; - -import { useParams } from 'next/navigation'; -import { EmptyState } from '@/components/empty-state'; -import { formatPrice } from '@/lib/format'; -import { useListing } from '@/features/listings/use-listing'; - -export default function ListingPage() { - const params = useParams<{ id: string }>(); - const listing = useListing(params.id); - - if (listing.isPending) { - return ( -
Chargement…
- ); - } - - if (listing.isError || !listing.data) { - return ( -
- -
- ); - } - - const data = listing.data; - - return ( -
-

{data.title}

-

- {formatPrice(data.price, data.type)} -

-

{data.location?.displayName}

- - {data.media.length > 0 ? ( -
- {data.media.map((media) => ( - // eslint-disable-next-line @next/next/no-img-element - - ))} -
- ) : null} - -

{data.description}

- -
- Publié par {data.seller.displayName} -
-
- ); -} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx deleted file mode 100644 index d24af92..0000000 --- a/apps/web/src/app/layout.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { Metadata } from 'next'; -import type { ReactNode } from 'react'; -import { QueryProvider } from '@/providers/query-provider'; -import '@/styles/globals.css'; - -export const metadata: Metadata = { - title: 'Wantere', - description: 'Acheter, vendre, donner et échanger près de chez soi.', -}; - -export default function RootLayout({ children }: { children: ReactNode }) { - return ( - - - {children} - - - ); -} diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx deleted file mode 100644 index 48682fa..0000000 --- a/apps/web/src/app/page.tsx +++ /dev/null @@ -1,50 +0,0 @@ -'use client'; - -import { EmptyState } from '@/components/empty-state'; -import { useCategories } from '@/features/categories/use-categories'; -import { ListingCard } from '@/features/listings/listing-card'; -import { useListings } from '@/features/listings/use-listings'; - -export default function HomePage() { - const categories = useCategories(); - const listings = useListings({ pageSize: 24 }); - - return ( -
-
-

Wantere

-

- Acheter, vendre, donner et échanger près de chez soi. -

-
- - - - {listings.isPending ? ( -

Chargement des annonces…

- ) : listings.isError ? ( - - ) : listings.data && listings.data.items.length > 0 ? ( -
- {listings.data.items.map((listing) => ( - - ))} -
- ) : ( - - )} -
- ); -} diff --git a/apps/web/src/components/empty-state.tsx b/apps/web/src/components/empty-state.tsx deleted file mode 100644 index f563796..0000000 --- a/apps/web/src/components/empty-state.tsx +++ /dev/null @@ -1,8 +0,0 @@ -export function EmptyState({ title, description }: { title: string; description?: string }) { - return ( -
-

{title}

- {description ?

{description}

: null} -
- ); -} diff --git a/apps/web/src/features/categories/api.ts b/apps/web/src/features/categories/api.ts deleted file mode 100644 index ac101d9..0000000 --- a/apps/web/src/features/categories/api.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { apiPath, request } from '@/lib/api'; - -export interface CategoryNode { - id: string; - name: string; - slug: string; - icon: string | null; - children: CategoryNode[]; -} - -export function fetchCategories(): Promise { - return request(apiPath('/categories')); -} diff --git a/apps/web/src/features/categories/use-categories.ts b/apps/web/src/features/categories/use-categories.ts deleted file mode 100644 index 3d95cf4..0000000 --- a/apps/web/src/features/categories/use-categories.ts +++ /dev/null @@ -1,12 +0,0 @@ -'use client'; - -import { useQuery } from '@tanstack/react-query'; -import { fetchCategories } from './api'; - -export function useCategories() { - return useQuery({ - queryKey: ['categories'], - queryFn: fetchCategories, - staleTime: 5 * 60_000, - }); -} diff --git a/apps/web/src/features/listings/api.ts b/apps/web/src/features/listings/api.ts deleted file mode 100644 index 55f23d2..0000000 --- a/apps/web/src/features/listings/api.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { apiPath, request } from '@/lib/api'; -import type { Paginated } from '@wantere/types'; - -export interface ListingSummary { - id: string; - title: string; - type: string; - status: string; - price: number | null; - currency: string; - coverUrl: string | null; - distanceMeters: number | null; - location: { displayName: string } | null; - publishedAt: string | null; -} - -export interface ListingQuery { - q?: string; - categoryId?: string; - type?: string; - page?: number; - pageSize?: number; -} - -export function fetchListings(query: ListingQuery): Promise> { - const params = new URLSearchParams(); - - for (const [key, value] of Object.entries(query)) { - if (value !== undefined && value !== '') { - params.set(key, String(value)); - } - } - - const suffix = params.size > 0 ? `?${params.toString()}` : ''; - return request>(apiPath(`/listings${suffix}`)); -} diff --git a/apps/web/src/features/listings/listing-card.tsx b/apps/web/src/features/listings/listing-card.tsx deleted file mode 100644 index a77edea..0000000 --- a/apps/web/src/features/listings/listing-card.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import Link from 'next/link'; -import { formatDistance, formatPrice } from '@/lib/format'; -import type { ListingSummary } from './api'; - -export function ListingCard({ listing }: { listing: ListingSummary }) { - const distance = formatDistance(listing.distanceMeters); - - return ( - -
- {listing.coverUrl ? ( - // eslint-disable-next-line @next/next/no-img-element - - ) : null} -
-
-

{listing.title}

-

- {formatPrice(listing.price, listing.type)} -

-

- {[listing.location?.displayName, distance].filter(Boolean).join(' · ')} -

-
- - ); -} diff --git a/apps/web/src/features/listings/use-listing.ts b/apps/web/src/features/listings/use-listing.ts deleted file mode 100644 index 1d9788c..0000000 --- a/apps/web/src/features/listings/use-listing.ts +++ /dev/null @@ -1,20 +0,0 @@ -'use client'; - -import { useQuery } from '@tanstack/react-query'; -import { apiPath, request } from '@/lib/api'; -import type { ListingSummary } from './api'; - -export interface ListingDetail extends ListingSummary { - description: string; - viewCount: number; - media: { id: string; url: string; sortOrder: number }[]; - seller: { id: string; displayName: string; avatarUrl: string | null; memberSince: string }; -} - -export function useListing(id: string) { - return useQuery({ - queryKey: ['listing', id], - queryFn: () => request(apiPath(`/listings/${id}`)), - enabled: Boolean(id), - }); -} diff --git a/apps/web/src/features/listings/use-listings.ts b/apps/web/src/features/listings/use-listings.ts deleted file mode 100644 index f4e3795..0000000 --- a/apps/web/src/features/listings/use-listings.ts +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; - -import { useQuery } from '@tanstack/react-query'; -import { fetchListings, type ListingQuery } from './api'; - -export function useListings(query: ListingQuery) { - return useQuery({ - queryKey: ['listings', query], - queryFn: () => fetchListings(query), - }); -} diff --git a/apps/web/src/lib/api.ts b/apps/web/src/lib/api.ts deleted file mode 100644 index ba721d7..0000000 --- a/apps/web/src/lib/api.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { configureApiClient, request } from '@wantere/api-client'; -import { API_PREFIX } from '@wantere/config'; - -configureApiClient({ - baseUrl: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:4000', -}); - -export function apiPath(path: string): string { - return `/${API_PREFIX}${path}`; -} - -export { request }; diff --git a/apps/web/src/lib/cn.ts b/apps/web/src/lib/cn.ts deleted file mode 100644 index 2509dbc..0000000 --- a/apps/web/src/lib/cn.ts +++ /dev/null @@ -1,6 +0,0 @@ -import clsx, { type ClassValue } from 'clsx'; -import { twMerge } from 'tailwind-merge'; - -export function cn(...inputs: ClassValue[]): string { - return twMerge(clsx(inputs)); -} diff --git a/apps/web/src/lib/format.ts b/apps/web/src/lib/format.ts deleted file mode 100644 index 0b865f0..0000000 --- a/apps/web/src/lib/format.ts +++ /dev/null @@ -1,25 +0,0 @@ -const currencyFormatter = new Intl.NumberFormat('fr-SN', { - style: 'currency', - currency: 'XOF', - maximumFractionDigits: 0, -}); - -export function formatPrice(price: number | null, type: string): string { - if (type === 'DONATION') { - return 'Don'; - } - if (type === 'BARTER') { - return 'Troc'; - } - if (price === null) { - return 'Prix à discuter'; - } - return currencyFormatter.format(price); -} - -export function formatDistance(meters: number | null): string | null { - if (meters === null) { - return null; - } - return meters < 1000 ? `${meters} m` : `${(meters / 1000).toFixed(1)} km`; -} diff --git a/apps/web/src/providers/query-provider.tsx b/apps/web/src/providers/query-provider.tsx deleted file mode 100644 index af548f9..0000000 --- a/apps/web/src/providers/query-provider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; - -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { useState, type ReactNode } from 'react'; - -export function QueryProvider({ children }: { children: ReactNode }) { - const [client] = useState( - () => - new QueryClient({ - defaultOptions: { - queries: { - staleTime: 30_000, - retry: 1, - refetchOnWindowFocus: false, - }, - }, - }), - ); - - return {children}; -} diff --git a/apps/web/src/styles/globals.css b/apps/web/src/styles/globals.css deleted file mode 100644 index 16a9fc3..0000000 --- a/apps/web/src/styles/globals.css +++ /dev/null @@ -1,11 +0,0 @@ -@import 'tailwindcss'; -@import '@wantere/design-tokens/css'; - -:root { - color-scheme: light; -} - -body { - background-color: var(--color-neutral-50); - color: var(--color-neutral-900); -} diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json deleted file mode 100644 index e36421e..0000000 --- a/apps/web/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "@wantere/typescript-config/nextjs.json", - "compilerOptions": { - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/docker/initdb/20-trim-extensions.sql b/docker/initdb/20-trim-extensions.sql index 655c31d..8b6581a 100644 --- a/docker/initdb/20-trim-extensions.sql +++ b/docker/initdb/20-trim-extensions.sql @@ -1,4 +1,4 @@ --- The PostGIS image preinstalls topology and tiger_geocoder; Wantere uses +-- The PostGIS image preinstalls topology and tiger_geocoder; P2P Local uses -- neither, and leaving them in place makes every `prisma migrate` report drift. DROP EXTENSION IF EXISTS postgis_tiger_geocoder CASCADE; DROP EXTENSION IF EXISTS postgis_topology CASCADE; diff --git a/docs/architecture.md b/docs/architecture.md index c1678b1..c01d600 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,13 +1,65 @@ # Architecture +## V1: a local-first mobile application + +The V1 is `apps/mobile`, an Expo application that runs without a backend. +Listings are written to the device, publishing asks for no account, and putting +two people in touch is delegated to WhatsApp. + +This is a starting point, not an end state. It exists to get the product in +front of a neighbourhood quickly, and it carries one heavy consequence that must +stay visible: **a listing published on a device is not visible on any other +device.** Sharing is what circulates a listing, not a feed. + +### The seam that makes it reversible + +Every read and write goes through `ListingRepository`, an interface in +`apps/mobile/features/listings`. Its only implementation in V1 stores a JSON +document in AsyncStorage. Three rules keep the seam useful: + +- every method is asynchronous, even those that would not need to be, so an HTTP + implementation substitutes without changing a signature; +- filtering happens in the repository, never in a screen, because a filter is a + query string once a server answers; +- no screen imports AsyncStorage. The repository is injected through a React + context, so switching to the API is one class and one line in the provider. + +### Listing ownership without accounts + +A listing carries an `ownerKey` generated at publication. Today the storage is +already private to the device, so the key buys nothing — it is written now so +that access control exists in the model and in the UI before a server needs it. + +Listings expire on their own after a fixed number of days, and completing one +keeps it visible, greyed out, for 48 hours before it is archived. Deleting one +removes its photo file as well. + +### Phone numbers + +The application never renders a phone number. It builds a `wa.me` link at the +moment of the tap, with a message that names the listing so the recipient can +tell where the contact comes from. A shared listing carries its title, its type +and its district — never a number. + +### What comes next + +A backend restores what local-first cannot do: listings visible to others, an +administration link that works from another screen, and light authentication. +The section below describes the API that already exists for that purpose. + +## Backend, out of scope for the V1 + +The code described from here on is implemented and tested in `apps/api`. **No +client consumes it today.** It is kept because it is where the product goes once +listings need to travel between phones. + ## Shape of the system -One API, three clients. `apps/api` is a NestJS modular monolith and owns every -business rule; `apps/web`, `apps/mobile` and `apps/admin` consume its REST API -through a client generated from its OpenAPI document. +`apps/api` is a NestJS modular monolith and owns every business rule. Clients +consume its REST API through a client generated from its OpenAPI document. -There are no microservices, and there is no second backend hiding in Next.js -server actions. A rule that matters lives in a Nest module, once. +There are no microservices, and there is no second backend hiding in a server +framework. A rule that matters lives in a Nest module, once. ## Why a modular monolith @@ -98,6 +150,6 @@ domains. - No Clean Architecture ceremony, no CQRS, no event sourcing. - No generic repository, no base service, no interface per service. -- No shared UI component library between React Native and the web: they share - tokens, not components. +- No shared UI component library: the design tokens are shared, components are + not. - No pricing or monetisation logic. diff --git a/docs/design/README.md b/docs/design/README.md index 50b61fc..7f927fa 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -4,10 +4,14 @@ Ce dossier réunit les documents visuels qui ont circulé pendant le cadrage du projet. Ils sont versionnés ici pour qu'une discussion sur un écart entre le code et une maquette porte sur une référence que tout le monde peut ouvrir. -> **Statut : en discussion.** Aucun de ces documents n'a été validé comme la -> référence de la V1. Ils sont réunis pour permettre la discussion, pas pour la -> clore. Tant que ce statut n'a pas changé, un écart entre le code et une de ces -> images n'est pas un bug. +> **Statut : écartés.** Ni le nom, ni l'identité visuelle, ni les mises en page +> de ces documents ne peuvent être repris. Ils restent versionnés parce qu'ils +> documentent le cadrage et le domaine que l'API implémente déjà, mais ils ne +> sont plus une référence : un écart entre l'application et une de ces images +> n'est pas un bug. +> +> La référence fonctionnelle de la V1 est [`parcours-mvp.md`](parcours-mvp.md), +> qui décrit ce que l'application fait sans décrire à quoi elle ressemble. ## Contenu @@ -35,8 +39,17 @@ constat, pas un jugement : les deux sont cohérents pris séparément. | Pile | Astro/Tailwind, Supabase ou Firebase | _non spécifiée_ | | Périmètre | Annonces, filtres, contact | + achat groupé, observatoire des prix, avis, livraison | -Le code suit aujourd'hui les maquettes : voir la section « Designed for, not -implemented » de [`../architecture.md`](../architecture.md). +Arbitrage rendu : la V1 suit la logique du blueprint — mise en relation par +WhatsApp, pas de messagerie interne, pas de compte. Le code de l'API, lui, suit +encore les maquettes : voir la section « Designed for, not implemented » de +[`../architecture.md`](../architecture.md). + +Un point reste ouvert. Le blueprint expose un numéro via un lien `wa.me`, la +maquette d'inscription promet « votre numéro n'apparaît jamais sur vos +annonces », et `CONTRIBUTING.md` interdit d'exposer un téléphone. L'application +ne l'affiche nulle part, mais l'auteur d'une annonce devient joignable. Trancher +entre un relais qui masque les deux numéros, une exposition assumée, ou un +consentement explicite par annonce est une décision d'équipe. Trancher entre les deux est une décision d'équipe. Elle n'est pas prise ici. diff --git a/docs/design/parcours-mvp.md b/docs/design/parcours-mvp.md new file mode 100644 index 0000000..fe702ce --- /dev/null +++ b/docs/design/parcours-mvp.md @@ -0,0 +1,89 @@ +# Parcours du MVP + +Ce document décrit ce que l'application mobile doit faire. Il ne décrit ni une +mise en page, ni une identité visuelle : celles-ci restent à concevoir, et rien +de ce qui a circulé pendant le cadrage ne peut être repris tel quel. + +## Les quatre types d'échange + +Une annonce a exactement un type. Ils sont déjà modélisés dans +`@p2p-local/types` : + +| Libellé | Type | Prix | +| ------------ | --------- | ------------------------------------- | +| Donner | `DONATION`| aucun | +| Troquer | `BARTER` | aucun | +| Prix coûtant | `SALE` | obligatoire, en francs CFA, sans marge | +| Besoin | `REQUEST` | facultatif | + +Le prix coûtant est le prix d'achat, sans marge spéculative. C'est une promesse +du produit, pas une case à cocher : si elle n'est pas tenue, l'annonce relève de +la vente ordinaire et n'a pas sa place ici. + +## Trouver + +1. La personne ouvre l'application. Un quartier est déjà sélectionné ; elle peut + en changer dans une liste fermée. +2. Elle voit les annonces de ce quartier, les plus récentes d'abord. +3. Elle filtre par type, ou cherche dans les titres. +4. Elle ouvre une annonce : photo, type, titre, description, quartier et + ancienneté. + +Le filtre est un **quartier choisi à la main**, pas un rayon GPS. Le public visé +a un forfait limité et n'active pas sa localisation pour chercher un cahier. + +## Contacter + +1. Sur une annonce, un bouton ouvre WhatsApp. +2. Avant l'ouverture, la personne renseigne son prénom, une fois pour toutes. +3. WhatsApp s'ouvre avec un message pré-rempli qui nomme l'annonce, pour que le + destinataire sache d'où vient le contact. +4. Sous le bouton, un avertissement permanent : l'application ne demande jamais + d'acompte ni de code Wave ou Orange Money. + +**Aucun numéro n'est affiché.** Ni dans une annonce, ni dans un bouton, ni dans +un texte partagé. Un numéro visible en clair attire les robots collecteurs, le +démarchage et les tentatives d'escroquerie, et il expose particulièrement les +femmes. Le numéro ne sert qu'à construire le lien, au moment du geste. + +## Publier + +1. Un bouton unique, visible depuis l'accueil. +2. Quatre champs : photo, type, quartier, description. Un cinquième, le prix, + n'apparaît que pour le prix coûtant. +3. Aucun compte n'est demandé. Le numéro WhatsApp de l'auteur est un réglage + renseigné une seule fois. +4. L'annonce est publiée ; elle apparaît immédiatement dans la liste. + +L'objectif est une minute, sur un téléphone d'entrée de gamme, avec une +connexion lente. + +## Gérer son annonce + +Sans compte, la propriété d'une annonce tient à la clé d'administration écrite +sur l'appareil au moment de la publication. + +| Action | Effet | +| ----------------------- | ---------------------------------------------------------------------------------------------- | +| Marquer comme donné | L'annonce reste visible 48 h, grisée, avec un badge ; le contact est désactivé, puis elle est archivée. | +| Supprimer définitivement | L'annonce et sa photo sont effacées immédiatement, sans corbeille. | +| Expiration automatique | Toute annonce est archivée d'elle-même au bout de 30 jours. | + +Garder une annonce accomplie visible pendant deux jours n'est pas un détail +technique : c'est ce qui rend l'entraide du quartier visible. + +## Partager + +Une annonce se partage sous forme de texte : titre, type, quartier. Le partage +est aujourd'hui le seul canal de diffusion réel, puisque rien n'est publié sur +un serveur. + +C'est aussi la limite la plus lourde de ce MVP : **une annonce publiée n'est +visible que sur le téléphone qui l'a publiée.** Tant qu'il n'y a pas de backend, +le texte partagé ne peut pas renvoyer vers une page consultable. + +## Hors périmètre du MVP + +- Notifications : rien ne peut en produire sans serveur. +- Messagerie interne : la mise en relation passe par WhatsApp, volontairement. +- Comptes, offres, avis, achat groupé, observatoire des prix. diff --git a/package.json b/package.json index 533bffb..1c34b34 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "wantere", + "name": "p2p-local", "private": true, "version": "0.1.0", "license": "MIT", @@ -15,15 +15,15 @@ "test": "turbo run test", "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"", "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"", - "api:generate": "pnpm --filter @wantere/api openapi:export && pnpm --filter @wantere/api-client generate", - "db:migrate": "pnpm --filter @wantere/api db:migrate", - "db:seed": "pnpm --filter @wantere/api db:seed", - "db:studio": "pnpm --filter @wantere/api db:studio", + "api:generate": "pnpm --filter @p2p-local/api openapi:export && pnpm --filter @p2p-local/api-client generate", + "db:migrate": "pnpm --filter @p2p-local/api db:migrate", + "db:seed": "pnpm --filter @p2p-local/api db:seed", + "db:studio": "pnpm --filter @p2p-local/api db:studio", "docker:up": "docker compose -f docker/docker-compose.dev.yml up -d", "docker:down": "docker compose -f docker/docker-compose.dev.yml down" }, "devDependencies": { - "@wantere/prettier-config": "workspace:*", + "@p2p-local/prettier-config": "workspace:*", "prettier": "^3.9.6", "turbo": "^2.10.12" } diff --git a/packages/api-client/eslint.config.mjs b/packages/api-client/eslint.config.mjs index 84b8336..61362cb 100644 --- a/packages/api-client/eslint.config.mjs +++ b/packages/api-client/eslint.config.mjs @@ -1,3 +1,3 @@ -import base from '@wantere/eslint-config/base'; +import base from '@p2p-local/eslint-config/base'; export default [...base, { ignores: ['src/generated/**'] }]; diff --git a/packages/api-client/orval.config.ts b/packages/api-client/orval.config.ts index f1b75e3..345878a 100644 --- a/packages/api-client/orval.config.ts +++ b/packages/api-client/orval.config.ts @@ -1,10 +1,10 @@ import { defineConfig } from 'orval'; export default defineConfig({ - wantere: { + 'p2p-local': { input: '../../apps/api/openapi.json', output: { - target: './src/generated/wantere.ts', + target: './src/generated/p2p-local.ts', schemas: './src/generated/models', client: 'fetch', mode: 'split', diff --git a/packages/api-client/package.json b/packages/api-client/package.json index 23f5158..84200a7 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/api-client", + "name": "@p2p-local/api-client", "version": "0.1.0", "private": true, "license": "MIT", @@ -15,8 +15,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "devDependencies": { - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "eslint": "^10.10.0", "orval": "^8.28.1", "typescript": "~6.0.3" diff --git a/packages/api-client/src/generated/models/addFavoriteDto.ts b/packages/api-client/src/generated/models/addFavoriteDto.ts index 91b7ef6..89df6aa 100644 --- a/packages/api-client/src/generated/models/addFavoriteDto.ts +++ b/packages/api-client/src/generated/models/addFavoriteDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/authTokensDto.ts b/packages/api-client/src/generated/models/authTokensDto.ts index 221a2cd..4841f76 100644 --- a/packages/api-client/src/generated/models/authTokensDto.ts +++ b/packages/api-client/src/generated/models/authTokensDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/categoriesControllerFindBySlugV1200.ts b/packages/api-client/src/generated/models/categoriesControllerFindBySlugV1200.ts index 0eb3a7c..ea95d01 100644 --- a/packages/api-client/src/generated/models/categoriesControllerFindBySlugV1200.ts +++ b/packages/api-client/src/generated/models/categoriesControllerFindBySlugV1200.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/categoriesControllerTreeV1200Item.ts b/packages/api-client/src/generated/models/categoriesControllerTreeV1200Item.ts index 2501f5d..9e8792e 100644 --- a/packages/api-client/src/generated/models/categoriesControllerTreeV1200Item.ts +++ b/packages/api-client/src/generated/models/categoriesControllerTreeV1200Item.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createCategoryDto.ts b/packages/api-client/src/generated/models/createCategoryDto.ts index cf36db9..bdbd6d0 100644 --- a/packages/api-client/src/generated/models/createCategoryDto.ts +++ b/packages/api-client/src/generated/models/createCategoryDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createListingDto.ts b/packages/api-client/src/generated/models/createListingDto.ts index 5e2371f..0c28d47 100644 --- a/packages/api-client/src/generated/models/createListingDto.ts +++ b/packages/api-client/src/generated/models/createListingDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createListingDtoCondition.ts b/packages/api-client/src/generated/models/createListingDtoCondition.ts index 045d34d..4d56148 100644 --- a/packages/api-client/src/generated/models/createListingDtoCondition.ts +++ b/packages/api-client/src/generated/models/createListingDtoCondition.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createListingDtoType.ts b/packages/api-client/src/generated/models/createListingDtoType.ts index e106b49..a37088d 100644 --- a/packages/api-client/src/generated/models/createListingDtoType.ts +++ b/packages/api-client/src/generated/models/createListingDtoType.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createReportDto.ts b/packages/api-client/src/generated/models/createReportDto.ts index f652f61..0d625c3 100644 --- a/packages/api-client/src/generated/models/createReportDto.ts +++ b/packages/api-client/src/generated/models/createReportDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createReportDtoReason.ts b/packages/api-client/src/generated/models/createReportDtoReason.ts index d5f1e6c..0b3a578 100644 --- a/packages/api-client/src/generated/models/createReportDtoReason.ts +++ b/packages/api-client/src/generated/models/createReportDtoReason.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/createReportDtoTargetType.ts b/packages/api-client/src/generated/models/createReportDtoTargetType.ts index d6a8477..65e1476 100644 --- a/packages/api-client/src/generated/models/createReportDtoTargetType.ts +++ b/packages/api-client/src/generated/models/createReportDtoTargetType.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/favoritesControllerListV1Params.ts b/packages/api-client/src/generated/models/favoritesControllerListV1Params.ts index 0fe1ac7..dd12f76 100644 --- a/packages/api-client/src/generated/models/favoritesControllerListV1Params.ts +++ b/packages/api-client/src/generated/models/favoritesControllerListV1Params.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200.ts b/packages/api-client/src/generated/models/healthControllerReady200.ts index 1b95a20..283c2a4 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200Details.ts b/packages/api-client/src/generated/models/healthControllerReady200Details.ts index bcc3c31..4c529a7 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200Details.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200Details.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200DetailsStatus.ts b/packages/api-client/src/generated/models/healthControllerReady200DetailsStatus.ts index 746a541..6170aa7 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200DetailsStatus.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200DetailsStatus.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200Error.ts b/packages/api-client/src/generated/models/healthControllerReady200Error.ts index cf55f69..2fc61af 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200Error.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200Error.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200Info.ts b/packages/api-client/src/generated/models/healthControllerReady200Info.ts index 188b69f..3d86bcd 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200Info.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200Info.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady200Status.ts b/packages/api-client/src/generated/models/healthControllerReady200Status.ts index ae70db6..07f68a9 100644 --- a/packages/api-client/src/generated/models/healthControllerReady200Status.ts +++ b/packages/api-client/src/generated/models/healthControllerReady200Status.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503.ts b/packages/api-client/src/generated/models/healthControllerReady503.ts index d6c8a84..15d91a7 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503Details.ts b/packages/api-client/src/generated/models/healthControllerReady503Details.ts index cb4aeb8..2813930 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503Details.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503Details.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503DetailsStatus.ts b/packages/api-client/src/generated/models/healthControllerReady503DetailsStatus.ts index 1344229..2b54ee7 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503DetailsStatus.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503DetailsStatus.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503Error.ts b/packages/api-client/src/generated/models/healthControllerReady503Error.ts index 07ef84d..3382dfd 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503Error.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503Error.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503Info.ts b/packages/api-client/src/generated/models/healthControllerReady503Info.ts index ff09e22..9de5fd8 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503Info.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503Info.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/healthControllerReady503Status.ts b/packages/api-client/src/generated/models/healthControllerReady503Status.ts index ed3e55d..5b362bf 100644 --- a/packages/api-client/src/generated/models/healthControllerReady503Status.ts +++ b/packages/api-client/src/generated/models/healthControllerReady503Status.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/index.ts b/packages/api-client/src/generated/models/index.ts index b069ff3..219faaa 100644 --- a/packages/api-client/src/generated/models/index.ts +++ b/packages/api-client/src/generated/models/index.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerCreateV1201.ts b/packages/api-client/src/generated/models/listingsControllerCreateV1201.ts index 76594a0..247cf8f 100644 --- a/packages/api-client/src/generated/models/listingsControllerCreateV1201.ts +++ b/packages/api-client/src/generated/models/listingsControllerCreateV1201.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindManyV1Condition.ts b/packages/api-client/src/generated/models/listingsControllerFindManyV1Condition.ts index 861917d..4506fed 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindManyV1Condition.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindManyV1Condition.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindManyV1Params.ts b/packages/api-client/src/generated/models/listingsControllerFindManyV1Params.ts index c6ea117..3008010 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindManyV1Params.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindManyV1Params.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindManyV1Sort.ts b/packages/api-client/src/generated/models/listingsControllerFindManyV1Sort.ts index b8e47d7..b3c676a 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindManyV1Sort.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindManyV1Sort.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindManyV1Type.ts b/packages/api-client/src/generated/models/listingsControllerFindManyV1Type.ts index a772ad0..9726ee5 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindManyV1Type.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindManyV1Type.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindMineV1Params.ts b/packages/api-client/src/generated/models/listingsControllerFindMineV1Params.ts index 6afb5e4..a76b4ab 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindMineV1Params.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindMineV1Params.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerFindOneV1200.ts b/packages/api-client/src/generated/models/listingsControllerFindOneV1200.ts index 5a8bc30..e7a91b5 100644 --- a/packages/api-client/src/generated/models/listingsControllerFindOneV1200.ts +++ b/packages/api-client/src/generated/models/listingsControllerFindOneV1200.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/listingsControllerUpdateV1200.ts b/packages/api-client/src/generated/models/listingsControllerUpdateV1200.ts index 9239127..01c4062 100644 --- a/packages/api-client/src/generated/models/listingsControllerUpdateV1200.ts +++ b/packages/api-client/src/generated/models/listingsControllerUpdateV1200.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/loginDto.ts b/packages/api-client/src/generated/models/loginDto.ts index 8752ef4..5aab457 100644 --- a/packages/api-client/src/generated/models/loginDto.ts +++ b/packages/api-client/src/generated/models/loginDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/notificationsControllerListV1Params.ts b/packages/api-client/src/generated/models/notificationsControllerListV1Params.ts index b965a7d..2181eb0 100644 --- a/packages/api-client/src/generated/models/notificationsControllerListV1Params.ts +++ b/packages/api-client/src/generated/models/notificationsControllerListV1Params.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/otpChallengeDto.ts b/packages/api-client/src/generated/models/otpChallengeDto.ts index 971397b..617e737 100644 --- a/packages/api-client/src/generated/models/otpChallengeDto.ts +++ b/packages/api-client/src/generated/models/otpChallengeDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/refreshDto.ts b/packages/api-client/src/generated/models/refreshDto.ts index 469a45e..10f0101 100644 --- a/packages/api-client/src/generated/models/refreshDto.ts +++ b/packages/api-client/src/generated/models/refreshDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/registerDto.ts b/packages/api-client/src/generated/models/registerDto.ts index ed9cc9f..8dde7f7 100644 --- a/packages/api-client/src/generated/models/registerDto.ts +++ b/packages/api-client/src/generated/models/registerDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/reportsControllerListV1Params.ts b/packages/api-client/src/generated/models/reportsControllerListV1Params.ts index d5f85b7..7ecaea8 100644 --- a/packages/api-client/src/generated/models/reportsControllerListV1Params.ts +++ b/packages/api-client/src/generated/models/reportsControllerListV1Params.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/reviewReportDto.ts b/packages/api-client/src/generated/models/reviewReportDto.ts index 1ce2290..49983ca 100644 --- a/packages/api-client/src/generated/models/reviewReportDto.ts +++ b/packages/api-client/src/generated/models/reviewReportDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/reviewReportDtoStatus.ts b/packages/api-client/src/generated/models/reviewReportDtoStatus.ts index 16865f7..6b09c3d 100644 --- a/packages/api-client/src/generated/models/reviewReportDtoStatus.ts +++ b/packages/api-client/src/generated/models/reviewReportDtoStatus.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/sessionUserDto.ts b/packages/api-client/src/generated/models/sessionUserDto.ts index 7ce7638..0ba28ea 100644 --- a/packages/api-client/src/generated/models/sessionUserDto.ts +++ b/packages/api-client/src/generated/models/sessionUserDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/updateCategoryDto.ts b/packages/api-client/src/generated/models/updateCategoryDto.ts index 4bc8d00..1806c54 100644 --- a/packages/api-client/src/generated/models/updateCategoryDto.ts +++ b/packages/api-client/src/generated/models/updateCategoryDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/updateListingDto.ts b/packages/api-client/src/generated/models/updateListingDto.ts index 22314ca..fff1db7 100644 --- a/packages/api-client/src/generated/models/updateListingDto.ts +++ b/packages/api-client/src/generated/models/updateListingDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/updateListingDtoCondition.ts b/packages/api-client/src/generated/models/updateListingDtoCondition.ts index 56acb77..01893fb 100644 --- a/packages/api-client/src/generated/models/updateListingDtoCondition.ts +++ b/packages/api-client/src/generated/models/updateListingDtoCondition.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/updateListingDtoStatus.ts b/packages/api-client/src/generated/models/updateListingDtoStatus.ts index a2457a2..0f30575 100644 --- a/packages/api-client/src/generated/models/updateListingDtoStatus.ts +++ b/packages/api-client/src/generated/models/updateListingDtoStatus.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/updateProfileDto.ts b/packages/api-client/src/generated/models/updateProfileDto.ts index c49725f..b7a8f38 100644 --- a/packages/api-client/src/generated/models/updateProfileDto.ts +++ b/packages/api-client/src/generated/models/updateProfileDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/verifyOtpDto.ts b/packages/api-client/src/generated/models/verifyOtpDto.ts index 8fcdef1..3d2820a 100644 --- a/packages/api-client/src/generated/models/verifyOtpDto.ts +++ b/packages/api-client/src/generated/models/verifyOtpDto.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/models/verifyOtpDtoPlatform.ts b/packages/api-client/src/generated/models/verifyOtpDtoPlatform.ts index 5eabcc7..06e3324 100644 --- a/packages/api-client/src/generated/models/verifyOtpDtoPlatform.ts +++ b/packages/api-client/src/generated/models/verifyOtpDtoPlatform.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/generated/wantere.ts b/packages/api-client/src/generated/p2p-local.ts similarity index 99% rename from packages/api-client/src/generated/wantere.ts rename to packages/api-client/src/generated/p2p-local.ts index fc932c7..4d96426 100644 --- a/packages/api-client/src/generated/wantere.ts +++ b/packages/api-client/src/generated/p2p-local.ts @@ -1,7 +1,7 @@ /** * Generated by orval 🍺 * Do not edit manually. - * Wantere API + * P2P Local API * Local commerce and exchange platform * OpenAPI spec version: 1.0 */ diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts index e730170..2505ec4 100644 --- a/packages/api-client/src/index.ts +++ b/packages/api-client/src/index.ts @@ -1,3 +1,3 @@ export * from './http-client'; -export * from './generated/wantere'; +export * from './generated/p2p-local'; export * from './generated/models'; diff --git a/packages/api-client/tsconfig.json b/packages/api-client/tsconfig.json index 8097e76..b5df718 100644 --- a/packages/api-client/tsconfig.json +++ b/packages/api-client/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/library.json", + "extends": "@p2p-local/typescript-config/library.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "dist", diff --git a/packages/config/eslint.config.mjs b/packages/config/eslint.config.mjs index 89de504..14ec7c5 100644 --- a/packages/config/eslint.config.mjs +++ b/packages/config/eslint.config.mjs @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/base'; +export { default } from '@p2p-local/eslint-config/base'; diff --git a/packages/config/package.json b/packages/config/package.json index e5cb598..81d3fd2 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/config", + "name": "@p2p-local/config", "version": "0.1.0", "private": true, "license": "MIT", @@ -15,8 +15,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "devDependencies": { - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "eslint": "^10.10.0", "typescript": "~6.0.3" } diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts index 4be35ea..059ead2 100644 --- a/packages/config/src/index.ts +++ b/packages/config/src/index.ts @@ -45,3 +45,4 @@ export const TOKENS = { accessTtl: '15m', refreshTtlDays: 30, } as const; +export * from './places'; diff --git a/packages/config/src/places.ts b/packages/config/src/places.ts new file mode 100644 index 0000000..ba770b6 --- /dev/null +++ b/packages/config/src/places.ts @@ -0,0 +1,68 @@ +/** + * Districts are a closed list, not free text. + * + * A listing is found by district, so the values have to be comparable: free + * text produces "Parcelles", "parcelles assainies" and "PA" for one place, and + * none of them group together. A short list is also faster to tap than a + * keyboard on an entry-level phone. + */ +export interface Neighborhood { + /** Stable slug. This is what a listing stores. */ + id: string; + name: string; + department: string; + region: string; +} + +const DAKAR = { department: 'Dakar', region: 'Dakar' } as const; +const PIKINE = { department: 'Pikine', region: 'Dakar' } as const; +const GUEDIAWAYE = { department: 'Guédiawaye', region: 'Dakar' } as const; +const RUFISQUE = { department: 'Rufisque', region: 'Dakar' } as const; +const KEUR_MASSAR = { department: 'Keur Massar', region: 'Dakar' } as const; + +export const SENEGAL_NEIGHBORHOODS: readonly Neighborhood[] = [ + { id: 'almadies', name: 'Almadies', ...DAKAR }, + { id: 'castors', name: 'Castors', ...DAKAR }, + { id: 'colobane', name: 'Colobane', ...DAKAR }, + { id: 'dieuppeul', name: 'Dieuppeul', ...DAKAR }, + { id: 'fann-point-e', name: 'Fann / Point E', ...DAKAR }, + { id: 'grand-dakar', name: 'Grand Dakar', ...DAKAR }, + { id: 'grand-yoff', name: 'Grand Yoff', ...DAKAR }, + { id: 'gueule-tapee', name: 'Gueule Tapée', ...DAKAR }, + { id: 'hlm', name: 'HLM', ...DAKAR }, + { id: 'liberte-6', name: 'Liberté 6', ...DAKAR }, + { id: 'medina', name: 'Médina', ...DAKAR }, + { id: 'mermoz', name: 'Mermoz', ...DAKAR }, + { id: 'ngor', name: 'Ngor', ...DAKAR }, + { id: 'ouakam', name: 'Ouakam', ...DAKAR }, + { id: 'parcelles-assainies', name: 'Parcelles Assainies', ...DAKAR }, + { id: 'plateau', name: 'Plateau', ...DAKAR }, + { id: 'sacre-coeur', name: 'Sacré-Cœur', ...DAKAR }, + { id: 'sicap-liberte', name: 'Sicap Liberté', ...DAKAR }, + { id: 'yoff', name: 'Yoff', ...DAKAR }, + { id: 'pikine', name: 'Pikine', ...PIKINE }, + { id: 'thiaroye', name: 'Thiaroye', ...PIKINE }, + { id: 'guediawaye', name: 'Guédiawaye', ...GUEDIAWAYE }, + { id: 'golf-sud', name: 'Golf Sud', ...GUEDIAWAYE }, + { id: 'keur-massar', name: 'Keur Massar', ...KEUR_MASSAR }, + { id: 'malika', name: 'Malika', ...KEUR_MASSAR }, + { id: 'yeumbeul', name: 'Yeumbeul', ...KEUR_MASSAR }, + { id: 'rufisque', name: 'Rufisque', ...RUFISQUE }, + { id: 'bargny', name: 'Bargny', ...RUFISQUE }, +]; + +export const DEFAULT_NEIGHBORHOOD_ID = 'parcelles-assainies'; + +export function findNeighborhood(id: string): Neighborhood | undefined { + return SENEGAL_NEIGHBORHOODS.find((neighborhood) => neighborhood.id === id); +} + +export function neighborhoodName(id: string): string { + return findNeighborhood(id)?.name ?? id; +} + +/** How long a listing stays visible before it archives itself. */ +export const LISTING_TTL_DAYS = 30; + +/** How long a completed listing stays visible, greyed out, before archiving. */ +export const COMPLETED_LISTING_GRACE_HOURS = 48; diff --git a/packages/config/tsconfig.json b/packages/config/tsconfig.json index 50bc9c1..03ef90b 100644 --- a/packages/config/tsconfig.json +++ b/packages/config/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/library.json", + "extends": "@p2p-local/typescript-config/library.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "dist", diff --git a/packages/design-tokens/css/tokens.css b/packages/design-tokens/css/tokens.css deleted file mode 100644 index b2e25ca..0000000 --- a/packages/design-tokens/css/tokens.css +++ /dev/null @@ -1,34 +0,0 @@ -@theme { - --color-brand-50: #eefbf3; - --color-brand-100: #d5f5e1; - --color-brand-200: #ade9c6; - --color-brand-300: #77d7a3; - --color-brand-400: #41bd7d; - --color-brand-500: #1d9e61; - --color-brand-600: #0f7f4d; - --color-brand-700: #0c6540; - --color-brand-800: #0c5034; - --color-brand-900: #0a422c; - - --color-accent-100: #ffeccc; - --color-accent-300: #ffcd6b; - --color-accent-500: #f5a623; - --color-accent-700: #b8730c; - - --color-neutral-50: #f7f8f7; - --color-neutral-100: #eceeed; - --color-neutral-200: #dcdfde; - --color-neutral-300: #bcc2c0; - --color-neutral-400: #8e9794; - --color-neutral-500: #6b7570; - --color-neutral-600: #4d5551; - --color-neutral-700: #3a413e; - --color-neutral-800: #242927; - --color-neutral-900: #141816; - - --radius-md: 0.5rem; - --radius-lg: 0.75rem; - --radius-xl: 1.25rem; - - --shadow-card: 0 4px 12px rgba(20, 24, 22, 0.08); -} diff --git a/packages/design-tokens/eslint.config.mjs b/packages/design-tokens/eslint.config.mjs index 89de504..14ec7c5 100644 --- a/packages/design-tokens/eslint.config.mjs +++ b/packages/design-tokens/eslint.config.mjs @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/base'; +export { default } from '@p2p-local/eslint-config/base'; diff --git a/packages/design-tokens/package.json b/packages/design-tokens/package.json index 991500e..3aae7cf 100644 --- a/packages/design-tokens/package.json +++ b/packages/design-tokens/package.json @@ -1,13 +1,12 @@ { - "name": "@wantere/design-tokens", + "name": "@p2p-local/design-tokens", "version": "0.1.0", "private": true, "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist", - "css" + "dist" ], "scripts": { "build": "tsc -p tsconfig.json", @@ -16,8 +15,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "devDependencies": { - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "eslint": "^10.10.0", "typescript": "~6.0.3" }, @@ -25,7 +24,6 @@ ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" - }, - "./css": "./css/tokens.css" + } } } diff --git a/packages/design-tokens/tsconfig.json b/packages/design-tokens/tsconfig.json index 50bc9c1..03ef90b 100644 --- a/packages/design-tokens/tsconfig.json +++ b/packages/design-tokens/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/library.json", + "extends": "@p2p-local/typescript-config/library.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "dist", diff --git a/packages/eslint-config/next.js b/packages/eslint-config/next.js deleted file mode 100644 index bb37ba2..0000000 --- a/packages/eslint-config/next.js +++ /dev/null @@ -1,18 +0,0 @@ -import { base } from './base.js'; -import tseslint from 'typescript-eslint'; -import reactHooks from 'eslint-plugin-react-hooks'; -import next from '@next/eslint-plugin-next'; -import globals from 'globals'; - -export default tseslint.config(...base, { - files: ['**/*.{ts,tsx}'], - plugins: { 'react-hooks': reactHooks, '@next/next': next }, - languageOptions: { - globals: { ...globals.browser }, - }, - rules: { - ...reactHooks.configs.recommended.rules, - ...next.configs.recommended.rules, - ...next.configs['core-web-vitals'].rules, - }, -}); diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 91c62d0..b274a9b 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,24 +1,21 @@ { - "name": "@wantere/eslint-config", + "name": "@p2p-local/eslint-config", "version": "0.1.0", "private": true, "license": "MIT", "type": "module", "exports": { "./base": "./base.js", - "./next": "./next.js", "./nest": "./nest.js", "./react-native": "./react-native.js" }, "files": [ "base.js", - "next.js", "nest.js", "react-native.js" ], "dependencies": { "@eslint/js": "^10.0.1", - "@next/eslint-plugin-next": "^16.3.4", "eslint-config-prettier": "^10.1.8", "eslint-plugin-react-hooks": "^7.1.1", "globals": "^17.12.0", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 96074bc..a7af7cb 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/prettier-config", + "name": "@p2p-local/prettier-config", "version": "0.1.0", "private": true, "license": "MIT", diff --git a/packages/types/eslint.config.mjs b/packages/types/eslint.config.mjs index 89de504..14ec7c5 100644 --- a/packages/types/eslint.config.mjs +++ b/packages/types/eslint.config.mjs @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/base'; +export { default } from '@p2p-local/eslint-config/base'; diff --git a/packages/types/package.json b/packages/types/package.json index e5d8de5..9189fa8 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/types", + "name": "@p2p-local/types", "version": "0.1.0", "private": true, "license": "MIT", @@ -15,8 +15,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "devDependencies": { - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "eslint": "^10.10.0", "typescript": "~6.0.3" } diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index 50bc9c1..03ef90b 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/library.json", + "extends": "@p2p-local/typescript-config/library.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "dist", diff --git a/packages/typescript-config/nextjs.json b/packages/typescript-config/nextjs.json deleted file mode 100644 index 33f4541..0000000 --- a/packages/typescript-config/nextjs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./base.json", - "compilerOptions": { - "lib": ["DOM", "DOM.Iterable", "ES2022"], - "jsx": "preserve", - "noEmit": true, - "allowJs": true, - "incremental": true, - "plugins": [{ "name": "next" }], - "module": "ESNext", - "moduleResolution": "Bundler" - } -} diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 3800ba3..796cebc 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,11 +1,10 @@ { - "name": "@wantere/typescript-config", + "name": "@p2p-local/typescript-config", "version": "0.1.0", "private": true, "license": "MIT", "files": [ "base.json", - "nextjs.json", "nestjs.json", "react-native.json", "library.json" diff --git a/packages/validation/eslint.config.mjs b/packages/validation/eslint.config.mjs index 89de504..14ec7c5 100644 --- a/packages/validation/eslint.config.mjs +++ b/packages/validation/eslint.config.mjs @@ -1 +1 @@ -export { default } from '@wantere/eslint-config/base'; +export { default } from '@p2p-local/eslint-config/base'; diff --git a/packages/validation/package.json b/packages/validation/package.json index b3d4a31..d9e9cd3 100644 --- a/packages/validation/package.json +++ b/packages/validation/package.json @@ -1,5 +1,5 @@ { - "name": "@wantere/validation", + "name": "@p2p-local/validation", "version": "0.1.0", "private": true, "license": "MIT", @@ -15,13 +15,13 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@wantere/config": "workspace:*", - "@wantere/types": "workspace:*", + "@p2p-local/config": "workspace:*", + "@p2p-local/types": "workspace:*", "zod": "^4.5.4" }, "devDependencies": { - "@wantere/eslint-config": "workspace:*", - "@wantere/typescript-config": "workspace:*", + "@p2p-local/eslint-config": "workspace:*", + "@p2p-local/typescript-config": "workspace:*", "eslint": "^10.10.0", "typescript": "~6.0.3" } diff --git a/packages/validation/src/auth.ts b/packages/validation/src/auth.ts index 6d4f8ed..2653fbf 100644 --- a/packages/validation/src/auth.ts +++ b/packages/validation/src/auth.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { OTP } from '@wantere/config'; +import { OTP } from '@p2p-local/config'; import { phoneSchema } from './primitives'; export const registerSchema = z.object({ diff --git a/packages/validation/src/listing.ts b/packages/validation/src/listing.ts index ee00592..5ec7352 100644 --- a/packages/validation/src/listing.ts +++ b/packages/validation/src/listing.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; -import { LISTING_LIMITS, SUPPORTED_CURRENCIES } from '@wantere/config'; -import { LISTING_CONDITIONS, LISTING_TYPES, LISTING_STATUSES, requiresPrice } from '@wantere/types'; +import { LISTING_LIMITS, SUPPORTED_CURRENCIES } from '@p2p-local/config'; +import { LISTING_CONDITIONS, LISTING_TYPES, LISTING_STATUSES, requiresPrice } from '@p2p-local/types'; import { idSchema, latitudeSchema, longitudeSchema, paginationSchema } from './primitives'; export const listingTypeSchema = z.enum(LISTING_TYPES); diff --git a/packages/validation/src/primitives.ts b/packages/validation/src/primitives.ts index 16f84b9..c95e8a8 100644 --- a/packages/validation/src/primitives.ts +++ b/packages/validation/src/primitives.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { PAGINATION } from '@wantere/config'; +import { PAGINATION } from '@p2p-local/config'; export const phoneSchema = z .string() @@ -30,3 +30,20 @@ export const paginationSchema = z.object({ }); export type PaginationInput = z.infer; + +/** + * Senegalese mobile numbers as people type them. + * + * `phoneSchema` above is strict E.164, which nobody types: the number is given + * as "77 123 45 67". This accepts the common spellings and always returns + * E.164, so everything downstream stores one shape. + */ +export const senegalMobileSchema = z + .string() + .trim() + .transform((value) => value.replace(/[\s.-]/g, '')) + .refine( + (value) => /^(?:\+221)?7[05-8]\d{7}$/.test(value), + 'Numéro de mobile sénégalais invalide', + ) + .transform((value) => (value.startsWith('+221') ? value : `+221${value}`)); diff --git a/packages/validation/src/report.ts b/packages/validation/src/report.ts index 04d99b9..f27f601 100644 --- a/packages/validation/src/report.ts +++ b/packages/validation/src/report.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { REPORT_REASONS, REPORT_TARGETS } from '@wantere/types'; +import { REPORT_REASONS, REPORT_TARGETS } from '@p2p-local/types'; import { idSchema } from './primitives'; export const createReportSchema = z.object({ diff --git a/packages/validation/tsconfig.json b/packages/validation/tsconfig.json index 50bc9c1..03ef90b 100644 --- a/packages/validation/tsconfig.json +++ b/packages/validation/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@wantere/typescript-config/library.json", + "extends": "@p2p-local/typescript-config/library.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "dist", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9791acc..ab85c5b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ importers: .: devDependencies: - '@wantere/prettier-config': + '@p2p-local/prettier-config': specifier: workspace:* version: link:packages/prettier-config prettier: @@ -18,67 +18,6 @@ importers: specifier: ^2.10.12 version: 2.10.12 - apps/admin: - dependencies: - '@tanstack/react-query': - specifier: ^5.102.8 - version: 5.102.8(react@19.2.3) - '@wantere/api-client': - specifier: workspace:* - version: link:../../packages/api-client - '@wantere/config': - specifier: workspace:* - version: link:../../packages/config - '@wantere/design-tokens': - specifier: workspace:* - version: link:../../packages/design-tokens - '@wantere/types': - specifier: workspace:* - version: link:../../packages/types - clsx: - specifier: ^2.1.1 - version: 2.1.1 - next: - specifier: ^16.3.4 - version: 16.3.4(@babel/core@7.29.7(supports-color@8.1.1))(@types/node@26.4.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: - specifier: 19.2.3 - version: 19.2.3 - react-dom: - specifier: 19.2.3 - version: 19.2.3(react@19.2.3) - tailwind-merge: - specifier: ^3.6.0 - version: 3.6.0 - devDependencies: - '@tailwindcss/postcss': - specifier: ^4.3.3 - version: 4.3.3 - '@types/node': - specifier: ^26.4.1 - version: 26.4.1 - '@types/react': - specifier: ^19.2.18 - version: 19.2.18 - '@types/react-dom': - specifier: ^19.2.7 - version: 19.2.7(@types/react@19.2.18) - '@wantere/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@wantere/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config - eslint: - specifier: ^10.10.0 - version: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) - tailwindcss: - specifier: ^4.3.3 - version: 4.3.3 - typescript: - specifier: ~6.0.3 - version: 6.0.3 - apps/api: dependencies: '@nestjs/bullmq': @@ -108,18 +47,18 @@ importers: '@nestjs/throttler': specifier: ^6.5.0 version: 6.5.0(@nestjs/common@12.0.1(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@8.1.1))(@nestjs/core@12.0.1)(reflect-metadata@0.2.2) + '@p2p-local/config': + specifier: workspace:* + version: link:../../packages/config + '@p2p-local/types': + specifier: workspace:* + version: link:../../packages/types '@prisma/adapter-pg': specifier: ^7.10.0 version: 7.10.0 '@prisma/client': specifier: ^7.10.0 version: 7.10.0(prisma@7.10.0(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@6.0.3))(typescript@6.0.3) - '@wantere/config': - specifier: workspace:* - version: link:../../packages/config - '@wantere/types': - specifier: workspace:* - version: link:../../packages/types argon2: specifier: ^0.45.1 version: 0.45.1 @@ -169,6 +108,12 @@ importers: '@nestjs/testing': specifier: ^12.0.1 version: 12.0.1(@nestjs/common@12.0.1(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@8.1.1))(@nestjs/core@12.0.1)(@nestjs/platform-express@12.0.1) + '@p2p-local/eslint-config': + specifier: workspace:* + version: link:../../packages/eslint-config + '@p2p-local/typescript-config': + specifier: workspace:* + version: link:../../packages/typescript-config '@types/express': specifier: ^5.0.6 version: 5.0.6 @@ -181,12 +126,6 @@ importers: '@types/supertest': specifier: ^7.2.1 version: 7.2.1 - '@wantere/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@wantere/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config cross-env: specifier: ^10.1.0 version: 10.1.0 @@ -220,150 +159,107 @@ importers: apps/mobile: dependencies: - '@react-native-async-storage/async-storage': - specifier: 2.2.0 - version: 2.2.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) - '@tanstack/react-query': - specifier: ^5.102.8 - version: 5.102.8(react@19.2.3) - '@wantere/api-client': - specifier: workspace:* - version: link:../../packages/api-client - '@wantere/config': + '@p2p-local/config': specifier: workspace:* version: link:../../packages/config - '@wantere/design-tokens': + '@p2p-local/design-tokens': specifier: workspace:* version: link:../../packages/design-tokens - '@wantere/types': + '@p2p-local/types': specifier: workspace:* version: link:../../packages/types - '@wantere/validation': + '@p2p-local/validation': specifier: workspace:* version: link:../../packages/validation + '@react-native-async-storage/async-storage': + specifier: 2.2.0 + version: 2.2.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) + '@tanstack/react-query': + specifier: ^5.102.8 + version: 5.102.8(react@19.2.3) expo: - specifier: ^57.0.20 - version: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-router: + specifier: ^57.0.24 + version: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-constants: + specifier: ~57.0.19 + version: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-crypto: + specifier: ~57.0.0 + version: 57.0.3(expo@57.0.24) + expo-file-system: + specifier: ~57.0.7 + version: 57.0.7(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) + expo-image: + specifier: ~57.0.0 + version: 57.0.5(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-image-picker: specifier: ~57.0.19 - version: 57.0.19(243f7c591f07ddad51b921ee265ef8e0) - expo-secure-store: - specifier: ~57.0.3 - version: 57.0.3(expo@57.0.20) + version: 57.0.19(expo@57.0.24) + expo-linking: + specifier: ~57.0.10 + version: 57.0.10(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + expo-router: + specifier: ~57.0.22 + version: 57.0.22(63b8705c02a23bc0793934d71227851b) + expo-splash-screen: + specifier: ~57.0.0 + version: 57.0.9(expo@57.0.24)(supports-color@8.1.1)(typescript@6.0.3) expo-status-bar: specifier: ~57.0.1 - version: 57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + version: 57.0.1(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-updates: + specifier: ~57.0.23 + version: 57.0.23(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) react: specifier: 19.2.3 version: 19.2.3 react-native: specifier: 0.86.3 - version: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + version: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) react-native-safe-area-context: specifier: ~5.7.0 - version: 5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + version: 5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-screens: specifier: ~4.26.2 - version: 4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + version: 4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + zod: + specifier: ^4.5.4 + version: 4.5.4 zustand: specifier: ^5.0.15 version: 5.0.15(@types/react@19.2.18)(react@19.2.3) devDependencies: - '@types/react': - specifier: ^19.2.18 - version: 19.2.18 - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../../packages/eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../../packages/typescript-config - eslint: - specifier: ^10.10.0 - version: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) - typescript: - specifier: ~6.0.3 - version: 6.0.3 - - apps/web: - dependencies: - '@hookform/resolvers': - specifier: ^5.9.1 - version: 5.9.1(@sinclair/typebox@0.34.52)(@standard-schema/spec@1.1.0)(ajv@8.20.0)(class-transformer@0.5.1)(class-validator@0.15.1)(effect@3.20.0)(react-hook-form@7.87.0(react@19.2.3))(valibot@1.4.2(typescript@6.0.3))(zod@4.5.4) - '@tanstack/react-query': - specifier: ^5.102.8 - version: 5.102.8(react@19.2.3) - '@wantere/api-client': - specifier: workspace:* - version: link:../../packages/api-client - '@wantere/config': - specifier: workspace:* - version: link:../../packages/config - '@wantere/design-tokens': - specifier: workspace:* - version: link:../../packages/design-tokens - '@wantere/types': - specifier: workspace:* - version: link:../../packages/types - '@wantere/validation': - specifier: workspace:* - version: link:../../packages/validation - clsx: - specifier: ^2.1.1 - version: 2.1.1 - next: - specifier: ^16.3.4 - version: 16.3.4(@babel/core@7.29.7(supports-color@8.1.1))(@types/node@26.4.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: - specifier: 19.2.3 - version: 19.2.3 - react-dom: - specifier: 19.2.3 - version: 19.2.3(react@19.2.3) - react-hook-form: - specifier: ^7.87.0 - version: 7.87.0(react@19.2.3) - tailwind-merge: - specifier: ^3.6.0 - version: 3.6.0 - zod: - specifier: ^4.5.4 - version: 4.5.4 - devDependencies: - '@tailwindcss/postcss': - specifier: ^4.3.3 - version: 4.3.3 - '@types/node': - specifier: ^26.4.1 - version: 26.4.1 + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 '@types/react': specifier: ^19.2.18 version: 19.2.18 - '@types/react-dom': - specifier: ^19.2.7 - version: 19.2.7(@types/react@19.2.18) - '@wantere/eslint-config': - specifier: workspace:* - version: link:../../packages/eslint-config - '@wantere/typescript-config': - specifier: workspace:* - version: link:../../packages/typescript-config eslint: specifier: ^10.10.0 version: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) - tailwindcss: - specifier: ^4.3.3 - version: 4.3.3 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + jest-expo: + specifier: ~57.0.0 + version: 57.0.5(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(expo@57.0.24)(jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) typescript: specifier: ~6.0.3 version: 6.0.3 packages/api-client: devDependencies: - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../typescript-config eslint: @@ -378,10 +274,10 @@ importers: packages/config: devDependencies: - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../typescript-config eslint: @@ -393,10 +289,10 @@ importers: packages/design-tokens: devDependencies: - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../typescript-config eslint: @@ -411,9 +307,6 @@ importers: '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)) - '@next/eslint-plugin-next': - specifier: ^16.3.4 - version: 16.3.4(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)) eslint: specifier: ^10.0.0 version: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) @@ -434,10 +327,10 @@ importers: packages/types: devDependencies: - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../typescript-config eslint: @@ -451,20 +344,20 @@ importers: packages/validation: dependencies: - '@wantere/config': + '@p2p-local/config': specifier: workspace:* version: link:../config - '@wantere/types': + '@p2p-local/types': specifier: workspace:* version: link:../types zod: specifier: ^4.5.4 version: 4.5.4 devDependencies: - '@wantere/eslint-config': + '@p2p-local/eslint-config': specifier: workspace:* version: link:../eslint-config - '@wantere/typescript-config': + '@p2p-local/typescript-config': specifier: workspace:* version: link:../typescript-config eslint: @@ -476,10 +369,6 @@ importers: packages: - '@alloc/quick-lru@5.3.0': - resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==} - engines: {node: '>=10'} - '@angular-devkit/core@22.1.5': resolution: {integrity: sha512-HiY6d5dkIdJs5grP9OHvgkf14QOcDIo+hbuT7YKuLItQ++ZxCwUabJMLCCJ5R0KrstE5NqED0dNcyk5WD01t5Q==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} @@ -993,9 +882,6 @@ packages: '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/runtime@1.11.3': - resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} - '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -1164,12 +1050,6 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.2': resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -1206,8 +1086,8 @@ packages: '@expo-google-fonts/material-symbols@0.4.45': resolution: {integrity: sha512-D5gd/uFa7KfMJX9S11hvej4GpQnBl27oKiUgyIq3cLTPtyDOWBwRgmeePIdV6+PGcedlDkaCND2BnRgAkxzNaA==} - '@expo/cli@57.0.22': - resolution: {integrity: sha512-MdToR0ZZ1yjfkqbP1jcA7viS9duMPGq/C+qQ/21dtq+en583Ghp+O11BP/wujHa9ZGRtXimzuKPZDpPresVE0g==} + '@expo/cli@57.0.26': + resolution: {integrity: sha512-vm769xuEyHMToi3uY66JLzRA2GGK+3WzdH71HNn67FuVhry82dKTvMUoeHYtHiindyeieiWfEvHT8Kr1VyEVPQ==} hasBin: true peerDependencies: expo: '*' @@ -1259,8 +1139,8 @@ packages: '@expo/expo-modules-macros-plugin@0.6.1': resolution: {integrity: sha512-cpsLZE4rqkc1Y3eZTkxB98jrqY1YXgetmtxFt8q89jBRmk3quRuk1BZo+VcnCSObZardjg99r1k5xijEMONFGA==} - '@expo/fingerprint@0.20.12': - resolution: {integrity: sha512-FIR5fkZYeFaLSowmjgyB6RPKl8AXeE8HuCBHHvyxK8UhOjpPfCAmzT4E7v2yub4qqDafKnfcOFCYxvpUEu+01w==} + '@expo/fingerprint@0.20.13': + resolution: {integrity: sha512-h1x+w+JpNRu88a/5SMZRzJs9YDGR/f7R8ApCr7OdenhqmJ00hFxQMzvxajDLL+1P2Y2g/ND0xksusqvBqWSW5Q==} hasBin: true '@expo/image-utils@0.11.5': @@ -1291,11 +1171,11 @@ packages: expo: optional: true - '@expo/metro-file-map@57.0.2': - resolution: {integrity: sha512-tb50nSIWwKpRufSkGuivOK0FbUxv1Uwqptb0SzFTk0bkmYmcy3gIwnCbOHTfmrQDVndRhPEiu2SYgh9Z0PCvGg==} + '@expo/metro-file-map@57.0.3': + resolution: {integrity: sha512-1OXy+uPYY5uc7Tm4VBsd2NRn+3wHhqeqNuEO/Xo4kmYgv8FjYgUAc+bUXON9FpC2ikcLn4EVlGM9ce2exx9Mlg==} - '@expo/metro-runtime@57.0.15': - resolution: {integrity: sha512-9RaFkqIzRud6ol9fc5ZKHgNDYeDjQVBdAQC+rjSQ6RiKV0pY+SjDqGmKY5a4M9TaV0qLMCNNrp5R88BqC2xbuQ==} + '@expo/metro-runtime@57.0.16': + resolution: {integrity: sha512-x43WgZoICpp37BhDV7vixe0bNxbVPPGaBLHYc98ZJ8MU+UC2dk39Y2XvkfYMRRbAUSIkCIJiwdERnptlPg0Ckw==} peerDependencies: '@expo/log-box': ^57.0.4 expo: '*' @@ -1319,8 +1199,8 @@ packages: '@expo/plist@0.8.1': resolution: {integrity: sha512-3gTReGIUm0oRaMClsAJYxBnVPCl6fVpsl8HS+DTVxDhW4GyVyxg9E/Znm3BvcHtUJ51RJJI14pC1wvrNilCRHw==} - '@expo/prebuild-config@57.0.15': - resolution: {integrity: sha512-xTbWHroj0PDmlbqvmU+zF9ZZxveJkiuyiPoeRJYRGruFHebRAWnoTdw5S7d/UCzDBI8ropGGu9g2eb2nMxtvAw==} + '@expo/prebuild-config@57.0.16': + resolution: {integrity: sha512-QA8oMZ7y70kjOzw+abhRl9uYC8Nu/abeUTHr0YVxb3pgIC14gc7w543bYtI+5gEDI3q55jKUViIauC76QvZN1w==} '@expo/require-utils@57.0.5': resolution: {integrity: sha512-kTAXj9lDFEIPMsbAOGCGbjBbMF0oi7CqkYM79KOX0DDD9wSwXmlKL1z2h8OwsrBf7mbOo2DjlRvZu4BEjrIxGw==} @@ -1330,13 +1210,13 @@ packages: typescript: optional: true - '@expo/router-server@57.0.9': - resolution: {integrity: sha512-/PxRQozFesIyCJZOAtrQE8XcmcojNiL5ctPMQnbE4ojC2EJPu0zc7c0Y4PuXsoRxrZxm8Usw76/lCVrXcfTZ2w==} + '@expo/router-server@57.0.10': + resolution: {integrity: sha512-8rGh6N5di7jzu7UC1SuIA1TWmVd+vBwOHwC7/1ww+FA6CcxcWyQlcPl39h2+Jpnul78CVzWpIjOcdKsZsp2zXw==} peerDependencies: '@expo/metro-runtime': ^57.0.15 expo: '*' - expo-constants: ^57.0.17 - expo-font: ^57.0.3 + expo-constants: ^57.0.18 + expo-font: ^57.0.4 expo-router: '*' expo-server: ^57.0.3 react: '*' @@ -1365,8 +1245,8 @@ packages: '@expo/sudo-prompt@9.3.2': resolution: {integrity: sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==} - '@expo/ui@57.0.16': - resolution: {integrity: sha512-3MK74dEPE4mwlv0VbyQKepmHigOs2bcOvay2SFqc1/QSywVTOjbkNPYUbq2H+LyOLP2sHMazrPBwfXGiYn3q7A==} + '@expo/ui@57.0.19': + resolution: {integrity: sha512-WB95zQPge5nb04zgY3O2NmMtxg6G+qFH3yOAHcBkTUrJXoBReQoyY3cfp/8N5Q/azcfHJcBE3Jy0Rwq9OoRrfA==} peerDependencies: '@babel/core': '*' expo: '*' @@ -1394,84 +1274,6 @@ packages: '@gerrit0/mini-shiki@3.23.0': resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} - '@hookform/resolvers@5.9.1': - resolution: {integrity: sha512-7b7vsbraJxKgjVSA1Nur9tLwj539WGJUBLA7QNvXnFoT2pM5Z7G+6rlukk4B2/QrTZy6huRtH6wKeESPKuIr6w==} - peerDependencies: - '@sinclair/typebox': '>=0.25.24' - '@standard-schema/spec': ^1.0.0 - '@typeschema/main': '>=0.13.7' - '@vinejs/vine': ^2.0.0 || ^3.0.0 || ^4.0.0 - ajv: ^8.12.0 - ajv-errors: ^3.0.0 - ajv-formats: ^2.1.1 - arktype: ^2.0.0 - ata-validator: ^1.2.0 - class-transformer: '>=0.4.0' - class-validator: '>=0.12.0' - computed-types: ^1.0.0 - effect: ^3.10.3 - fluentvalidation-ts: ^3.0.0 - fp-ts: ^2.7.0 - io-ts: ^2.0.0 - joi: ^17.0.0 || ^18.0.0 - nope-validator: '>=0.12.0' - react-hook-form: ^7.55.0 - superstruct: '>=0.12.0' - typanion: ^3.3.2 - valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc' - vest: '>=6.0.0' - yup: ^1.0.0 - zod: ^3.25.0 || ^4.0.0 - peerDependenciesMeta: - '@sinclair/typebox': - optional: true - '@standard-schema/spec': - optional: true - '@typeschema/main': - optional: true - '@vinejs/vine': - optional: true - ajv: - optional: true - ajv-errors: - optional: true - ajv-formats: - optional: true - arktype: - optional: true - ata-validator: - optional: true - class-transformer: - optional: true - class-validator: - optional: true - computed-types: - optional: true - effect: - optional: true - fluentvalidation-ts: - optional: true - fp-ts: - optional: true - io-ts: - optional: true - joi: - optional: true - nope-validator: - optional: true - superstruct: - optional: true - typanion: - optional: true - valibot: - optional: true - vest: - optional: true - yup: - optional: true - zod: - optional: true - '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -1492,168 +1294,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/colour@1.1.0': - resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.35.4': - resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==} - engines: {node: '>=20.9.0'} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.35.4': - resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==} - engines: {node: '>=20.9.0'} - cpu: [x64] - os: [darwin] - - '@img/sharp-freebsd-wasm32@0.35.4': - resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==} - engines: {node: '>=20.9.0'} - os: [freebsd] - - '@img/sharp-libvips-darwin-arm64@1.3.3': - resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.3.3': - resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.3.3': - resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-arm@1.3.3': - resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-ppc64@1.3.3': - resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-riscv64@1.3.3': - resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-s390x@1.3.3': - resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-x64@1.3.3': - resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linuxmusl-arm64@1.3.3': - resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-libvips-linuxmusl-x64@1.3.3': - resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-linux-arm64@0.35.4': - resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==} - engines: {node: '>=20.9.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-arm@0.35.4': - resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==} - engines: {node: '>=20.9.0'} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-ppc64@0.35.4': - resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==} - engines: {node: '>=20.9.0'} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-riscv64@0.35.4': - resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==} - engines: {node: '>=20.9.0'} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-s390x@0.35.4': - resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==} - engines: {node: '>=20.9.0'} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-x64@0.35.4': - resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==} - engines: {node: '>=20.9.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-linuxmusl-arm64@0.35.4': - resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==} - engines: {node: '>=20.9.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-linuxmusl-x64@0.35.4': - resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==} - engines: {node: '>=20.9.0'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-wasm32@0.35.4': - resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==} - engines: {node: '>=20.9.0'} - - '@img/sharp-webcontainers-wasm32@0.35.4': - resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==} - engines: {node: '>=20.9.0'} - cpu: [wasm32] - - '@img/sharp-win32-arm64@0.35.4': - resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==} - engines: {node: '>=20.9.0'} - cpu: [arm64] - os: [win32] - - '@img/sharp-win32-ia32@0.35.4': - resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==} - engines: {node: ^20.9.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.35.4': - resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==} - engines: {node: '>=20.9.0'} - cpu: [x64] - os: [win32] - '@inquirer/ansi@2.0.8': resolution: {integrity: sha512-WpQM+Ti6Z40EFwwt+uL2p4UabT+W179zHp6HhLVOzfbwnVn05IPO/eXIZXGNqcT1jbQ15SujNLzQ39k4QPPxBQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1816,10 +1456,23 @@ packages: resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} engines: {node: '>=8'} + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/console@30.5.1': resolution: {integrity: sha512-u5Ncuc+gXVUwjNMFQOnphHo2Qx2DxyC8Dvpmf4HCx4y0kvSkRRNiQYRixrvOP4V7y52JcSuNxqochCt0PpdHVg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + '@jest/core@30.5.1': resolution: {integrity: sha512-BL9g6CJUUhIbdoAflz/Va658erSSXUIvU8XUYiWNTbZljJjZ5yaC9EJ9/dQ19rpbYV3ZOK4sBACqhPaTyhoUIA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1829,22 +1482,42 @@ packages: node-notifier: optional: true + '@jest/create-cache-key-function@29.7.0': + resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/diff-sequences@30.5.0': resolution: {integrity: sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/environment@30.5.1': resolution: {integrity: sha512-eYJAkOsrpwDXPcoLNEG6lN9Zo3Cy35pxnVQD74vyIfsi/Q8wB/lZFsEjU4wrecOgT4ZviQDZaX/cFIJyMdMxTw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect-utils@30.5.1': resolution: {integrity: sha512-WcRWhHQdTMRDpyWKZ/6MINBmovI7zeD+bL8wFjCncRV3NQOwKy1X45IfyblfHR4k/XciIlNEdFL9QjFO+HNKOg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect@30.5.1': resolution: {integrity: sha512-uOGd40P/COyUp9xHf5jeGiGJC2/ANg+2+Tk9/xN5/LxmlY/r/gxsPrx3DTEtaRZsLAX4wgNSLEDELZ5bmVs2bA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/fake-timers@30.5.1': resolution: {integrity: sha512-rEkV6YzpBXo/L9cnj2ibyuYZuyGiNWaPUsyCu3HYJbqCV4jnEiKmf7hId20z8eKjZ0JQ9jtIYKxRSmYB/OYSsA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1853,6 +1526,10 @@ packages: resolution: {integrity: sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/globals@30.5.1': resolution: {integrity: sha512-VhqvQ251XIC7pk46YymI3HCeBLOdvriDw9zibekodAHEwoVvbVVgpU5H13GvmyOAzxtZCfsm1uvzqkaqJf2I+g==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1861,6 +1538,15 @@ packages: resolution: {integrity: sha512-HdNQYSdRTEBNrginaqzQtTjG0HRMfrra/z6Ok7uL3S87vSlarIVohEsJsSj5edu3MiHoHjAkvPROz5ZjoKai+w==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + '@jest/reporters@30.5.1': resolution: {integrity: sha512-RbUXIfv85KxitJn4l3MpAoMilkvXe2QCO5lXxHWftywo/VdZ5vkEoHRDgphcxP6qmoIkUaN8/UZj6NhdkIFdJg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1882,18 +1568,34 @@ packages: resolution: {integrity: sha512-V3wnxNtiVmw5PPVg433Cn3VdXnsOeu/ofLw3KC04Bn2y1wIlU5kozXQn48rhrgj/02LrCVtntTEF1yBha0XSUw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/source-map@30.5.0': resolution: {integrity: sha512-xWpTJP9D0bDFGbPGT8XuWSwwha/iHADyyKzUnMx4UbdgnHugxrDaQFO4RZ8x4ZsFzRP6pNii8uvlgKCDxCIuDg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-result@30.5.1': resolution: {integrity: sha512-A/1S6ZBdpic50E0pxLgvaB9XNPL4k7AksmG69OO2oiotxciWZwHkbOec+qbIi+uUtIIByOVlXJUl97oZUsz+Jw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-sequencer@30.5.1': resolution: {integrity: sha512-SHcPnrjdVRYJv6y6l4JUTy4Jccu7zmO6BmiOfOA34UiVBto22s19WiDC0A/2qfM7MWB/qdcoqfSIRMitpjTT4A==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/transform@30.5.1': resolution: {integrity: sha512-EDnDhn0jleU9ZhpVoA4gvqw+Ev0iw/r5upNT2b79RiwiaTiYAMMhvNJP3lmocjIe5J2ZkoNr0B3K/J6O5GIm4Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2184,80 +1886,10 @@ packages: '@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 reflect-metadata: ^0.1.13 || ^0.2.0 - '@next/env@16.3.4': - resolution: {integrity: sha512-cjWZnUUa6jZq2kFaNe/ZyJdZonOZ/QoN0Zka2nz/FLOrfx14pQuM9c5RaSVkWMqgdt4ksgPAMWPyHSs/CyV48Q==} - - '@next/eslint-plugin-next@16.3.4': - resolution: {integrity: sha512-szW9y2Aumu4z88YXfTzcFsgUAg2k64uzbtcO5L9f1AKS4w/GUKJcbFllRflROVyNPgJtGOnvNxiyp3v6b+prIA==} - - '@next/swc-darwin-arm64@16.3.4': - resolution: {integrity: sha512-iBr3I5LZNk5/bgl5//iTgD2tcym14MX0Xo7fD//u9dYAEgGzza1y9oywluPtf74YnOswVdH1908aK9xVz7zQTw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@16.3.4': - resolution: {integrity: sha512-2dpiSyl2Jw/NrBPaU2MAKGSa+2MR82pJIn4Sm5Rjr+gxAeuh0z158Su3Z2O8zn7UNNq+ej4bToed6RcRN/Lydg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@16.3.4': - resolution: {integrity: sha512-+t+U8HZT+fApePCS5h89CSH3datz29MkzyfCn+6fpsZBG/oiEOhINcb9rtkv6sdpToLGFn2e6146NzaKCXkqrA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@next/swc-linux-arm64-musl@16.3.4': - resolution: {integrity: sha512-mx03GNs1ocQA5JQ4FxDMmIsNkdrZh8cuezKCrId28e5/gIPU/l7Kcy2+vmCCzdjnnmXJy+iOAu+7K0QppO6Urg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@next/swc-linux-x64-gnu@16.3.4': - resolution: {integrity: sha512-YIhGY6fSMfha52bnVxnzc9zaVBzJg+cqQTOD8tXIBSx4fuv0pVMxQTE0PaS59YhnMOiYiG09IMwxJAf/CFm/Dw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@next/swc-linux-x64-musl@16.3.4': - resolution: {integrity: sha512-+eaaX6axpDb0yF1GCpiERe6njplvdC+nks/fKfcHu3XPGRrald8P3/X7yv7QLdjA51knnxwl9pxdIJsg+w1L+Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@next/swc-win32-arm64-msvc@16.3.4': - resolution: {integrity: sha512-0jcXW7Xs/uzICrmgV3MhDYDeRy++1CqnpDIerlPIqYO4bhzB4WNbX/aRnQclustsAyTkFKB0z6rbcjmNg5tR8A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@16.3.4': - resolution: {integrity: sha512-vvBzwu1pYQCp92maZCFCIw/XgOTMR5tur9GjakwIo2cmwRTMKajRZZDS9+e4KsUZWKu1E007WUeAFXRRjZeuzw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@orval/angular@8.28.1': resolution: {integrity: sha512-8SLvDzsuI395Nn7uwMPMxW0soawi4tDeXjEoZZclG+n1ncJ/aiPiNUi9KiJOrQwmux2e4anNFilR47whPRfExA==} @@ -2829,6 +2461,12 @@ packages: resolution: {integrity: sha512-lxmx0GqLEWRIpZfpYFXlYVIs3ENQwaW6Vmp6oi29l2GoQJ1wZfFZRdMimDWlGEk8LKfHar3QH3iaPMkTcK9lEQ==} engines: {node: ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0} + '@react-native/jest-preset@0.86.3': + resolution: {integrity: sha512-oMmBwXUpTgJvGlcXQQPuiQLykoM8jsWYp6RwdJ2NWyIWzJcGp1rmSr3XV7istoIcUt0wdOVLtQs0A0nDm9ND+A==} + engines: {node: '>= 20.19.4'} + peerDependencies: + react: ^19.2.3 + '@react-native/js-polyfills@0.86.3': resolution: {integrity: sha512-eYIJ0es967+tePBFQDnl/gidVFxLns3fnbiK6rxscQrGodvuUO6hwxpQnfNynJ8MjbbndImXihXjcnJdc7SzJg==} engines: {node: ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0} @@ -2905,135 +2543,40 @@ packages: '@shikijs/langs@3.23.0': resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} - '@shikijs/themes@3.23.0': - resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} - - '@shikijs/types@3.23.0': - resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} - - '@shikijs/vscode-textmate@10.0.2': - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - - '@sinclair/typebox@0.27.12': - resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} - - '@sinclair/typebox@0.34.52': - resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} - - '@sindresorhus/is@4.6.0': - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - - '@sindresorhus/merge-streams@4.0.0': - resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} - engines: {node: '>=18'} - - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@15.4.0': - resolution: {integrity: sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@standard-schema/utils@0.3.0': - resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - - '@swc/helpers@0.5.23': - resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} - - '@tailwindcss/node@4.3.3': - resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} - - '@tailwindcss/oxide-android-arm64@4.3.3': - resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.3.3': - resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.3.3': - resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} - '@tailwindcss/oxide-freebsd-x64@4.3.3': - resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': - resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': - resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] + '@sinclair/typebox@0.27.12': + resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} - '@tailwindcss/oxide-linux-arm64-musl@4.3.3': - resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] + '@sinclair/typebox@0.34.52': + resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} - '@tailwindcss/oxide-linux-x64-gnu@4.3.3': - resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} - '@tailwindcss/oxide-linux-x64-musl@4.3.3': - resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} - '@tailwindcss/oxide-wasm32-wasi@4.3.3': - resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': - resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - '@tailwindcss/oxide-win32-x64-msvc@4.3.3': - resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - '@tailwindcss/oxide@4.3.3': - resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} - engines: {node: '>= 20'} + '@sinonjs/fake-timers@15.4.0': + resolution: {integrity: sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==} - '@tailwindcss/postcss@4.3.3': - resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@tanstack/query-core@5.102.8': resolution: {integrity: sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==} @@ -3050,6 +2593,10 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tootallnate/once@2.0.1': + resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} + engines: {node: '>= 10'} + '@turbo/darwin-64@2.10.12': resolution: {integrity: sha512-9nKgKoF6ZOUsM+or0OtNf+TTJSfGvDNP7ZFv/ZGWVwOSCkumyctQiTeHwB4UNljHTnC41AqylgbunLDHoccNrA==} cpu: [x64] @@ -3152,6 +2699,9 @@ packages: '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/hast@3.0.5': resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} @@ -3167,9 +2717,15 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/jest@30.0.0': resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + '@types/jsdom@20.0.1': + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3223,6 +2779,9 @@ packages: '@types/supertest@7.2.1': resolution: {integrity: sha512-4CbBvoYVLHL7+yhbYrZET0vsvuyXTC05aRe7dNQkwMzm56auceoy6Yu3K50uZmwfHna1os3CMSgM/3QVkUtPTw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -3460,6 +3019,10 @@ packages: resolution: {integrity: sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==} engines: {node: '>=14.6'} + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -3472,16 +3035,27 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} + acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + acorn@8.18.0: resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -3520,6 +3094,10 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} + ansi-escapes@6.2.1: + resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} + engines: {node: '>=14.16'} + ansi-regex@4.1.1: resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} engines: {node: '>=6'} @@ -3559,6 +3137,9 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -3593,16 +3174,30 @@ packages: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + babel-jest@30.5.1: resolution: {integrity: sha512-ge1xUVZS91ml09YRMgRGgeKJ4YJpcOiuwteAxFBYLugQyp7cRw+hHej6Ho0vPjvLrjq60bb7JPHH9LAMA1/krA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@babel/core': ^7.11.0 || ^8.0.0-0 + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + babel-plugin-istanbul@8.0.0: resolution: {integrity: sha512-18wCskrN3DgbuBmp1gr7LBGT8xdz5xhQQqFvFhVxbkl8VBCrMKQ2YtqBWtUal1Zrc1HTuX0011+Brjw78TCFkg==} engines: {node: '>=18'} + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + babel-plugin-jest-hoist@30.5.0: resolution: {integrity: sha512-gtGo1B+u14jrZQv6TdSWIWkTqclboo7Qn+dFAGUOIuXLFuJKAdg3U5MIWzZnW4vfUb4dX9skmAMiby86e/SF4A==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -3642,12 +3237,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 || ^8.0.0-0 - babel-preset-expo@57.0.10: - resolution: {integrity: sha512-08bt6bqMZFoQuWO9gkt0EXotbqKHimELFGa1LlKJvY89iKsi4S0FJSFBFJ4pn9NZvofet48HIjYDQ0SZJ7bNrg==} + babel-preset-expo@57.0.12: + resolution: {integrity: sha512-rrZqJPYbVevy7rqibJZQFd3AsleGslJ63vmB3Qs8b5poOO5AHaehUGbZHjb0HoOZO59d86BEifYbq0/ncoM2UQ==} peerDependencies: '@babel/runtime': ^7.20.0 expo: '*' - expo-widgets: ^57.0.16 + expo-widgets: ^57.0.19 react-refresh: '>=0.14.0 <1.0.0' peerDependenciesMeta: '@babel/runtime': @@ -3657,6 +3252,12 @@ packages: expo-widgets: optional: true + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + babel-preset-jest@30.5.0: resolution: {integrity: sha512-ZGPn5ClP4lBDpuOK8W1yQIOy359HmbnZv3suucAlIe+SEE9yDsxV4S2PjSbH2Vc97U+WmzYD7vw3kr8NsQ/i6w==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -3700,6 +3301,9 @@ packages: resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} engines: {node: '>= 5.10.0'} + brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} + brace-expansion@2.1.4: resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} @@ -3793,6 +3397,10 @@ packages: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -3805,6 +3413,10 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + char-regex@2.0.2: + resolution: {integrity: sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==} + engines: {node: '>=12.20'} + chardet@2.2.0: resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} @@ -3831,6 +3443,9 @@ packages: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + cjs-module-lexer@2.2.1: resolution: {integrity: sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==} @@ -3878,10 +3493,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - cluster-key-slot@1.1.1: resolution: {integrity: sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==} engines: {node: '>=0.10.0'} @@ -3953,6 +3564,9 @@ packages: resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} engines: {node: '>= 0.8.0'} + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-stream@2.0.0: resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} engines: {'0': node >= 6.0} @@ -4001,6 +3615,11 @@ packages: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + cron-parser@5.10.0: resolution: {integrity: sha512-izNAxJyRWUP8ljBoDSub5WyrVOUlT4SLGShswE7eoRBpp6QUsSycYxLBMJlbshgPBMcPT/nrfgjNY2918ayv2A==} engines: {node: '>=18'} @@ -4014,6 +3633,16 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -4065,6 +3694,10 @@ packages: resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} engines: {node: '>=12'} + data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} @@ -4093,6 +3726,9 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} engines: {node: '>=0.10'} @@ -4158,9 +3794,18 @@ packages: dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dnssd-advertise@1.1.6: resolution: {integrity: sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==} + domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead + dotenv-expand@13.0.0: resolution: {integrity: sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==} engines: {node: '>=12'} @@ -4219,14 +3864,14 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - enhanced-resolve@5.24.5: - resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} - engines: {node: '>=10.13.0'} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4283,6 +3928,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-prettier@10.1.8: resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true @@ -4362,61 +4012,106 @@ packages: resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} engines: {node: '>= 0.8.0'} + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect@30.5.1: resolution: {integrity: sha512-m8YrYgvKe9+9gEnWEuKz+qCGfHqkrff7PPfyDnOFkjsfYRKqiYyOxDFMFieCGAuhtk/VNm63tvNgKZVzVy+Hvg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - expo-asset@57.0.16: - resolution: {integrity: sha512-IBRfQdW3iFT+GOBERMZLZM1MUNyrjMgMskuD0elVZ1ae44858UFlTJkHO3f8vi+u5zuv7O7KofsiN8NMG/uWzw==} + expo-asset@57.0.18: + resolution: {integrity: sha512-zDIQkUr0NM2S7YRj98Zohf/OBuM1q0o4ctxLz1C1oe4/33lHNLjp+2v3qUtBWVwn0zKka8UGADmS8M+83Wi6pw==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo-constants@57.0.17: - resolution: {integrity: sha512-cPWYBKN1SEbg2lXg2f8VkePJqGZrJPLvVdQDCTfbFu9sQHO1M31Y1zILReUuGnmt/VKeUz40ze579vR00xGu/A==} + expo-constants@57.0.19: + resolution: {integrity: sha512-3eK1kZRwCdMizQLlM/PPlPwjaPnB5qKvdRDMBMnB1ZxmvWJBf9TB4uEO4DMMfIPaFUxYFs29dsR5fPr1gh3FTQ==} + peerDependencies: + expo: '*' + react-native: '*' + + expo-crypto@57.0.3: + resolution: {integrity: sha512-SAWqEfF37nc8ot7bXsVmu9AFYwQdC2kGvH/eNAHiR3bmlcf1Vv8wu9AnGKT+a90r3T8YfwMpZP4QAYlo4vCn9w==} + peerDependencies: + expo: '*' + + expo-eas-client@57.0.4: + resolution: {integrity: sha512-VSPi6Kldu0EpPkC2e3bv3QNAUVDogbz1tTj7KgcdbsuUySt0hu24g4f1fJ/YjYzCw9G1l755x4QQctcX1j7UEA==} + + expo-file-system@57.0.7: + resolution: {integrity: sha512-1vkZRadOsIputFDBcclqBa1pO3iXOO6iIsdqJipQWw4V5TSnWgmRTuOF7ro8IzrVue+PHbum++KCG3Tawem4cg==} peerDependencies: expo: '*' react-native: '*' - expo-file-system@57.0.6: - resolution: {integrity: sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==} + expo-font@57.0.4: + resolution: {integrity: sha512-7WOMC2oA6xCfOm8bbofqWn2bIqyWFm7YLEnpc/gA1MJH0Ll0TfT/3+CqRkoW2eNRWMS8sxrz5WukUmSvmNquHA==} peerDependencies: expo: '*' + react: '*' react-native: '*' - expo-font@57.0.3: - resolution: {integrity: sha512-kiVUnc2A8vAvO2FfDJTsQa5BwmY+PAkof/1wRb5MOkcX1jtiaSTwz9gCUAyscMBFLundZDmZrLy1P7LZVC+NvA==} + expo-glass-effect@57.0.3: + resolution: {integrity: sha512-aTh2J5eCxf+rSRMBJTnP8Ib5/k8DYFVDuEX1xqesN9F9aqTXocwMv/aQRVBNUs/iogDWhHIJz2pN97IsrrTcoA==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo-glass-effect@57.0.1: - resolution: {integrity: sha512-m/n8maxqNcHk6ZDhuqXBfD5Kt1Iz3M8xykVgdB0iSCIXvF70IqWXmQhX8Psswhrp8eZ+3r0mAD0Jh/2gFA3QaA==} + expo-image-loader@57.0.1: + resolution: {integrity: sha512-uhrZKLT/cTl2mXyR28kPpVkS5O+PK9N1QA/07IFM4f5T4g0lTW1JHT3NEWwEEsGFldPmVX4j7LwUVVZxE+woug==} + peerDependencies: + expo: '*' + + expo-image-picker@57.0.19: + resolution: {integrity: sha512-SWKY235q7TOmlGhFTUWhJZnRqrW/HYHG/6USypa1qgnaQ0ndvToUGjZwVMeAlqtJeqJCXOXSAJzXTxkw7jJc+A==} + peerDependencies: + expo: '*' + + expo-image@57.0.5: + resolution: {integrity: sha512-jOm5lofaIKXhQ7i0Hz3I5JuNULw/aghmpIPZXddwQcEtw8+wUhlozq3M7LbsOrcsBEapcG4jFs85DsfuFoz1tQ==} peerDependencies: expo: '*' react: '*' react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native-web: + optional: true + + expo-json-utils@57.0.2: + resolution: {integrity: sha512-9kYZECLKE3pYZQs+kt3+ggY83Lfryog9/UEo3HJKGcHUZeKKtlFBIPFjI4LzREubsvjP7AsvG0FdEX9EquIoAQ==} - expo-keep-awake@57.0.1: - resolution: {integrity: sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg==} + expo-keep-awake@57.0.2: + resolution: {integrity: sha512-GqgH746wtJImmsbyHmCQoi7cOslKuWQBbJHXr53S35Bpf5UvxCAztvnitUEd7D0QvFN2rvkOhylbZpgZZfBLlQ==} peerDependencies: expo: '*' react: '*' - expo-linking@57.0.9: - resolution: {integrity: sha512-TQJe3NsnpZXApBg1n6DKaZ4TNhYm+iYWq7W9rTp+G44IBMZSUcI8ba+ffYC/LMY1qw+95AuBPIF1zTx1NQoTXw==} + expo-linking@57.0.10: + resolution: {integrity: sha512-RzRi4l4pIYzjgoCJKnqkO+lUI+M2YX6qgcMIQkIbLAXdcWrykBoKYwHGlmAkdFHQm89GaYcq329yfxG+c1hv8w==} peerDependencies: react: '*' react-native: '*' - expo-modules-autolinking@57.0.12: - resolution: {integrity: sha512-Q8KAlq37nLKsQ+HsS9NpQVpd5jCgqtu694TDUNHBUBpV9ViD82mRBh8Uug/h68RG9xnLS+kuL4nYaCuFRghHjg==} + expo-manifests@57.0.2: + resolution: {integrity: sha512-pPIIcKR73OShwlWMg8H90WRzKUd2krDdKlKAwuQV1FtUwE7H3hQEFw0ePFQY9yFoGMF/77ryYwNKfI5umMcCog==} + peerDependencies: + expo: '*' + + expo-modules-autolinking@57.0.13: + resolution: {integrity: sha512-Hj5NjZRlfccazhKab+wK19leRVUr1Y/PUERaRvegIbUSkq4GVxKq6lU9QHlKQyC16MdD/VS4iwsiLivB4o7lvQ==} hasBin: true - expo-modules-core@57.0.16: - resolution: {integrity: sha512-vPbxDOdvG6Ucpws5ucdbQa+nNmdxKONS1fTg92sy0p4TnHX8hBiExtbrtUA/5+1t3FRCUuiy29/1nJEGdt3E4A==} + expo-modules-core@57.0.18: + resolution: {integrity: sha512-ovB7C+GVQTlKAOIsOIHJVVXN9Mn0ljf2SYBS+afrRaGqq+HZEn1D3o+HReIVeH1NjCn/xDBb7I4HjldHs6luZA==} peerDependencies: react: '*' react-native: '*' @@ -4425,20 +4120,20 @@ packages: react-native-worklets: optional: true - expo-modules-jsi@57.0.8: - resolution: {integrity: sha512-MFwvKP0FXLkEET27KsKvOh/L7Dpu2d00UgzAlmKozJgtI23WTKSyKPxu+EOSs9peSgkHzKI0vQOhWjOseGBMkQ==} + expo-modules-jsi@57.1.0: + resolution: {integrity: sha512-a5ckeHfnbYfonhcHGkM0EU/a0Keh+/OufXy/HyFS+spr5Ib0N4Oh1ZsSYFQhp5xdOUFkVofKRhfH+VmcccIIpA==} peerDependencies: react-native: '*' - expo-router@57.0.19: - resolution: {integrity: sha512-JovzZ066+qhykyJLC4hSEJpM8ToVWnJqbxmTN7USzARM0HgRR/g05a75f/EIsY4S//hbPGm6wGl/ObcCVtAX+A==} + expo-router@57.0.22: + resolution: {integrity: sha512-kOuS3RjMC73YLyBFiV9BzO0Z5OK1nLhPwmptK2II+tePtWXH7oA4zWaPwdWsdzTJRnmGMs/8Sr8YdTPHm1LUCg==} peerDependencies: '@expo/log-box': ^57.0.4 - '@expo/metro-runtime': ^57.0.15 + '@expo/metro-runtime': ^57.0.16 '@testing-library/react-native': '>= 13.2.0' expo: '*' - expo-constants: ^57.0.17 - expo-linking: ^57.0.9 + expo-constants: ^57.0.19 + expo-linking: ^57.0.10 react: '*' react-dom: '*' react-native: '*' @@ -4462,15 +4157,15 @@ packages: react-server-dom-webpack: optional: true - expo-secure-store@57.0.3: - resolution: {integrity: sha512-w7XkSQeUiYXPoKXo1jSrQqql7pyCSyIzOp2k0apsZZBE+RkoLTQIMjcbqc181y6KgupfNnYxkaKe+4MEg94+SA==} - peerDependencies: - expo: '*' - expo-server@57.0.3: resolution: {integrity: sha512-aK+LdKzauHSGmsOStZtyxdzv0zWssCkxTw3m4QuOhfDSJsZaMRTd9O41d8ixU/QfELTbaJ0oRNcF7JFV/7O9YQ==} engines: {node: '>=20.16.0'} + expo-splash-screen@57.0.9: + resolution: {integrity: sha512-7cKDn7uBwg0RkcmY015/5j9st4msWJ4zQiPmQdVZoppW3cFSbv05n7xhM6CjUU466Tx4VRTqDF21HuIHkmnEtA==} + peerDependencies: + expo: '*' + expo-status-bar@57.0.1: resolution: {integrity: sha512-Xwaq1gAoVRWx5dPG5VhT5RSbnI9OilhZnO5qoPBnUaBAa5VzRzfdS8q0/bsPt0jR2DKLtGuP0bQ6efMJ4RIMDg==} peerDependencies: @@ -4478,16 +4173,36 @@ packages: react: '*' react-native: '*' - expo-symbols@57.0.2: - resolution: {integrity: sha512-qZ0iqOflm5lZGwRsQ5Y8sDksw3GAUKwHSX1bJBoocXf7gu14vafIXXYWte+JT9VfXAUGyKodJhLHP/GoOrcNWg==} + expo-structured-headers@57.0.1: + resolution: {integrity: sha512-5VwmitVr2J716pOuHXWmEnHbZhZg63DBOZKH5tj0SR8Sps/3jSAf9wf9+UGTKcKgAxGf1PPwQ0lAQ2bG3RwjAg==} + + expo-symbols@57.0.3: + resolution: {integrity: sha512-uuK5yHLVR7kExUCrO/ItBvp/kp1maQ9Nkb6KvNy5ZUQnN0NMKwuhJ4GvbfS9N3ACmvCjTT4gKvg4yH5UuKIYNA==} peerDependencies: expo: '*' expo-font: '*' react: '*' react-native: '*' - expo@57.0.20: - resolution: {integrity: sha512-H57GWLLpNPrltsrjvx6ROsMecoFQza7h9OzujUjBsaY+aDL+bj3GsZaH3T5v5B96R7txuidUwjUh5q5hi3qttg==} + expo-updates-interface@57.0.2: + resolution: {integrity: sha512-x3SA5toiHZEkW+5oeNdUM1Rvt6M3ExegQsSwS3Z1+S9gn9utGYTGBkb8MBQivhjIZiRlQYDIhauxA8kySQEWtQ==} + peerDependencies: + expo: '*' + + expo-updates@57.0.23: + resolution: {integrity: sha512-try1ndXkEH1qpMqs2Nf1fXxN/0GShZad9dWp8pbQpXAngyRk8k/MxJ5gJuVabkPJ2vEW3IgNvTkq54aOELkpZA==} + hasBin: true + peerDependencies: + expo: '*' + expo-dev-client: '*' + react: '*' + react-native: '*' + peerDependenciesMeta: + expo-dev-client: + optional: true + + expo@57.0.24: + resolution: {integrity: sha512-LxSnKMv7en/w4XDNxW3VOx7SbtQ2Bs4MyGhtoZCToDsEsBPO7pJXlv5GnQUCd7Wi8118QV/VDwsDLBKTB3Z3iQ==} hasBin: true peerDependencies: '@expo/dom-webview': '*' @@ -4532,10 +4247,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -4560,9 +4271,6 @@ packages: fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} - fastq@1.20.3: - resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==} - fb-dotslash@0.5.8: resolution: {integrity: sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==} engines: {node: '>=20'} @@ -4666,6 +4374,9 @@ packages: resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} engines: {node: '>=14.14'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -4727,10 +4438,6 @@ packages: resolution: {integrity: sha512-r+mvuDjrjMpsdw46Kmeydb8bdHm7wOKw8wNBtTndkjbPjgAp5oUJUxRE76wZFknxIPokfWvep2qSXK37aXE6zg==} hasBin: true - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -4744,6 +4451,10 @@ packages: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + globals@17.12.0: resolution: {integrity: sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==} engines: {node: '>=18'} @@ -4834,6 +4545,10 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -4841,6 +4556,14 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -4853,6 +4576,10 @@ packages: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} engines: {node: '>=18.18.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + iconv-lite@0.7.3: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} @@ -4882,6 +4609,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -4947,6 +4678,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -4976,6 +4710,10 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + istanbul-lib-instrument@6.0.3: resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} engines: {node: '>=10'} @@ -4984,6 +4722,10 @@ packages: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + istanbul-lib-source-maps@5.0.6: resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} @@ -4999,14 +4741,32 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-changed-files@30.5.1: resolution: {integrity: sha512-0+bvMM/ENhDI29Z8q1r4HxiDIi4G5tnBmSw4esfPQoj9q8Nik7KIyuxHkTVnnniJQf05SxpGaKDQ+4h28ynGPg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-circus@30.5.1: resolution: {integrity: sha512-NgliezXQ6yznqR4W5Gqw++0cZSbBZlF0NknNIAE5VmSJKWOtmWJmWnBq3TSkUOVBTPrT7FGGhVdA8DLWnxo2Sw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + jest-cli@30.5.1: resolution: {integrity: sha512-uwNYepWgaNBCplm42fCIUZTf/tIEHIy5AYvx7eL1BrwIgyjPt+2poouR23UO2yopIP+kV8oZFHfv+l4pg/8prQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -5017,6 +4777,18 @@ packages: node-notifier: optional: true + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + jest-config@30.5.1: resolution: {integrity: sha512-L8PKM2X/ngG8PxfLMqglKGZjylPgw84bVPUlMY9W/o76TnLqPWrmQgsaT0HrheGdRtpGE5FbmREA0Kvb+Qx5gQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -5032,66 +4804,158 @@ packages: ts-node: optional: true + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-diff@30.5.1: resolution: {integrity: sha512-e3cNNMpv8Kh20MjjphTXs+3Vz7DQyLM1nft7KJhnh46atFhjVJRa+0Hq0beywuwsACtMQUBihQkFl8zxb7gt1Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-docblock@30.5.0: resolution: {integrity: sha512-NwDqcxtoZi33RhuW+zJS/RVA3rmheQ8BnwpYZuc/Eruaz6seQb7+aoCeDZu/3X7W2XmD8DbSo9Pn72DbKsBFYw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-each@30.5.1: resolution: {integrity: sha512-S1af0TU4v1EZ/AUlkFs/sxf/5KGsbAT9kRgdyoMX/x72y7C8ZEgETE5o1TPnbKRnrbprc5FR/moYLfdRmqEjsQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-environment-jsdom@29.7.0: + resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-environment-node@30.5.1: resolution: {integrity: sha512-LrPj3sPMjsQoOB3jrb8p/sa+XkSFNKo60TTsyc+EB2kxQJHgbwElpXnx1yX25fdFn5958FIObRtcLSHyV8VIAw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-expo@57.0.5: + resolution: {integrity: sha512-U08fwjaDBwnnbKnZcOA0WQbHfKqOWTCGku+IdCaekrLZmfbbZr3P1WqEsXHo6ntidQ3DmW+TT6G1aOp+ChYfKA==} + hasBin: true + peerDependencies: + '@react-native/jest-preset': ^0.86.3 + expo: '*' + react-native: '*' + react-server-dom-webpack: ~19.0.4 || ~19.1.5 || ~19.2.4 + peerDependenciesMeta: + expo: + optional: true + react-server-dom-webpack: + optional: true + jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@30.5.1: resolution: {integrity: sha512-VIFgt67jW480YDxKfEv9IYQKrFpYt7bOCMn3VsnjK7AK9qo7p6acpnA1DHwsVOULE3dTaYew/6JaTD/d0VDHoQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-leak-detector@30.5.1: resolution: {integrity: sha512-gt4GT2aWgEoCNTcBe4rqS74xTIUJxi+UD9SNSu9aOk5LmTEd6fS5KSTmAKAfitCCktQHNN+upUuL6EkBfFbMDQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@30.5.1: resolution: {integrity: sha512-aroZVqwOz/wC2y6pC+obgFWKV9viaQWQTTSB6W5H55+egtUczIfXR/rxExTv92xD/ADYwpqaYfVWx1aqwKg7FA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-message-util@30.5.1: resolution: {integrity: sha512-UdQlLdd9wL/Ys7xRErckqwD6wPlSZYueosSWuHc1r2ztGLwlgPvtSJq2+BPEgaEY13WLvfFbmhTj8pba0Sd1jg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-mock@30.5.1: resolution: {integrity: sha512-9fVjc3leUpGID2/by/LU4Dvdcp7PFh9LlxS3QRWK3ABm+KtvEVsG/AEGeLY3gKOZsjkBxyfwGltoAVlW7dygHg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-regex-util@30.5.0: resolution: {integrity: sha512-Mg0WK7A6xRHLSA1udJ8y9f3lM0uUhFTBnLKzwPmqB9AylvpleJ6BLemR8K9dK27DY+cesDryoA7yLZCAHsPG1A==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-resolve-dependencies@30.5.1: resolution: {integrity: sha512-JKpXGONDcTaunrNVn8KCl6qAnwl06jIkvv70lhq0Ze47lsPx9sH5HoeEUiXX6iFGnliHN/qpIbQ0l38wrVmXaw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-resolve@30.5.1: resolution: {integrity: sha512-wprhLejRtwN6h8ZgaqC0eYjGJ1uMdGPT/+b3eFncbG4NWuuP9QL+vWwRinu9waw7hkOLcpMJGVJAMgBwsPssMQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runner@30.5.1: resolution: {integrity: sha512-FPlQE4+mwnFxXmpPrSi836KV2ZzvK1g6/nPCT8o5BcoDUUNJQeHo1/Qdkoe/QeoL4M7OeJpbnGUhYKhC1VMdaQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runtime@30.5.1: resolution: {integrity: sha512-UB88+NRkK2Tw/OqV7dofYcyiUGrVZtD41k/N0xQOs9fG//57XHK7JLWG52HD1UYpUAhjK4xm6DBvFX3yWudsMA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-snapshot@30.5.1: resolution: {integrity: sha512-cNWFdSb5xuDGl8hKkAZJ3YtI/PzHpAPFV+HUXWIOG8rMhpDTLVbvAc2d2wRicoYw2wGsJGLaurJT6BLC97bLXQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -5112,6 +4976,19 @@ packages: resolution: {integrity: sha512-i/buJ56wTpxihE93hQYNMfdOThS87+HGvLZzZJmU4xggPcdTYQq051iwALLCHp3q+SkCGH+EFejQZz5EbBSkkg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-watch-select-projects@2.0.0: + resolution: {integrity: sha512-j00nW4dXc2NiCW6znXgFLF9g8PJ0zP25cpQ1xRro/HU2GBfZQFZD0SoXnAlaoKkIY4MlfTMkKGbNXFpvCdjl1w==} + + jest-watch-typeahead@2.2.1: + resolution: {integrity: sha512-jYpYmUnTzysmVnwq49TAxlmtOAwp8QIqvZyoofQFn8fiWhEDZj33ZXzg3JA4nGnzWFm1hbWf3ADpteUokvXgFA==} + engines: {node: ^14.17.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + jest: ^27.0.0 || ^28.0.0 || ^29.0.0 + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-watcher@30.5.1: resolution: {integrity: sha512-+FHJ7C+S7b3ySfhA1aFmoa6TztsnwZVv84ycPRn0tVN93np2EU4b8C/KadqA3l6igdjgLBTnUotab9ER0HLG8A==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -5124,6 +5001,16 @@ packages: resolution: {integrity: sha512-Cbxh5v7AoLuFRmFJSM4/aHdQ68rjXvUWr716EE0Dh3I7T+T/3FgFKhOERGXHcU2Meftq9+9zxPM3TSNyI9D+HA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + jest@30.5.1: resolution: {integrity: sha512-3qrR8+ZXFnn7y0H2yjWQNkGGBLBY4zTRoTMAq9zJcgwLLtlyonfsCLviIXK9xuE2KgIyM+M36AFcoK2DgFR36w==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -5167,6 +5054,15 @@ packages: jsc-safe-url@0.2.4: resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -5238,73 +5134,36 @@ packages: lighthouse-logger@1.4.2: resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - lightningcss-android-arm64@1.33.0: resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - lightningcss-darwin-arm64@1.33.0: resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - lightningcss-darwin-x64@1.33.0: resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - lightningcss-freebsd-x64@1.33.0: resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - lightningcss-linux-arm-gnueabihf@1.33.0: resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - lightningcss-linux-arm64-gnu@1.33.0: resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} @@ -5312,13 +5171,6 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - lightningcss-linux-arm64-musl@1.33.0: resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} @@ -5326,13 +5178,6 @@ packages: os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - lightningcss-linux-x64-gnu@1.33.0: resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} @@ -5340,13 +5185,6 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - lightningcss-linux-x64-musl@1.33.0: resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} @@ -5354,34 +5192,18 @@ packages: os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - lightningcss-win32-arm64-msvc@1.33.0: resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - lightningcss-win32-x64-msvc@1.33.0: resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} - engines: {node: '>= 12.0.0'} - lightningcss@1.33.0: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} @@ -5477,9 +5299,6 @@ packages: resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magic-string@1.0.0: resolution: {integrity: sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA==} @@ -5529,10 +5348,6 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -5699,6 +5514,9 @@ packages: resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@9.0.9: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} @@ -5785,27 +5603,6 @@ packages: pino-http: ^11.0.0 rxjs: ^7.1.0 - next@16.3.4: - resolution: {integrity: sha512-/Ztf6CeRH+ejEXUrYtqI4gkS66eFIHuSwqi60RgcpWKodxFZx2/dqVCMKBwILfAHXQ+F1b1vAudgj3mnxqtoIA==} - engines: {node: '>=20.9.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} @@ -5858,6 +5655,9 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + nwsapi@2.2.27: + resolution: {integrity: sha512-gQPNF78qebCQ6tvVFBYrvJdBNOrYZm90ZlXgpIFm06p6qHDHq/XC4TnJftN6OMbxVE0UTBAoRgcsDeJBBooITw==} + ob1@0.84.5: resolution: {integrity: sha512-aH9RkoZc7w/90HBamFxTw8ZLFr05wXS+iOnvmrgo53Ep8Pyrm5FieQSaPIVROkfFVQISeD/zo92fes26TOwe+A==} engines: {node: ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0} @@ -5977,6 +5777,9 @@ packages: resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==} engines: {node: '>=10'} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -5985,6 +5788,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -6102,10 +5909,6 @@ packages: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} - postcss@8.5.23: - resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.28: resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} engines: {node: ^10 || ^12 || >=14} @@ -6193,6 +5996,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} @@ -6222,8 +6028,8 @@ packages: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} @@ -6249,11 +6055,6 @@ packages: react-devtools-core@6.1.5: resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} - react-dom@19.2.3: - resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} - peerDependencies: - react: ^19.2.3 - react-dom@19.2.8: resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} peerDependencies: @@ -6268,12 +6069,6 @@ packages: peerDependencies: react: '>=17.0.0' - react-hook-form@7.87.0: - resolution: {integrity: sha512-zhFzWvLxNHH+8839OnZcUxgMZw88ah2jZWDWvKWgF3Tpbnd0vKL+dlcuU3nZVWESZQjd81EW8K+wU+cYfYAc0w==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^16.8.0 || ^17 || ^18 || ^19 - react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -6375,6 +6170,11 @@ packages: '@types/react': optional: true + react-test-renderer@19.2.3: + resolution: {integrity: sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw==} + peerDependencies: + react: ^19.2.3 + react@19.2.3: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} @@ -6441,6 +6241,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -6455,6 +6258,10 @@ packages: resolve-workspace-root@2.0.1: resolution: {integrity: sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==} + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + resolve@1.22.12: resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} engines: {node: '>= 0.4'} @@ -6476,10 +6283,6 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - robust-predicates@3.0.3: resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} @@ -6487,9 +6290,6 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} @@ -6516,6 +6316,10 @@ packages: resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -6567,15 +6371,6 @@ packages: shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - sharp@0.35.4: - resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==} - engines: {node: '>=20.9.0'} - peerDependencies: - '@types/node': '*' - peerDependenciesMeta: - '@types/node': - optional: true - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -6628,6 +6423,10 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + slugify@1.6.9: resolution: {integrity: sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==} engines: {node: '>=8.0.0'} @@ -6639,9 +6438,16 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} @@ -6669,6 +6475,9 @@ packages: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} + stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -6676,6 +6485,12 @@ packages: stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + + stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + stacktrace-parser@0.1.11: resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} engines: {node: '>=6'} @@ -6721,6 +6536,10 @@ packages: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} + string-length@5.0.1: + resolution: {integrity: sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==} + engines: {node: '>=12.20'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -6779,19 +6598,6 @@ packages: structured-headers@0.4.1: resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==} - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - superagent@10.3.0: resolution: {integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==} engines: {node: '>=14.18.0'} @@ -6823,20 +6629,13 @@ packages: swagger-ui-dist@5.32.14: resolution: {integrity: sha512-nOA2pSQhcmODMUQZpJHYKNuwniDUqcOWGNaSCOoZv12FdOSJ9JxV95HtyRGNMqEBj6h6lCNTy20TgZDYTSuUIg==} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.11.13: resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} - tailwind-merge@3.6.0: - resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} - - tailwindcss@4.3.3: - resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} - - tapable@2.3.3: - resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} - engines: {node: '>=6'} - terminal-link@2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} engines: {node: '>=8'} @@ -6846,6 +6645,10 @@ packages: engines: {node: '>=10'} hasBin: true + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + test-exclude@7.0.2: resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} @@ -6879,6 +6682,14 @@ packages: toqr@0.1.1: resolution: {integrity: sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -7033,6 +6844,10 @@ packages: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -7053,6 +6868,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -7123,6 +6941,10 @@ packages: vlq@1.0.1: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -7132,12 +6954,29 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + whatwg-fetch@3.6.20: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + whatwg-url-minimum@0.1.2: resolution: {integrity: sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A==} + whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -7161,6 +7000,10 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@5.0.1: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -7193,6 +7036,10 @@ packages: resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} engines: {node: '>=10.0.0'} + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + xml2js@0.6.0: resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==} engines: {node: '>=4.0.0'} @@ -7205,6 +7052,9 @@ packages: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -7276,8 +7126,6 @@ packages: snapshots: - '@alloc/quick-lru@5.3.0': {} - '@angular-devkit/core@22.1.5(chokidar@5.0.0)': dependencies: ajv: 8.20.0 @@ -7901,11 +7749,6 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.3': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 @@ -7996,11 +7839,6 @@ snapshots: eslint: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))': - dependencies: - eslint: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) - eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.2': {} '@eslint/config-array@0.23.5(supports-color@8.1.1)': @@ -8032,7 +7870,7 @@ snapshots: '@expo-google-fonts/material-symbols@0.4.45': {} - '@expo/cli@57.0.22(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-constants@57.0.17)(expo-font@57.0.3)(expo-router@57.0.19)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3)': + '@expo/cli@57.0.26(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.16)(expo-constants@57.0.19)(expo-font@57.0.4)(expo-router@57.0.22)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@expo/code-signing-certificates': 0.0.6 '@expo/config': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) @@ -8042,16 +7880,16 @@ snapshots: '@expo/image-utils': 0.11.5(supports-color@8.1.1)(typescript@6.0.3) '@expo/inline-modules': 0.1.7(supports-color@8.1.1)(typescript@6.0.3) '@expo/json-file': 11.0.1 - '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@expo/metro': 56.0.2(supports-color@8.1.1) - '@expo/metro-config': 57.0.12(expo@57.0.20)(supports-color@8.1.1)(typescript@6.0.3) - '@expo/metro-file-map': 57.0.2(supports-color@8.1.1) + '@expo/metro-config': 57.0.12(expo@57.0.24)(supports-color@8.1.1)(typescript@6.0.3) + '@expo/metro-file-map': 57.0.3(supports-color@8.1.1) '@expo/osascript': 2.7.1 '@expo/package-manager': 1.13.1 '@expo/plist': 0.8.1 - '@expo/prebuild-config': 57.0.15(supports-color@8.1.1)(typescript@6.0.3) + '@expo/prebuild-config': 57.0.16(supports-color@8.1.1)(typescript@6.0.3) '@expo/require-utils': 57.0.5(supports-color@8.1.1)(typescript@6.0.3) - '@expo/router-server': 57.0.9(@expo/metro-runtime@57.0.15)(expo-constants@57.0.17)(expo-font@57.0.3)(expo-router@57.0.19)(expo-server@57.0.3)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(supports-color@8.1.1) + '@expo/router-server': 57.0.10(@expo/metro-runtime@57.0.16)(expo-constants@57.0.19)(expo-font@57.0.4)(expo-router@57.0.22)(expo-server@57.0.3)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(supports-color@8.1.1) '@expo/schema-utils': 57.0.2 '@expo/spawn-async': 1.8.0 '@expo/ws-tunnel': 2.0.0(ws@8.21.3) @@ -8068,7 +7906,7 @@ snapshots: connect: 3.7.0(supports-color@8.1.1) debug: 4.4.3(supports-color@8.1.1) dnssd-advertise: 1.1.6 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) expo-server: 57.0.3 fetch-nodeshim: 0.4.10 getenv: 2.0.0 @@ -8095,8 +7933,8 @@ snapshots: ws: 8.21.3 zod: 3.25.76 optionalDependencies: - expo-router: 57.0.19(243f7c591f07ddad51b921ee265ef8e0) - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + expo-router: 57.0.22(63b8705c02a23bc0793934d71227851b) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - '@expo/dom-webview' - '@expo/metro-runtime' @@ -8158,18 +7996,18 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/devtools@57.0.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@expo/devtools@57.0.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: chalk: 4.1.2 optionalDependencies: react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - '@expo/dom-webview@57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@expo/dom-webview@57.0.1(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) '@expo/env@2.4.3(supports-color@8.1.1)': dependencies: @@ -8181,7 +8019,7 @@ snapshots: '@expo/expo-modules-macros-plugin@0.6.1': {} - '@expo/fingerprint@0.20.12(supports-color@8.1.1)': + '@expo/fingerprint@0.20.13(supports-color@8.1.1)': dependencies: '@expo/env': 2.4.3(supports-color@8.1.1) '@expo/spawn-async': 1.8.0 @@ -8230,16 +8068,16 @@ snapshots: - supports-color - typescript - '@expo/log-box@57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@expo/log-box@57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - '@expo/dom-webview': 57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/dom-webview': 57.0.1(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) anser: 1.4.10 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) stacktrace-parser: 0.1.11 - '@expo/metro-config@57.0.12(expo@57.0.20)(supports-color@8.1.1)(typescript@6.0.3)': + '@expo/metro-config@57.0.12(expo@57.0.24)(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@babel/code-frame': 7.29.7 '@babel/core': 7.29.7(supports-color@8.1.1) @@ -8265,14 +8103,14 @@ snapshots: postcss: 8.5.28 resolve-from: 5.0.0 optionalDependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) transitivePeerDependencies: - bufferutil - supports-color - typescript - utf-8-validate - '@expo/metro-file-map@57.0.2(supports-color@8.1.1)': + '@expo/metro-file-map@57.0.3(supports-color@8.1.1)': dependencies: debug: 4.4.3(supports-color@8.1.1) fb-watchman: 2.0.2 @@ -8283,14 +8121,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/metro-runtime@57.0.15(@expo/log-box@57.0.4)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@expo/metro-runtime@57.0.16(@expo/log-box@57.0.4)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) anser: 1.4.10 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) pretty-format: 29.7.0 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) stacktrace-parser: 0.1.11 whatwg-fetch: 3.6.20 optionalDependencies: @@ -8336,7 +8174,7 @@ snapshots: base64-js: 1.5.1 xmlbuilder: 15.1.1 - '@expo/prebuild-config@57.0.15(supports-color@8.1.1)(typescript@6.0.3)': + '@expo/prebuild-config@57.0.16(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@expo/config': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) '@expo/config-plugins': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) @@ -8345,7 +8183,7 @@ snapshots: '@expo/json-file': 11.0.1 '@react-native/normalize-colors': 0.86.3 debug: 4.4.3(supports-color@8.1.1) - expo-modules-autolinking: 57.0.12(supports-color@8.1.1)(typescript@6.0.3) + expo-modules-autolinking: 57.0.13(supports-color@8.1.1)(typescript@6.0.3) resolve-from: 5.0.0 semver: 7.8.5 transitivePeerDependencies: @@ -8362,17 +8200,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/router-server@57.0.9(@expo/metro-runtime@57.0.15)(expo-constants@57.0.17)(expo-font@57.0.3)(expo-router@57.0.19)(expo-server@57.0.3)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(supports-color@8.1.1)': + '@expo/router-server@57.0.10(@expo/metro-runtime@57.0.16)(expo-constants@57.0.19)(expo-font@57.0.4)(expo-router@57.0.22)(expo-server@57.0.3)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(supports-color@8.1.1)': dependencies: debug: 4.4.3(supports-color@8.1.1) - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-constants: 57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) - expo-font: 57.0.3(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-constants: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-font: 57.0.4(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-server: 57.0.3 react: 19.2.3 optionalDependencies: - '@expo/metro-runtime': 57.0.15(@expo/log-box@57.0.4)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - expo-router: 57.0.19(243f7c591f07ddad51b921ee265ef8e0) + '@expo/metro-runtime': 57.0.16(@expo/log-box@57.0.4)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-router: 57.0.22(63b8705c02a23bc0793934d71227851b) react-dom: 19.2.8(react@19.2.3) transitivePeerDependencies: - supports-color @@ -8387,175 +8225,54 @@ snapshots: '@expo/sudo-prompt@9.3.2': {} - '@expo/ui@57.0.16(@babel/core@7.29.7(supports-color@8.1.1))(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@expo/ui@57.0.19(4f0edff33624ffc12a98997d036683d3)': dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - sf-symbols-typescript: 2.2.0 - vaul: 1.1.2(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.3))(react@19.2.3) - optionalDependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - react-dom: 19.2.8(react@19.2.3) - react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - '@expo/ws-tunnel@2.0.0(ws@8.21.3)': - dependencies: - ws: 8.21.3 - - '@expo/xcpretty@4.4.4': - dependencies: - '@babel/code-frame': 7.29.7 - chalk: 4.1.2 - js-yaml: 4.3.2 - - '@gerrit0/mini-shiki@3.23.0': - dependencies: - '@shikijs/engine-oniguruma': 3.23.0 - '@shikijs/langs': 3.23.0 - '@shikijs/themes': 3.23.0 - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - - '@hookform/resolvers@5.9.1(@sinclair/typebox@0.34.52)(@standard-schema/spec@1.1.0)(ajv@8.20.0)(class-transformer@0.5.1)(class-validator@0.15.1)(effect@3.20.0)(react-hook-form@7.87.0(react@19.2.3))(valibot@1.4.2(typescript@6.0.3))(zod@4.5.4)': - dependencies: - '@standard-schema/utils': 0.3.0 - react-hook-form: 7.87.0(react@19.2.3) - optionalDependencies: - '@sinclair/typebox': 0.34.52 - '@standard-schema/spec': 1.1.0 - ajv: 8.20.0 - class-transformer: 0.5.1 - class-validator: 0.15.1 - effect: 3.20.0 - valibot: 1.4.2(typescript@6.0.3) - zod: 4.5.4 - - '@humanfs/core@0.19.2': - dependencies: - '@humanfs/types': 0.15.0 - - '@humanfs/node@0.16.8': - dependencies: - '@humanfs/core': 0.19.2 - '@humanfs/types': 0.15.0 - '@humanwhocodes/retry': 0.4.3 - - '@humanfs/types@0.15.0': {} - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} - - '@img/colour@1.1.0': - optional: true - - '@img/sharp-darwin-arm64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.3.3 - optional: true - - '@img/sharp-darwin-x64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.3.3 - optional: true - - '@img/sharp-freebsd-wasm32@0.35.4': - dependencies: - '@img/sharp-wasm32': 0.35.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.3.3': - optional: true - - '@img/sharp-libvips-darwin-x64@1.3.3': - optional: true - - '@img/sharp-libvips-linux-arm64@1.3.3': - optional: true - - '@img/sharp-libvips-linux-arm@1.3.3': - optional: true - - '@img/sharp-libvips-linux-ppc64@1.3.3': - optional: true - - '@img/sharp-libvips-linux-riscv64@1.3.3': - optional: true - - '@img/sharp-libvips-linux-s390x@1.3.3': - optional: true - - '@img/sharp-libvips-linux-x64@1.3.3': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.3.3': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.3.3': - optional: true - - '@img/sharp-linux-arm64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.3.3 - optional: true - - '@img/sharp-linux-arm@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.3.3 - optional: true - - '@img/sharp-linux-ppc64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.3.3 - optional: true - - '@img/sharp-linux-riscv64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.3.3 - optional: true - - '@img/sharp-linux-s390x@0.35.4': + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + sf-symbols-typescript: 2.2.0 + vaul: 1.1.2(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.3))(react@19.2.3) optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.3.3 - optional: true + '@babel/core': 7.29.7(supports-color@8.1.1) + react-dom: 19.2.8(react@19.2.3) + react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' - '@img/sharp-linux-x64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.3.3 - optional: true + '@expo/ws-tunnel@2.0.0(ws@8.21.3)': + dependencies: + ws: 8.21.3 - '@img/sharp-linuxmusl-arm64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 - optional: true + '@expo/xcpretty@4.4.4': + dependencies: + '@babel/code-frame': 7.29.7 + chalk: 4.1.2 + js-yaml: 4.3.2 - '@img/sharp-linuxmusl-x64@0.35.4': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.3.3 - optional: true + '@gerrit0/mini-shiki@3.23.0': + dependencies: + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 - '@img/sharp-wasm32@0.35.4': + '@humanfs/core@0.19.2': dependencies: - '@emnapi/runtime': 1.11.3 - optional: true + '@humanfs/types': 0.15.0 - '@img/sharp-webcontainers-wasm32@0.35.4': + '@humanfs/node@0.16.8': dependencies: - '@img/sharp-wasm32': 0.35.4 - optional: true + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 - '@img/sharp-win32-arm64@0.35.4': - optional: true + '@humanfs/types@0.15.0': {} - '@img/sharp-win32-ia32@0.35.4': - optional: true + '@humanwhocodes/module-importer@1.0.1': {} - '@img/sharp-win32-x64@0.35.4': - optional: true + '@humanwhocodes/retry@0.4.3': {} '@inquirer/ansi@2.0.8': {} @@ -8714,6 +8431,15 @@ snapshots: '@istanbuljs/schema@0.1.6': {} + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + '@jest/console@30.5.1': dependencies: '@jest/types': 30.5.1 @@ -8723,6 +8449,41 @@ snapshots: jest-util: 30.5.1 slash: 3.0.0 + '@jest/core@29.7.0(supports-color@8.1.1)': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0(supports-color@8.1.1) + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0(supports-color@8.1.1) + jest-runner: 29.7.0(supports-color@8.1.1) + jest-runtime: 29.7.0(supports-color@8.1.1) + jest-snapshot: 29.7.0(supports-color@8.1.1) + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + '@jest/core@30.5.1(supports-color@8.1.1)': dependencies: '@jest/console': 30.5.1 @@ -8759,8 +8520,19 @@ snapshots: - supports-color - ts-node + '@jest/create-cache-key-function@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@jest/diff-sequences@30.5.0': {} + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + jest-mock: 29.7.0 + '@jest/environment@30.5.1': dependencies: '@jest/fake-timers': 30.5.1 @@ -8768,10 +8540,21 @@ snapshots: '@types/node': 26.4.1 jest-mock: 30.5.1 + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + '@jest/expect-utils@30.5.1': dependencies: '@jest/get-type': 30.5.0 + '@jest/expect@29.7.0(supports-color@8.1.1)': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + '@jest/expect@30.5.1(supports-color@8.1.1)': dependencies: expect: 30.5.1 @@ -8779,6 +8562,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 26.4.1 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + '@jest/fake-timers@30.5.1': dependencies: '@jest/types': 30.5.1 @@ -8790,6 +8582,15 @@ snapshots: '@jest/get-type@30.5.0': {} + '@jest/globals@29.7.0(supports-color@8.1.1)': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + '@jest/globals@30.5.1(supports-color@8.1.1)': dependencies: '@jest/environment': 30.5.1 @@ -8804,6 +8605,35 @@ snapshots: '@types/node': 26.4.1 jest-regex-util: 30.5.0 + '@jest/reporters@29.7.0(supports-color@8.1.1)': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 26.4.1 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3(supports-color@8.1.1) + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1(supports-color@8.1.1) + istanbul-reports: 3.2.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + '@jest/reporters@30.5.1(supports-color@8.1.1)': dependencies: '@bcoe/v8-coverage': 0.2.3 @@ -8847,6 +8677,12 @@ snapshots: graceful-fs: 4.2.11 natural-compare: 1.4.0 + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 + '@jest/source-map@30.5.0': dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -8854,6 +8690,13 @@ snapshots: convert-source-map: 2.0.0 graceful-fs: 4.2.11 + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + '@jest/test-result@30.5.1': dependencies: '@jest/console': 30.5.1 @@ -8861,6 +8704,13 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 collect-v8-coverage: 1.0.3 + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + '@jest/test-sequencer@30.5.1': dependencies: '@jest/test-result': 30.5.1 @@ -8868,6 +8718,26 @@ snapshots: jest-haste-map: 30.5.1 slash: 3.0.0 + '@jest/transform@29.7.0(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 6.1.1(supports-color@8.1.1) + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + '@jest/transform@30.5.1(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -9118,53 +8988,8 @@ snapshots: '@nestjs/core': 12.0.1(@nestjs/common@12.0.1(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@8.1.1))(@nestjs/platform-express@12.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 - '@next/env@16.3.4': {} - - '@next/eslint-plugin-next@16.3.4(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)) - fast-glob: 3.3.1 - transitivePeerDependencies: - - eslint - - '@next/swc-darwin-arm64@16.3.4': - optional: true - - '@next/swc-darwin-x64@16.3.4': - optional: true - - '@next/swc-linux-arm64-gnu@16.3.4': - optional: true - - '@next/swc-linux-arm64-musl@16.3.4': - optional: true - - '@next/swc-linux-x64-gnu@16.3.4': - optional: true - - '@next/swc-linux-x64-musl@16.3.4': - optional: true - - '@next/swc-win32-arm64-msvc@16.3.4': - optional: true - - '@next/swc-win32-x64-msvc@16.3.4': - optional: true - '@noble/hashes@1.8.0': {} - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.3 - '@orval/angular@8.28.1(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@orval/core': 8.28.1(supports-color@8.1.1)(typescript@6.0.3) @@ -9710,15 +9535,15 @@ snapshots: optionalDependencies: '@types/react': 19.2.18 - '@react-native-async-storage/async-storage@2.2.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))': + '@react-native-async-storage/async-storage@2.2.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))': dependencies: merge-options: 3.0.4 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - '@react-native-masked-view/masked-view@0.3.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@react-native-masked-view/masked-view@0.3.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) '@react-native/assets-registry@0.86.3': {} @@ -9843,6 +9668,18 @@ snapshots: '@react-native/gradle-plugin@0.86.3': {} + '@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)': + dependencies: + '@jest/create-cache-key-function': 29.7.0 + '@react-native/js-polyfills': 0.86.3 + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + jest-environment-node: 29.7.0 + react: 19.2.3 + regenerator-runtime: 0.13.11 + transitivePeerDependencies: + - '@babel/core' + - supports-color + '@react-native/js-polyfills@0.86.3': {} '@react-native/js-polyfills@0.87.1': {} @@ -9870,12 +9707,12 @@ snapshots: '@react-native/normalize-colors@0.86.3': {} - '@react-native/virtualized-lists@0.86.3(@types/react@19.2.18)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': + '@react-native/virtualized-lists@0.86.3(@types/react@19.2.18)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: '@types/react': 19.2.18 @@ -9952,86 +9789,15 @@ snapshots: dependencies: type-detect: 4.0.8 - '@sinonjs/fake-timers@15.4.0': + '@sinonjs/fake-timers@10.3.0': dependencies: '@sinonjs/commons': 3.0.1 - '@standard-schema/spec@1.1.0': {} - - '@standard-schema/utils@0.3.0': {} - - '@swc/helpers@0.5.23': - dependencies: - tslib: 2.8.1 - - '@tailwindcss/node@4.3.3': + '@sinonjs/fake-timers@15.4.0': dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.24.5 - jiti: 2.7.0 - lightningcss: 1.32.0 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.3.3 - - '@tailwindcss/oxide-android-arm64@4.3.3': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.3.3': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.3.3': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.3.3': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.3.3': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.3.3': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.3.3': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.3.3': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.3.3': - optional: true + '@sinonjs/commons': 3.0.1 - '@tailwindcss/oxide@4.3.3': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.3 - '@tailwindcss/oxide-darwin-arm64': 4.3.3 - '@tailwindcss/oxide-darwin-x64': 4.3.3 - '@tailwindcss/oxide-freebsd-x64': 4.3.3 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 - '@tailwindcss/oxide-linux-x64-musl': 4.3.3 - '@tailwindcss/oxide-wasm32-wasi': 4.3.3 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 - - '@tailwindcss/postcss@4.3.3': - dependencies: - '@alloc/quick-lru': 5.3.0 - '@tailwindcss/node': 4.3.3 - '@tailwindcss/oxide': 4.3.3 - postcss: 8.5.28 - tailwindcss: 4.3.3 + '@standard-schema/spec@1.1.0': {} '@tanstack/query-core@5.102.8': {} @@ -10049,6 +9815,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tootallnate/once@2.0.1': {} + '@turbo/darwin-64@2.10.12': optional: true @@ -10153,6 +9921,10 @@ snapshots: '@types/geojson@7946.0.16': {} + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 26.4.1 + '@types/hast@3.0.5': dependencies: '@types/unist': 3.0.3 @@ -10169,11 +9941,22 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/jest@30.0.0': dependencies: expect: 30.5.1 pretty-format: 30.5.1 + '@types/jsdom@20.0.1': + dependencies: + '@types/node': 26.4.1 + '@types/tough-cookie': 4.0.5 + parse5: 7.3.0 + '@types/json-schema@7.0.15': {} '@types/jsonwebtoken@9.0.10': @@ -10204,6 +9987,7 @@ snapshots: '@types/react-dom@19.2.7(@types/react@19.2.18)': dependencies: '@types/react': 19.2.18 + optional: true '@types/react-test-renderer@19.1.0': dependencies: @@ -10236,6 +10020,8 @@ snapshots: '@types/methods': 1.1.4 '@types/superagent': 8.1.11 + '@types/tough-cookie@4.0.5': {} + '@types/unist@3.0.3': {} '@types/validator@13.15.10': {} @@ -10490,6 +10276,8 @@ snapshots: '@xmldom/xmldom@0.9.12': {} + abab@2.0.6: {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -10504,12 +10292,27 @@ snapshots: mime-types: 3.0.2 negotiator: 1.1.0 + acorn-globals@7.0.1: + dependencies: + acorn: 8.18.0 + acorn-walk: 8.3.5 + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: acorn: 8.18.0 + acorn-walk@8.3.5: + dependencies: + acorn: 8.18.0 + acorn@8.18.0: {} + agent-base@6.0.2(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} agent-cli-detector@0.1.7: {} @@ -10542,6 +10345,8 @@ snapshots: dependencies: type-fest: 0.21.3 + ansi-escapes@6.2.1: {} + ansi-regex@4.1.1: {} ansi-regex@5.0.1: {} @@ -10569,6 +10374,8 @@ snapshots: append-field@1.0.0: {} + arg@4.1.3: {} + arg@5.0.2: {} argon2@0.45.1: @@ -10598,6 +10405,19 @@ snapshots: aws-ssl-profiles@1.1.2: {} + babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1(supports-color@8.1.1) + babel-preset-jest: 29.6.3(@babel/core@7.29.7(supports-color@8.1.1)) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + babel-jest@30.5.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -10611,6 +10431,16 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-istanbul@6.1.1(supports-color@8.1.1): + dependencies: + '@babel/helper-plugin-utils': 7.29.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 5.2.1(supports-color@8.1.1) + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + babel-plugin-istanbul@8.0.0(supports-color@8.1.1): dependencies: '@babel/helper-plugin-utils': 7.29.7 @@ -10621,6 +10451,13 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + babel-plugin-jest-hoist@30.5.0: dependencies: '@types/babel__core': 7.20.5 @@ -10688,7 +10525,7 @@ snapshots: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@8.1.1)) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@8.1.1)) - babel-preset-expo@57.0.10(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.20)(react-refresh@0.14.2)(supports-color@8.1.1): + babel-preset-expo@57.0.12(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.24)(react-refresh@0.14.2)(supports-color@8.1.1): dependencies: '@babel/generator': 7.29.8 '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) @@ -10735,11 +10572,17 @@ snapshots: react-refresh: 0.14.2 optionalDependencies: '@babel/runtime': 7.29.7 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) transitivePeerDependencies: - '@babel/core' - supports-color + babel-preset-jest@29.6.3(@babel/core@7.29.7(supports-color@8.1.1)): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) + babel-preset-jest@30.5.0(@babel/core@7.29.7(supports-color@8.1.1)): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -10784,6 +10627,11 @@ snapshots: dependencies: big-integer: 1.6.52 + brace-expansion@1.1.21: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 @@ -10880,6 +10728,11 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -10889,6 +10742,8 @@ snapshots: char-regex@1.0.2: {} + char-regex@2.0.2: {} + chardet@2.2.0: {} chokidar@5.0.0: @@ -10920,6 +10775,8 @@ snapshots: ci-info@4.4.0: {} + cjs-module-lexer@1.4.3: {} + cjs-module-lexer@2.2.1: {} class-transformer@0.5.1: {} @@ -10962,8 +10819,6 @@ snapshots: clone@1.0.4: {} - clsx@2.1.1: {} - cluster-key-slot@1.1.1: {} co@4.6.0: {} @@ -11031,6 +10886,8 @@ snapshots: transitivePeerDependencies: - supports-color + concat-map@0.0.1: {} + concat-stream@2.0.0: dependencies: buffer-from: 1.1.2 @@ -11074,6 +10931,21 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 + create-jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + cron-parser@5.10.0: dependencies: luxon: 3.7.2 @@ -11089,6 +10961,14 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cssom@0.3.8: {} + + cssom@0.5.0: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + csstype@3.2.3: {} d3-array@3.2.1: @@ -11137,6 +11017,12 @@ snapshots: dependencies: d3-array: 3.2.4 + data-urls@3.0.2: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + dateformat@4.6.3: {} debug@2.6.9(supports-color@8.1.1): @@ -11157,6 +11043,8 @@ snapshots: optionalDependencies: supports-color: 8.1.1 + decimal.js@10.6.0: {} + decode-uri-component@0.2.2: {} dedent@1.7.2: {} @@ -11198,8 +11086,14 @@ snapshots: asap: 2.0.6 wrappy: 1.0.2 + diff-sequences@29.6.3: {} + dnssd-advertise@1.1.6: {} + domexception@4.0.0: + dependencies: + webidl-conversions: 7.0.0 + dotenv-expand@13.0.0: dependencies: dotenv: 17.4.2 @@ -11247,13 +11141,10 @@ snapshots: dependencies: once: 1.4.0 - enhanced-resolve@5.24.5: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.3 - entities@4.5.0: {} + entities@6.0.1: {} + env-paths@3.0.0: {} error-ex@1.3.4: @@ -11322,6 +11213,14 @@ snapshots: escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-config-prettier@10.1.8(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)): dependencies: eslint: 10.10.0(jiti@2.7.0)(supports-color@8.1.1) @@ -11438,6 +11337,16 @@ snapshots: exit-x@0.2.2: {} + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + expect@30.5.1: dependencies: '@jest/expect-utils': 30.5.1 @@ -11447,59 +11356,88 @@ snapshots: jest-mock: 30.5.1 jest-util: 30.5.1 - expo-asset@57.0.16(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3): + expo-asset@57.0.18(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3): dependencies: '@expo/image-utils': 0.11.5(supports-color@8.1.1)(typescript@6.0.3) - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-constants: 57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-constants: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - typescript - expo-constants@57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1): + expo-constants@57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: '@expo/env': 2.4.3(supports-color@8.1.1) - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - expo-file-system@57.0.6(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)): + expo-crypto@57.0.3(expo@57.0.24): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + + expo-eas-client@57.0.4: {} + + expo-file-system@57.0.7(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - expo-font@57.0.3(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + expo-font@57.0.4(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) fontfaceobserver: 2.3.0 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + + expo-glass-effect@57.0.3(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + react: 19.2.3 + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + + expo-image-loader@57.0.1(expo@57.0.24): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + + expo-image-picker@57.0.19(expo@57.0.24): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-image-loader: 57.0.1(expo@57.0.24) - expo-glass-effect@57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + expo-image@57.0.5(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + sf-symbols-typescript: 2.2.0 - expo-keep-awake@57.0.1(expo@57.0.20)(react@19.2.3): + expo-json-utils@57.0.2: {} + + expo-keep-awake@57.0.2(expo@57.0.24)(react@19.2.3): dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - expo-linking@57.0.9(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): + expo-linking@57.0.10(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: - expo-constants: 57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-constants: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - expo - supports-color - expo-modules-autolinking@57.0.12(supports-color@8.1.1)(typescript@6.0.3): + expo-manifests@57.0.2(expo@57.0.24): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-json-utils: 57.0.2 + + expo-modules-autolinking@57.0.13(supports-color@8.1.1)(typescript@6.0.3): dependencies: '@expo/require-utils': 57.0.5(supports-color@8.1.1)(typescript@6.0.3) '@expo/spawn-async': 1.8.0 @@ -11509,39 +11447,39 @@ snapshots: - supports-color - typescript - expo-modules-core@57.0.16(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + expo-modules-core@57.0.18(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@expo/expo-modules-macros-plugin': 0.6.1 - expo-modules-jsi: 57.0.8(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) + expo-modules-jsi: 57.1.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: - react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) - expo-modules-jsi@57.0.8(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)): + expo-modules-jsi@57.1.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)): dependencies: - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - expo-router@57.0.19(243f7c591f07ddad51b921ee265ef8e0): + expo-router@57.0.22(63b8705c02a23bc0793934d71227851b): dependencies: - '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - '@expo/metro-runtime': 57.0.15(@expo/log-box@57.0.4)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro-runtime': 57.0.16(@expo/log-box@57.0.4)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@expo/schema-utils': 57.0.2 - '@expo/ui': 57.0.16(@babel/core@7.29.7(supports-color@8.1.1))(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/ui': 57.0.19(4f0edff33624ffc12a98997d036683d3) '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.3) '@radix-ui/react-tabs': 1.1.21(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.3))(react@19.2.3) - '@react-native-masked-view/masked-view': 0.3.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@react-native-masked-view/masked-view': 0.3.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) client-only: 0.0.1 color: 4.2.3 debug: 4.4.3(supports-color@8.1.1) escape-string-regexp: 4.0.0 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-constants: 57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) - expo-glass-effect: 57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - expo-linking: 57.0.9(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-constants: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-glass-effect: 57.0.3(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-linking: 57.0.10(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-server: 57.0.3 - expo-symbols: 57.0.2(expo-font@57.0.3)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-symbols: 57.0.3(expo-font@57.0.4)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) fast-deep-equal: 3.1.3 invariant: 2.2.4 nanoid: 3.3.18 @@ -11549,10 +11487,10 @@ snapshots: react: 19.2.3 react-fast-compare: 3.2.2 react-is: 19.2.8 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-drawer-layout: 4.2.10(d3e3ad05aa2c9aac4e7403ecfa138bc3) - react-native-safe-area-context: 5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - react-native-screens: 4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native-drawer-layout: 4.2.10(9c65bb1a95d51bb544559258759eb2b8) + react-native-safe-area-context: 5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-screens: 4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) server-only: 0.0.1 sf-symbols-typescript: 2.2.0 shallowequal: 1.1.0 @@ -11560,8 +11498,8 @@ snapshots: vaul: 1.1.2(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.3))(react@19.2.3) optionalDependencies: react-dom: 19.2.8(react@19.2.3) - react-native-gesture-handler: 3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - react-native-reanimated: 4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-gesture-handler: 3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) transitivePeerDependencies: - '@babel/core' - '@types/react' @@ -11570,56 +11508,91 @@ snapshots: - react-native-worklets - supports-color - expo-secure-store@57.0.3(expo@57.0.20): - dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-server@57.0.3: {} - expo-status-bar@57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + expo-splash-screen@57.0.9(expo@57.0.24)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/config-plugins': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/image-utils': 0.11.5(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + xml2js: 0.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + expo-status-bar@57.0.1(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + + expo-structured-headers@57.0.1: {} - expo-symbols@57.0.2(expo-font@57.0.3)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + expo-symbols@57.0.3(expo-font@57.0.4)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@expo-google-fonts/material-symbols': 0.4.45 - expo: 57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-font: 57.0.3(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-font: 57.0.4(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) sf-symbols-typescript: 2.2.0 - expo@57.0.20(@babel/core@7.29.7(supports-color@8.1.1))(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-router@57.0.19)(react-dom@19.2.8(react@19.2.3))(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3): + expo-updates-interface@57.0.2(expo@57.0.24): + dependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + + expo-updates@57.0.23(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): + dependencies: + '@expo/code-signing-certificates': 0.0.6 + '@expo/plist': 0.8.1 + '@expo/spawn-async': 1.8.0 + arg: 4.1.3 + chalk: 4.1.2 + debug: 4.4.3(supports-color@8.1.1) + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + expo-eas-client: 57.0.4 + expo-manifests: 57.0.2(expo@57.0.24) + expo-structured-headers: 57.0.1 + expo-updates-interface: 57.0.2(expo@57.0.24) + getenv: 2.0.0 + glob: 13.0.6 + ignore: 5.3.2 + nullthrows: 1.1.1 + react: 19.2.3 + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + resolve-from: 5.0.0 + transitivePeerDependencies: + - supports-color + + expo@57.0.24(e48455ad65eda9a98d89cb1034806adf): dependencies: '@babel/runtime': 7.29.7 - '@expo/cli': 57.0.22(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.15)(expo-constants@57.0.17)(expo-font@57.0.3)(expo-router@57.0.19)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + '@expo/cli': 57.0.26(@expo/dom-webview@57.0.1)(@expo/metro-runtime@57.0.16)(expo-constants@57.0.19)(expo-font@57.0.4)(expo-router@57.0.22)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) '@expo/config': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) '@expo/config-plugins': 57.0.9(supports-color@8.1.1)(typescript@6.0.3) - '@expo/devtools': 57.0.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - '@expo/fingerprint': 0.20.12(supports-color@8.1.1) + '@expo/devtools': 57.0.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/fingerprint': 0.20.13(supports-color@8.1.1) '@expo/local-build-cache-provider': 57.0.8(supports-color@8.1.1)(typescript@6.0.3) - '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/log-box': 57.0.4(@expo/dom-webview@57.0.1)(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@expo/metro': 56.0.2(supports-color@8.1.1) - '@expo/metro-config': 57.0.12(expo@57.0.20)(supports-color@8.1.1)(typescript@6.0.3) + '@expo/metro-config': 57.0.12(expo@57.0.24)(supports-color@8.1.1)(typescript@6.0.3) '@ungap/structured-clone': 1.4.0 - babel-preset-expo: 57.0.10(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.20)(react-refresh@0.14.2)(supports-color@8.1.1) - expo-asset: 57.0.16(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) - expo-constants: 57.0.17(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) - expo-file-system: 57.0.6(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) - expo-font: 57.0.3(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - expo-keep-awake: 57.0.1(expo@57.0.20)(react@19.2.3) - expo-modules-autolinking: 57.0.12(supports-color@8.1.1)(typescript@6.0.3) - expo-modules-core: 57.0.16(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + babel-preset-expo: 57.0.12(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.24)(react-refresh@0.14.2)(supports-color@8.1.1) + expo-asset: 57.0.18(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 57.0.19(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-file-system: 57.0.7(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)) + expo-font: 57.0.4(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-keep-awake: 57.0.2(expo@57.0.24)(react@19.2.3) + expo-modules-autolinking: 57.0.13(supports-color@8.1.1)(typescript@6.0.3) + expo-modules-core: 57.0.18(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) pretty-format: 29.7.0 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) react-refresh: 0.14.2 whatwg-url-minimum: 0.1.2 optionalDependencies: - '@expo/dom-webview': 57.0.1(expo@57.0.20)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - '@expo/metro-runtime': 57.0.15(@expo/log-box@57.0.4)(expo@57.0.20)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/dom-webview': 57.0.1(expo@57.0.24)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro-runtime': 57.0.16(@expo/log-box@57.0.4)(expo@57.0.24)(react-dom@19.2.8(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-dom: 19.2.8(react@19.2.3) transitivePeerDependencies: - '@babel/core' @@ -11679,14 +11652,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-glob@3.3.1: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -11709,10 +11674,6 @@ snapshots: dependencies: fast-string-width: 3.0.2 - fastq@1.20.3: - dependencies: - reusify: 1.1.0 - fb-dotslash@0.5.8: {} fb-watchman@2.0.2: @@ -11835,6 +11796,8 @@ snapshots: jsonfile: 6.2.1 universalify: 2.0.1 + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true @@ -11889,10 +11852,6 @@ snapshots: giget@3.3.1: {} - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -11912,6 +11871,15 @@ snapshots: minipass: 7.1.3 path-scurry: 2.0.2 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + globals@17.12.0: {} gopd@1.2.0: {} @@ -11987,6 +11955,10 @@ snapshots: dependencies: lru-cache: 10.4.3 + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + html-escaper@2.0.2: {} http-errors@2.0.1: @@ -11997,6 +11969,21 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + http-proxy-agent@5.0.0(supports-color@8.1.1): + dependencies: + '@tootallnate/once': 2.0.1 + agent-base: 6.0.2(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1(supports-color@8.1.1): + dependencies: + agent-base: 6.0.2(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6(supports-color@8.1.1): dependencies: agent-base: 7.1.4 @@ -12008,6 +11995,10 @@ snapshots: human-signals@8.0.1: {} + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 @@ -12029,6 +12020,11 @@ snapshots: imurmurhash@0.1.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} internmap@2.0.3: {} @@ -12078,6 +12074,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-property@1.0.2: {} @@ -12096,6 +12094,16 @@ snapshots: istanbul-lib-coverage@3.2.2: {} + istanbul-lib-instrument@5.2.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/parser': 7.29.8 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + istanbul-lib-instrument@6.0.3(supports-color@8.1.1): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -12112,6 +12120,14 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 + istanbul-lib-source-maps@4.0.1(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + istanbul-lib-source-maps@5.0.6(supports-color@8.1.1): dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -12133,12 +12149,44 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + jest-changed-files@30.5.1: dependencies: execa: 5.1.1 jest-util: 30.5.1 p-limit: 3.1.0 + jest-circus@29.7.0(supports-color@8.1.1): + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0(supports-color@8.1.1) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.2 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0(supports-color@8.1.1) + jest-snapshot: 29.7.0(supports-color@8.1.1) + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-circus@30.5.1(supports-color@8.1.1): dependencies: '@jest/environment': 30.5.1 @@ -12165,6 +12213,25 @@ snapshots: - babel-plugin-macros - supports-color + jest-cli@29.7.0(@types/node@26.4.1)(supports-color@8.1.1): + dependencies: + '@jest/core': 29.7.0(supports-color@8.1.1) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.3 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jest-cli@30.5.1(@types/node@26.4.1)(supports-color@8.1.1): dependencies: '@jest/core': 30.5.1(supports-color@8.1.1) @@ -12184,6 +12251,36 @@ snapshots: - supports-color - ts-node + jest-config@29.7.0(@types/node@26.4.1)(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0(supports-color@8.1.1) + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0(supports-color@8.1.1) + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 26.4.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-config@30.5.1(@types/node@26.4.1)(supports-color@8.1.1): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -12215,6 +12312,13 @@ snapshots: - babel-plugin-macros - supports-color + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + jest-diff@30.5.1: dependencies: '@jest/diff-sequences': 30.5.0 @@ -12222,10 +12326,22 @@ snapshots: chalk: 4.1.2 pretty-format: 30.5.1 + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + jest-docblock@30.5.0: dependencies: detect-newline: 3.1.0 + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + jest-each@30.5.1: dependencies: '@jest/get-type': 30.5.0 @@ -12234,6 +12350,30 @@ snapshots: jest-util: 30.5.1 pretty-format: 30.5.1 + jest-environment-jsdom@29.7.0(supports-color@8.1.1): + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/jsdom': 20.0.1 + '@types/node': 26.4.1 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jsdom: 20.0.3(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jest-environment-node@30.5.1: dependencies: '@jest/environment': 30.5.1 @@ -12244,8 +12384,51 @@ snapshots: jest-util: 30.5.1 jest-validate: 30.5.1 + jest-expo@57.0.5(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(expo@57.0.24)(jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): + dependencies: + '@jest/create-cache-key-function': 29.7.0 + '@jest/globals': 29.7.0(supports-color@8.1.1) + '@react-native/jest-preset': 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + jest-environment-jsdom: 29.7.0(supports-color@8.1.1) + jest-snapshot: 29.7.0(supports-color@8.1.1) + jest-watch-select-projects: 2.0.0 + jest-watch-typeahead: 2.2.1(jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1)) + json5: 2.2.3 + lodash: 4.18.1 + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-test-renderer: 19.2.3(react@19.2.3) + server-only: 0.0.1 + stacktrace-js: 2.0.2 + optionalDependencies: + expo: 57.0.24(e48455ad65eda9a98d89cb1034806adf) + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - canvas + - jest + - react + - supports-color + - utf-8-validate + jest-get-type@29.6.3: {} + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 26.4.1 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + jest-haste-map@30.5.1: dependencies: '@jest/types': 30.5.1 @@ -12260,11 +12443,23 @@ snapshots: jest-worker: 30.5.1 picomatch: 4.0.7 + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + jest-leak-detector@30.5.1: dependencies: '@jest/get-type': 30.5.0 pretty-format: 30.5.1 + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + jest-matcher-utils@30.5.1: dependencies: '@jest/get-type': 30.5.0 @@ -12272,6 +12467,18 @@ snapshots: jest-diff: 30.5.1 pretty-format: 30.5.1 + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.29.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + jest-message-util@30.5.1: dependencies: '@babel/code-frame': 7.29.7 @@ -12285,6 +12492,12 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + jest-util: 29.7.0 + jest-mock@30.5.1: dependencies: '@jest/expect-utils': 30.5.1 @@ -12292,8 +12505,21 @@ snapshots: '@types/node': 26.4.1 jest-util: 30.5.1 + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + jest-regex-util@30.5.0: {} + jest-resolve-dependencies@29.7.0(supports-color@8.1.1): + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + jest-resolve-dependencies@30.5.1(supports-color@8.1.1): dependencies: jest-regex-util: 30.5.0 @@ -12301,6 +12527,18 @@ snapshots: transitivePeerDependencies: - supports-color + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.12 + resolve.exports: 2.0.3 + slash: 3.0.0 + jest-resolve@30.5.1: dependencies: chalk: 4.1.2 @@ -12311,6 +12549,32 @@ snapshots: slash: 3.0.0 unrs-resolver: 1.12.2 + jest-runner@29.7.0(supports-color@8.1.1): + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0(supports-color@8.1.1) + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + jest-runner@30.5.1(supports-color@8.1.1): dependencies: '@jest/console': 30.5.1 @@ -12338,6 +12602,33 @@ snapshots: transitivePeerDependencies: - supports-color + jest-runtime@29.7.0(supports-color@8.1.1): + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0(supports-color@8.1.1) + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.3 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0(supports-color@8.1.1) + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + jest-runtime@30.5.1(supports-color@8.1.1): dependencies: '@jest/environment': 30.5.1 @@ -12366,6 +12657,31 @@ snapshots: transitivePeerDependencies: - supports-color + jest-snapshot@29.7.0(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/types': 7.29.8 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + jest-snapshot@30.5.1(supports-color@8.1.1): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -12428,6 +12744,34 @@ snapshots: leven: 3.1.0 pretty-format: 30.5.1 + jest-watch-select-projects@2.0.0: + dependencies: + ansi-escapes: 4.3.2 + chalk: 3.0.0 + prompts: 2.4.2 + + jest-watch-typeahead@2.2.1(jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1)): + dependencies: + ansi-escapes: 6.2.1 + chalk: 4.1.2 + jest: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + jest-regex-util: 29.6.3 + jest-watcher: 29.7.0 + slash: 5.1.0 + string-length: 5.0.1 + strip-ansi: 7.2.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.4.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + jest-watcher@30.5.1: dependencies: '@jest/test-result': 30.5.1 @@ -12454,6 +12798,18 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jest@29.7.0(@types/node@26.4.1)(supports-color@8.1.1): + dependencies: + '@jest/core': 29.7.0(supports-color@8.1.1) + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@26.4.1)(supports-color@8.1.1) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jest@30.5.1(@types/node@26.4.1)(supports-color@8.1.1): dependencies: '@jest/core': 30.5.1(supports-color@8.1.1) @@ -12494,6 +12850,39 @@ snapshots: jsc-safe-url@0.2.4: {} + jsdom@20.0.3(supports-color@8.1.1): + dependencies: + abab: 2.0.6 + acorn: 8.18.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.6.0 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.6 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0(supports-color@8.1.1) + https-proxy-agent: 5.0.1(supports-color@8.1.1) + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.27 + parse5: 7.3.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.21.3 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@3.1.0: {} json-parse-even-better-errors@2.3.1: {} @@ -12566,88 +12955,39 @@ snapshots: transitivePeerDependencies: - supports-color - lightningcss-android-arm64@1.32.0: - optional: true - lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: - optional: true - lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: - optional: true - lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: - optional: true - lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: - optional: true - lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: - optional: true - lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: - optional: true - lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: - optional: true - lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: - optional: true - lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: - optional: true - lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: - optional: true - lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 - lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 @@ -12735,10 +13075,6 @@ snapshots: luxon@3.7.2: {} - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.6.0 - magic-string@1.0.0: dependencies: '@jridgewell/sourcemap-codec': 1.6.0 @@ -12782,8 +13118,6 @@ snapshots: merge-stream@2.0.0: {} - merge2@1.4.1: {} - methods@1.1.2: {} metro-babel-transformer@0.84.5(supports-color@8.1.1): @@ -13163,6 +13497,10 @@ snapshots: dependencies: brace-expansion: 5.0.9 + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.21 + minimatch@9.0.9: dependencies: brace-expansion: 2.1.4 @@ -13244,32 +13582,6 @@ snapshots: pino-http: 11.0.0 rxjs: 7.8.2 - next@16.3.4(@babel/core@7.29.7(supports-color@8.1.1))(@types/node@26.4.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - '@next/env': 16.3.4 - '@swc/helpers': 0.5.23 - baseline-browser-mapping: 2.11.21 - caniuse-lite: 1.0.30001810 - postcss: 8.5.23 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3) - optionalDependencies: - '@next/swc-darwin-arm64': 16.3.4 - '@next/swc-darwin-x64': 16.3.4 - '@next/swc-linux-arm64-gnu': 16.3.4 - '@next/swc-linux-arm64-musl': 16.3.4 - '@next/swc-linux-x64-gnu': 16.3.4 - '@next/swc-linux-x64-musl': 16.3.4 - '@next/swc-win32-arm64-msvc': 16.3.4 - '@next/swc-win32-x64-msvc': 16.3.4 - babel-plugin-react-compiler: 1.0.0 - sharp: 0.35.4(@types/node@26.4.1) - transitivePeerDependencies: - - '@babel/core' - - '@types/node' - - babel-plugin-macros - node-abort-controller@3.1.1: {} node-addon-api@7.1.1: {} @@ -13316,6 +13628,8 @@ snapshots: nullthrows@1.1.1: {} + nwsapi@2.2.27: {} + ob1@0.84.5: dependencies: flow-enums-runtime: 0.0.6 @@ -13471,10 +13785,16 @@ snapshots: dependencies: pngjs: 3.4.0 + parse5@7.3.0: + dependencies: + entities: 6.0.1 + parseurl@1.3.3: {} path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -13605,12 +13925,6 @@ snapshots: pngjs@3.4.0: {} - postcss@8.5.23: - dependencies: - nanoid: 3.3.18 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.28: dependencies: nanoid: 3.3.18 @@ -13695,6 +14009,10 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + psl@1.15.0: + dependencies: + punycode: 2.3.1 + pump@3.0.4: dependencies: end-of-stream: 1.4.5 @@ -13724,7 +14042,7 @@ snapshots: split-on-first: 1.1.0 strict-uri-encode: 2.0.0 - queue-microtask@1.2.3: {} + querystringify@2.2.0: {} queue@6.0.2: dependencies: @@ -13756,11 +14074,6 @@ snapshots: - bufferutil - utf-8-validate - react-dom@19.2.3(react@19.2.3): - dependencies: - react: 19.2.3 - scheduler: 0.27.0 - react-dom@19.2.8(react@19.2.3): dependencies: react: 19.2.3 @@ -13777,56 +14090,52 @@ snapshots: dependencies: react: 19.2.3 - react-hook-form@7.87.0(react@19.2.3): - dependencies: - react: 19.2.3 - react-is@18.3.1: {} react-is@19.2.8: {} - react-native-drawer-layout@4.2.10(d3e3ad05aa2c9aac4e7403ecfa138bc3): + react-native-drawer-layout@4.2.10(9c65bb1a95d51bb544559258759eb2b8): dependencies: color: 4.2.3 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-gesture-handler: 3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - react-native-reanimated: 4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native-gesture-handler: 3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) use-latest-callback: 0.2.6(react@19.2.3) - react-native-gesture-handler@3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + react-native-gesture-handler@3.2.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@types/react-test-renderer': 19.1.0 invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-is-edge-to-edge@1.3.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + react-native-is-edge-to-edge@1.3.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-reanimated@4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + react-native-reanimated@4.6.0(react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-is-edge-to-edge: 1.3.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native-is-edge-to-edge: 1.3.1(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-worklets: 0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) semver: 7.8.5 - react-native-safe-area-context@5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + react-native-safe-area-context@5.7.0(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) - react-native-screens@4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): + react-native-screens@4.26.2(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 react-freeze: 1.0.4(react@19.2.3) - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) warn-once: 0.1.1 - react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): + react-native-worklets@0.12.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.8 @@ -13844,12 +14153,12 @@ snapshots: '@react-native/metro-config': 0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) convert-source-map: 2.0.0 react: 19.2.3 - react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) + react-native: 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1) semver: 7.8.5 transitivePeerDependencies: - supports-color - react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1): + react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1): dependencies: '@react-native/assets-registry': 0.86.3 '@react-native/codegen': 0.86.3(@babel/core@7.29.7(supports-color@8.1.1)) @@ -13857,7 +14166,7 @@ snapshots: '@react-native/gradle-plugin': 0.86.3 '@react-native/js-polyfills': 0.86.3 '@react-native/normalize-colors': 0.86.3 - '@react-native/virtualized-lists': 0.86.3(@types/react@19.2.18)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@react-native/virtualized-lists': 0.86.3(@types/react@19.2.18)(react-native@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 @@ -13885,6 +14194,7 @@ snapshots: ws: 7.5.13 yargs: 17.7.3 optionalDependencies: + '@react-native/jest-preset': 0.86.3(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) '@types/react': 19.2.18 transitivePeerDependencies: - '@babel/core' @@ -13923,6 +14233,12 @@ snapshots: optionalDependencies: '@types/react': 19.2.18 + react-test-renderer@19.2.3(react@19.2.3): + dependencies: + react: 19.2.3 + react-is: 19.2.8 + scheduler: 0.27.0 + react@19.2.3: {} react@19.2.8: {} @@ -13974,6 +14290,8 @@ snapshots: require-from-string@2.0.2: {} + requires-port@1.0.0: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -13984,6 +14302,8 @@ snapshots: resolve-workspace-root@2.0.1: {} + resolve.exports@2.0.3: {} + resolve@1.22.12: dependencies: es-errors: 1.3.0 @@ -14005,8 +14325,6 @@ snapshots: retry@0.12.0: {} - reusify@1.1.0: {} - robust-predicates@3.0.3: {} router@2.2.0(supports-color@8.1.1): @@ -14019,10 +14337,6 @@ snapshots: transitivePeerDependencies: - supports-color - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -14041,6 +14355,10 @@ snapshots: sax@1.6.1: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} secure-json-parse@4.1.0: {} @@ -14113,40 +14431,6 @@ snapshots: shallowequal@1.1.0: {} - sharp@0.35.4(@types/node@26.4.1): - dependencies: - '@img/colour': 1.1.0 - detect-libc: 2.1.2 - semver: 7.8.5 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.35.4 - '@img/sharp-darwin-x64': 0.35.4 - '@img/sharp-freebsd-wasm32': 0.35.4 - '@img/sharp-libvips-darwin-arm64': 1.3.3 - '@img/sharp-libvips-darwin-x64': 1.3.3 - '@img/sharp-libvips-linux-arm': 1.3.3 - '@img/sharp-libvips-linux-arm64': 1.3.3 - '@img/sharp-libvips-linux-ppc64': 1.3.3 - '@img/sharp-libvips-linux-riscv64': 1.3.3 - '@img/sharp-libvips-linux-s390x': 1.3.3 - '@img/sharp-libvips-linux-x64': 1.3.3 - '@img/sharp-libvips-linuxmusl-arm64': 1.3.3 - '@img/sharp-libvips-linuxmusl-x64': 1.3.3 - '@img/sharp-linux-arm': 0.35.4 - '@img/sharp-linux-arm64': 0.35.4 - '@img/sharp-linux-ppc64': 0.35.4 - '@img/sharp-linux-riscv64': 0.35.4 - '@img/sharp-linux-s390x': 0.35.4 - '@img/sharp-linux-x64': 0.35.4 - '@img/sharp-linuxmusl-arm64': 0.35.4 - '@img/sharp-linuxmusl-x64': 0.35.4 - '@img/sharp-webcontainers-wasm32': 0.35.4 - '@img/sharp-win32-arm64': 0.35.4 - '@img/sharp-win32-ia32': 0.35.4 - '@img/sharp-win32-x64': 0.35.4 - '@types/node': 26.4.1 - optional: true - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -14205,6 +14489,8 @@ snapshots: slash@3.0.0: {} + slash@5.1.0: {} + slugify@1.6.9: {} sonic-boom@4.2.1: @@ -14213,11 +14499,18 @@ snapshots: source-map-js@1.2.1: {} + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + source-map@0.5.6: {} + source-map@0.5.7: {} source-map@0.6.1: {} @@ -14232,12 +14525,27 @@ snapshots: sqlstring@2.3.3: {} + stack-generator@2.0.10: + dependencies: + stackframe: 1.3.4 + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 stackframe@1.3.4: {} + stacktrace-gps@3.1.2: + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + + stacktrace-js@2.0.2: + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + stacktrace-parser@0.1.11: dependencies: type-fest: 0.7.1 @@ -14267,6 +14575,11 @@ snapshots: char-regex: 1.0.2 strip-ansi: 6.0.1 + string-length@5.0.1: + dependencies: + char-regex: 2.0.2 + strip-ansi: 7.2.0 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -14318,13 +14631,6 @@ snapshots: structured-headers@0.4.1: {} - styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@8.1.1))(react@19.2.3): - dependencies: - client-only: 0.0.1 - react: 19.2.3 - optionalDependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - superagent@10.3.0(supports-color@8.1.1): dependencies: component-emitter: 1.3.1 @@ -14370,16 +14676,12 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 + symbol-tree@3.2.4: {} + synckit@0.11.13: dependencies: '@pkgr/core': 0.3.6 - tailwind-merge@3.6.0: {} - - tailwindcss@4.3.3: {} - - tapable@2.3.3: {} - terminal-link@2.1.1: dependencies: ansi-escapes: 4.3.2 @@ -14392,6 +14694,12 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 7.2.3 + minimatch: 3.1.5 + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.6 @@ -14425,6 +14733,17 @@ snapshots: toqr@0.1.1: {} + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@3.0.0: + dependencies: + punycode: 2.3.1 + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: typescript: 6.0.3 @@ -14556,6 +14875,8 @@ snapshots: unicorn-magic@0.3.0: {} + universalify@0.2.0: {} + universalify@2.0.1: {} unpipe@1.0.0: {} @@ -14597,6 +14918,11 @@ snapshots: dependencies: punycode: 2.3.1 + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + use-callback-ref@1.3.3(@types/react@19.2.18)(react@19.2.3): dependencies: react: 19.2.3 @@ -14649,6 +14975,10 @@ snapshots: vlq@1.0.1: {} + w3c-xmlserializer@4.0.0: + dependencies: + xml-name-validator: 4.0.0 + walker@1.0.8: dependencies: makeerror: 1.0.12 @@ -14659,10 +14989,23 @@ snapshots: dependencies: defaults: 1.0.4 + webidl-conversions@7.0.0: {} + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + whatwg-fetch@3.6.20: {} + whatwg-mimetype@3.0.0: {} + whatwg-url-minimum@0.1.2: {} + whatwg-url@11.0.0: + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -14685,6 +15028,11 @@ snapshots: wrappy@1.0.2: {} + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 @@ -14699,6 +15047,8 @@ snapshots: simple-plist: 1.3.1 uuid: 7.0.3 + xml-name-validator@4.0.0: {} + xml2js@0.6.0: dependencies: sax: 1.6.1 @@ -14708,6 +15058,8 @@ snapshots: xmlbuilder@15.1.1: {} + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 079b00e..c8c2a55 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -14,3 +14,14 @@ allowBuilds: msgpackr-extract: true prisma: true unrs-resolver: true + +minimumReleaseAgeExclude: + - '@expo/cli@57.0.26' + - expo-asset@57.0.18 + - expo-constants@57.0.19 + - expo@57.0.24 + - '@expo/metro-runtime@57.0.16' + - '@expo/ui@57.0.19' + - expo-image-picker@57.0.19 + - expo-router@57.0.22 + - expo-updates@57.0.23