npm package: @jysperu/schema-direccion
Description: Esquemas para direcciones: Mongoose, JSON Schema y Joi
Author: JYS Perú
Latest version: 1.0.1

# @jysperu/schema-direccion

[![npm version](https://badge.fury.io/js/@jysperu%2Fschema-direccion.svg)](https://badge.fury.io/js/@jysperu%2Fschema-direccion)
[![npm downloads](https://img.shields.io/npm/dm/@jysperu/schema-direccion)](https://www.npmjs.com/package/@jysperu/schema-direccion)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Node.js](https://img.shields.io/badge/Node.js-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
[![MongoDB](https://img.shields.io/badge/MongoDB-47A248?logo=mongodb&logoColor=white)](https://www.mongodb.com/)
[![Joi](https://img.shields.io/badge/Joi-FF6B6B?logo=joi&logoColor=white)](https://joi.dev/)
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/@jysperu/schema-direccion)](https://bundlephobia.com/package/@jysperu/schema-direccion)

Esquemas para direcciones con soporte para **Mongoose**, **JSON Schema** y **Joi**.

## 🚀 Características

- 🏠 **Validación** de direcciones
- 🌍 **Soporte** para direcciones de Perú y otros países
- 🔧 **Desglose** automático de componentes de dirección
- 🏷️ **Clasificaciones** del tipo de dirección (Trabajo, Personal, etc.)
- ✅ **Estados** de validación y verificación
- 📍 **Coordenadas** GPS y ubigeo
- 🗺️ **División política** (departamento, provincia, distrito)

## 📦 Instalación

```bash
npm install @jysperu/schema-direccion
```

## ⚡ Inicio Rápido

```typescript
import { MongoSchemaDireccion, JsonSchemaDireccion, JoiSchemaDireccion } from "@jysperu/schema-direccion";
import { IDireccion, ClasificacionDireccion } from "@jysperu/schema-direccion";

// Mongoose
const PersonaSchema = new Schema({
  direcciones: [MongoSchemaDireccion],
});

// Joi Validation
const { error, value } = JoiSchemaDireccion.validate({
  direccion_completa: "Av. Javier Prado Este 123, San Isidro, Lima",
  tipo: "Personal",
  pais: "Perú",
  valida: true,
});

// JSON Schema
const validate = ajv.compile(JsonSchemaDireccion);
const isValid = validate(direccionData);
```

## 📚 Esquemas Disponibles

### 1. 🍃 Mongoose Schema

```typescript
import { MongoSchemaDireccion, IDireccion } from "@jysperu/schema-direccion";
import { Schema, model, Document } from "mongoose";

interface IPersona extends Document {
  nombres: string;
  direcciones: IDireccion[];
}

const PersonaSchema = new Schema<IPersona>({
  nombres: { type: String, required: true },
  direcciones: [MongoSchemaDireccion], // Array de direcciones
});

const PersonaModel = model<IPersona>("Persona", PersonaSchema);
```

### 2. 📋 JSON Schema

```typescript
import { JsonSchemaDireccion } from "@jysperu/schema-direccion";
import Ajv from "ajv";

const ajv = new Ajv();
const validate = ajv.compile(JsonSchemaDireccion);

const direccion = {
  direccion_completa: "Av. Javier Prado Este 123, San Isidro, Lima",
  tipo: "Personal",
  pais: "Perú",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "San Isidro",
  valida: true,
};

const valid = validate(direccion);
if (!valid) console.log(validate.errors);
```

### 3. ✅ Joi Schema

```typescript
import { JoiSchemaDireccion } from "@jysperu/schema-direccion";

// Validación individual
const { error, value } = JoiSchemaDireccion.validate({
  direccion_completa: "Av. Arequipa 1234, Lince, Lima",
  tipo: "Personal",
  pais: "Perú",
  departamento: "Lima",
  valida: true,
});

if (error) {
  error.details.forEach((err) => console.log(`❌ ${err.path}: ${err.message}`));
}

// Para arrays de direcciones
import Joi from "@jysperu/joi-spanish";

const personaSchema = Joi.object({
  nombres: Joi.string().required(),
  direcciones: Joi.array().items(JoiSchemaDireccion).default([]),
});
```

## 🛠️ Casos de Uso Avanzados

### Crear persona con múltiples direcciones

```typescript
import { MongoSchemaDireccion, IDireccion, ClasificacionDireccion } from "@jysperu/schema-direccion";

const persona = new PersonaModel({
  nombres: "Ana García",
  direcciones: [
    {
      direccion_completa: "Av. Javier Prado Este 4200, Surquillo, Lima",
      tipo: ClasificacionDireccion.TRABAJO,
      pais: "Perú",
      pais_code: "PE",
      departamento: "Lima",
      provincia: "Lima",
      distrito: "Surquillo",
      via_tipo: "Avenida",
      via_nombre: "Javier Prado Este",
      nro: "4200",
      valida: true,
      verificada: true,
    },
    {
      direccion_completa: "Jr. Los Olivos 123, Miraflores, Lima",
      tipo: ClasificacionDireccion.PERSONAL,
      pais: "Perú",
      pais_code: "PE",
      departamento: "Lima",
      provincia: "Lima",
      distrito: "Miraflores",
      via_tipo: "Jirón",
      via_nombre: "Los Olivos",
      nro: "123",
      valida: true,
    },
  ],
});

await persona.save();
```

### Operaciones con direcciones

```typescript
// Buscar direcciones verificadas
const direccionesVerificadas = persona.direcciones.filter((direccion) => direccion.verificada);

// Encontrar direcciones de trabajo
const direccionesDeTrabajo = persona.direcciones.filter((direccion) => direccion.tipo === ClasificacionDireccion.TRABAJO);

// Agregar nueva dirección
persona.direcciones.push({
  direccion_completa: "Calle Las Flores 456, Barranco, Lima",
  tipo: "Secundaria",
  pais: "Perú",
  pais_code: "PE",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "Barranco",
  valida: true,
});

await persona.save();
```

## 📊 Esquema de Datos

### ✅ Campo Obligatorio (Al menos uno)

| Campo                | Tipo     | Validación    | Descripción |
| -------------------- | -------- | ------------- | ----------- | ------------------------------------ |
| `direccion_completa` | `String` | Max 500 chars | -           | Dirección completa formateada        |
| `direccion_simple`   | `String` | Max 300 chars | -           | Versión simplificada de la dirección |
| `direccion`          | `String` | Max 300 chars | -           | Dirección principal o calle          |

### ⚙️ Campos Opcionales

| Campo          | Tipo      | Validación/Enum                      | Defecto             | Descripción                        |
| -------------- | --------- | ------------------------------------ | ------------------- | ---------------------------------- |
| `tipo`         | `String`  | Min 1 char, personalizable           | "Trabajo"           | Clasificación (Trabajo/Personal)   |
| `via_tipo`     | `String`  | Max 20 chars, lowercase              | -                   | Tipo de vía (calle, avenida, etc.) |
| `via_nombre`   | `String`  | Max 150 chars, lowercase             | -                   | Nombre de la vía                   |
| `nro`          | `String`  | Max 10 chars                         | -                   | Número de la dirección             |
| `pais`         | `String`  | Required, trim, max 100              | Nombre del país     |
| `pais_code`    | `String`  | Required, trim, 2-3 chars, uppercase | Código ISO del país |
| `departamento` | `String`  | Max 100 chars                        | -                   | Departamento o estado              |
| `provincia`    | `String`  | Max 100 chars                        | -                   | Provincia o región                 |
| `distrito`     | `String`  | Max 100 chars                        | -                   | Distrito o municipio               |
| `ubigeo`       | `String`  | 6 dígitos                            | -                   | Código ubigeo de 6 dígitos         |
| `gps`          | `String`  | Formato lat,lng                      | -                   | Coordenadas GPS                    |
| `valida`       | `Boolean` | true/false                           | false               | Formato de dirección válido        |
| `verificada`   | `Boolean` | true/false                           | false               | Dirección verificada físicamente   |

### 🏷️ Clasificaciones de Direcciones

```typescript
enum ClasificacionDireccion {
  TRABAJO = "Trabajo", // 🏢 Dirección laboral
  PERSONAL = "Personal", // 👤 Dirección personal
}
```

## 💡 Ejemplos de Datos

### 🏠 Dirección Personal (Completa)

```typescript
const direccionCompleta: IDireccion = {
  direccion_completa: "Av. Javier Prado Este 123, Dpto. 501, San Isidro, Lima",
  tipo: "Personal",
  pais: "Perú",
  pais_code: "PE",
  continente: "América del Sur",
  direccion: "Av. Javier Prado Este 123, Dpto. 501",
  via_tipo: "Avenida",
  via_nombre: "Javier Prado Este",
  nro: "123",
  interior: "Dpto. 501",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "San Isidro",
  ubigeo: "150130",
  gps: "-12.0964,-77.0428",
  valida: true,
  verificada: true,
};
```

### 🏢 Dirección de Trabajo

```typescript
const direccionTrabajo: IDireccion = {
  direccion_completa: "Av. El Sol 456, Piso 8, Oficina 802, Miraflores, Lima",
  tipo: "Trabajo",
  pais: "Perú",
  pais_code: "PE",
  direccion: "Av. El Sol 456",
  via_tipo: "Avenida",
  via_nombre: "El Sol",
  nro: "456",
  interior: "Piso 8, Oficina 802",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "Miraflores",
  ubigeo: "150122",
  valida: true,
  verificada: false,
};
```

### 🏪 Dirección Comercial

```typescript
const direccionComercial: IDireccion = {
  direccion_completa: "Jr. Unión 789, Local 12, Cercado de Lima, Lima",
  tipo: "Comercial",
  pais: "Perú",
  pais_code: "PE",
  direccion: "Jr. Unión 789",
  via_tipo: "Jirón",
  via_nombre: "Unión",
  nro: "789",
  interior: "Local 12",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "Cercado de Lima",
  ubigeo: "150101",
  valida: true,
  verificada: false,
};
```

### 🏫 Dirección Educativa

```typescript
const direccionEducativa: IDireccion = {
  direccion_completa: "Av. Universitaria 1801, San Martín de Porres, Lima",
  tipo: "Educativo",
  pais: "Perú",
  pais_code: "PE",
  direccion: "Av. Universitaria 1801",
  via_tipo: "Avenida",
  via_nombre: "Universitaria",
  nro: "1801",
  departamento: "Lima",
  provincia: "Lima",
  distrito: "San Martín de Porres",
  ubigeo: "150132",
  valida: true,
  verificada: true,
};
```

## 🔧 Configuración del Esquema

```typescript
// Configuración Mongoose
{
  strict: false,        // Permite campos adicionales
  timestamps: true,     // createdAt, updatedAt automáticos
  _id: true             // Cada correo tiene su propio ID
}

// Configuración Joi
{
  stripUnknown: false,  // Mantiene campos extra
  allowUnknown: true,   // Permite propiedades no definidas
  convert: true,        // Conversión automática de tipos
  abortEarly: false     // Muestra todos los errores
}
```

## 📋 JSON Schema Standalone

El archivo `direccion.schema.json` se genera automáticamente en cada build:

```bash
# Usar direccion.schema.json directamente
curl -O https://gitlab.com/tiny.node/schema/direccion/-/raw/main/dist/direccion.schema.json

# Validar con cualquier validador JSON Schema
cat data.json | ajv validate -s direccion.schema.json
```

## 🧪 Testing y Validación

```typescript
// Test básico con Joi
import { JoiSchemaDireccion } from "@jysperu/schema-direccion";

const testCases = [
  { direccion_completa: "Av. Arequipa 123, Lima", pais: "Perú", pais_code: "PE", valid: true },
  { direccion_completa: "", valid: false }, // Vacío
  { pais: "", valid: false }, // Sin país
  { pais_code: "X", valid: false }, // Código inválido
];

testCases.forEach((test) => {
  const result = JoiSchemaDireccion.validate(test);
  console.log(`${test.direccion_completa || "Vacío"}: ${result.error ? "❌" : "✅"}`);
});
```

## 📦 Build y Distribución

```bash
# Construir el proyecto
npm run build

# Genera automáticamente:
# └── dist/
#     ├── direccion.es.js       # ESM
#     ├── direccion.cjs.js      # CommonJS
#     ├── direccion.umd.js      # UMD
#     ├── *.d.ts             # TypeScript definitions
#     └── direccion.schema.json # JSON Schema
```

## 🔗 Enlaces y Recursos

- 📘 **Repositorio**: [GitLab - schema-direccion](https://gitlab.com/tiny.node/schema/direccion)
- 🐛 **Issues**: [Reportar problemas](https://gitlab.com/tiny.node/schema/direccion/issues)
- 📦 **npm**: [@jysperu/schema-direccion](https://www.npmjs.com/package/@jysperu/schema-direccion)
- 📚 **Documentación Joi**: [@jysperu/joi-spanish](https://www.npmjs.com/package/@jysperu/joi-spanish)
- 🏢 **JYS Perú**: [www.jys.pe](https://www.jys.pe)

## 📄 Licencia

**MIT License** - Consulta el archivo [LICENSE](./LICENSE) para detalles completos.

```text
MIT License - Copyright (c) 2025 JYS Perú
```

---

Desarrollado con ❤️ por [**JYS Perú**](https://www.jys.pe)