← Documentación

Arquitectura

Documento de arquitectura del monorepo. Acompaña al PRD (sección 13) y al modelo de datos.

1. Visión general

Tres piezas de código y un backend gestionado:

                       ┌─────────────────────────┐
                       │   packages/shared        │
                       │   @envios/shared         │
                       │  · tipos TypeScript      │
                       │  · esquemas zod          │
                       │  · máquina de estados    │
                       │  · helpers puros (payout)│
                       └───────────┬─────────────┘
                                   │ import (fuente de verdad)
                 ┌─────────────────┴──────────────────┐
                 │                                     │
       ┌─────────▼─────────┐                 ┌─────────▼─────────┐
       │   apps/web        │                 │   apps/mobile     │
       │   Next.js (TS)    │                 │   Expo / RN (TS)  │
       │   empresas + admin│                 │   repartidores    │
       └─────────┬─────────┘                 └─────────┬─────────┘
                 │                                     │
                 └──────────────┬──────────────────────┘
                                │ @supabase/supabase-js
                       ┌────────▼─────────┐
                       │     Supabase     │
                       │ Postgres+PostGIS │
                       │  Auth · Storage  │
                       └──────────────────┘

2. Monorepo (pnpm workspaces + Turborepo)

3. packages/shared — la fuente de verdad

Es el corazón del repo. Define una sola vez los contratos del dominio para que web y mobile no diverjan. Se distribuye como TypeScript sin build (main/types apuntan a src/index.ts); cada app lo transpila:

Contenido (ver DATA-MODEL.md para el detalle):

Módulo Qué expone
brand.ts resolveAppName(), DEFAULT_APP_NAME (nombre parametrizable).
enums.ts Enums del dominio (z.enum) + tipos inferidos.
geo.ts GeoPoint, Zone, DestinationZone.
common.ts Primitivas: Id, timestamps, money, Dimensions, TimeWindow.
entities.ts Esquemas zod + tipos de todas las entidades + DEFAULT_PLATFORM_CONFIG.
state-machine.ts Transiciones de Package y Shipment, isPayoutReleasable, deriveShipmentStatus.
payments.ts computePayout() (puro) + interfaz PaymentProvider (mock pendiente).
geocoding.ts Interfaz Geocoder + tipos (impl. Nominatim en apps/web/lib/geocoder.ts).
dto.ts CourierPackageView + toCourierPackageView() (omite confirmationCode).

Patrón zod-first: los esquemas son la fuente de verdad de validación y los tipos TypeScript se infieren con z.infer, evitando duplicar definiciones.

4. apps/web — Next.js (empresas + back-office)

5. apps/mobile — Expo (repartidores)

6. Backend — Supabase

7. Base de datos y migraciones

El esquema vive versionado en supabase/migrations/: tablas (companies, couriers + courier_destination_areas, areas, shipments, packages, assignments, platform_config), la vista courier_available_packages, la función de toma atómica claim_route (FOR UPDATE SKIP LOCKED), PostGIS, RLS explícito con policies + grants (la auto-exposición de tablas del proyecto está desactivada) y un trigger on_auth_user_created role-aware que, según raw_user_meta_data.role, crea el perfil de company (default, alta desde la web) o de courier (alta desde la app). Cómo aplicarlas: ver el README.

7.b Backend serverless — Edge Functions

Para la monetización por acceso (el repartidor paga para desbloquear el depósito de una ruta que reservó) hay dos Edge Functions (Deno) en supabase/functions/: create-pickup-payment (la llama la app con el JWT del courier; crea la preferencia en Mercado Pago con el token secreto y devuelve el init_point) y mp-webhook (verify_jwt = false; es la fuente de verdad del pago: re-consulta el pago en la API de MP y, si está approved, marca el assignment y revela el depósito). El claim es de dos fases: claim_route reserva (pending + expiración de 15 min); el pago aprobado lo pasa a approved. Regla de oro: el redirect a la app NO es prueba de pago; el webhook server-to-server sí.

8. Lo que todavía NO está