@jysperu/schema-telefono 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 JYS Perú
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,372 @@
1
+ # @jysperu/schema-telefono
2
+
3
+ [![npm version](https://badge.fury.io/js/@jysperu%2Fschema-telefono.svg)](https://badge.fury.io/js/@jysperu%2Fschema-telefono)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@jysperu/schema-telefono)](https://www.npmjs.com/package/@jysperu/schema-telefono)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
8
+ [![MongoDB](https://img.shields.io/badge/MongoDB-47A248?logo=mongodb&logoColor=white)](https://www.mongodb.com/)
9
+ [![Joi](https://img.shields.io/badge/Joi-FF6B6B?logo=joi&logoColor=white)](https://joi.dev/)
10
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@jysperu/schema-telefono)](https://bundlephobia.com/package/@jysperu/schema-telefono)
11
+
12
+ Esquemas para números telefónicos con soporte para **Mongoose**, **JSON Schema** y **Joi**.
13
+
14
+ ## 🚀 Características
15
+
16
+ - 📞 **Validación** de números telefónicos
17
+ - 🌍 **Soporte internacional** completo (E.164, códigos de país)
18
+ - 🔧 **Tipos** de línea telefónica (MOBILE, FIXED_LINE, etc.)
19
+ - 🏷️ **Clasificaciones** del uso telefónico (Trabajo, Personal, etc.)
20
+ - ✅ **Estados** de validación y verificación
21
+
22
+ ## 📦 Instalación
23
+
24
+ ```bash
25
+ npm install @jysperu/schema-telefono
26
+ ```
27
+
28
+ ## ⚡ Inicio Rápido
29
+
30
+ ```typescript
31
+ import { MongoSchemaTelefono, JsonSchemaTelefono, JoiSchemaTelefono } from "@jysperu/schema-telefono";
32
+ import { ITelefono, TipoLineaTelefonica, ClasificacionTelefono } from "@jysperu/schema-telefono";
33
+
34
+ // Mongoose
35
+ const PersonaSchema = new Schema({
36
+ telefonos: [MongoSchemaTelefono],
37
+ });
38
+
39
+ // Joi Validation
40
+ const { error, value } = JoiSchemaTelefono.validate({
41
+ telefono: "987654321",
42
+ countrycode: "pe", // → "PE" automáticamente
43
+ whatsapp: true,
44
+ });
45
+
46
+ // JSON Schema
47
+ const validate = ajv.compile(JsonSchemaTelefono);
48
+ const isValid = validate(telefonoData);
49
+ ```
50
+
51
+ ## 📚 Esquemas Disponibles
52
+
53
+ ### 1. 🍃 Mongoose Schema
54
+
55
+ ```typescript
56
+ import { MongoSchemaTelefono, ITelefono } from "@jysperu/schema-telefono";
57
+ import { Schema, model, Document } from "mongoose";
58
+
59
+ interface IPersona extends Document {
60
+ nombres: string;
61
+ telefonos: ITelefono[];
62
+ }
63
+
64
+ const PersonaSchema = new Schema<IPersona>({
65
+ nombres: { type: String, required: true },
66
+ telefonos: [MongoSchemaTelefono], // Array de teléfonos
67
+ });
68
+
69
+ const PersonaModel = model<IPersona>("Persona", PersonaSchema);
70
+ ```
71
+
72
+ ### 2. 📋 JSON Schema
73
+
74
+ ```typescript
75
+ import { JsonSchemaTelefono } from "@jysperu/schema-telefono";
76
+ import Ajv from "ajv";
77
+
78
+ const ajv = new Ajv();
79
+ const validate = ajv.compile(JsonSchemaTelefono);
80
+
81
+ const telefono = {
82
+ telefono: "987654321",
83
+ tipo: "Personal",
84
+ countrycode: "PE",
85
+ whatsapp: true,
86
+ };
87
+
88
+ const valid = validate(telefono);
89
+ if (!valid) console.log(validate.errors);
90
+ ```
91
+
92
+ ### 3. ✅ Joi Schema
93
+
94
+ ```typescript
95
+ import { JoiSchemaTelefono } from "@jysperu/schema-telefono";
96
+
97
+ // Validación individual
98
+ const { error, value } = JoiSchemaTelefono.validate({
99
+ telefono: "987654321",
100
+ tipo: "Personal",
101
+ countrycode: "pe", // Se convierte a "PE"
102
+ whatsapp: true,
103
+ });
104
+
105
+ if (error) {
106
+ error.details.forEach((err) => console.log(`❌ ${err.path}: ${err.message}`));
107
+ }
108
+
109
+ // Para arrays de teléfonos
110
+ import Joi from "@jysperu/joi-spanish";
111
+
112
+ const personaSchema = Joi.object({
113
+ nombres: Joi.string().required(),
114
+ telefonos: Joi.array().items(JoiSchemaTelefono).default([]),
115
+ });
116
+ ```
117
+
118
+ ## 🛠️ Casos de Uso Avanzados
119
+
120
+ ### Crear persona con múltiples teléfonos
121
+
122
+ ```typescript
123
+ import { MongoSchemaTelefono, ITelefono, TipoLineaTelefonica } from "@jysperu/schema-telefono";
124
+
125
+ const persona = new PersonaModel({
126
+ nombres: "Ana García",
127
+ telefonos: [
128
+ {
129
+ telefono: "987654321",
130
+ tipo: "Personal",
131
+ countrycode: "PE",
132
+ type: TipoLineaTelefonica.MOBILE,
133
+ whatsapp: true,
134
+ valido: true,
135
+ },
136
+ {
137
+ telefono: "014567890",
138
+ tipo: "Trabajo",
139
+ countrycode: "PE",
140
+ type: TipoLineaTelefonica.FIXED_LINE,
141
+ whatsapp: false,
142
+ valido: true,
143
+ },
144
+ ],
145
+ });
146
+
147
+ await persona.save();
148
+ ```
149
+
150
+ ### Operaciones con teléfonos
151
+
152
+ ```typescript
153
+ // Buscar números de WhatsApp
154
+ const whatsappNumbers = persona.telefonos.filter((tel) => tel.whatsapp);
155
+
156
+ // Encontrar móviles verificados
157
+ const mobilesVerificados = persona.telefonos.filter((tel) => tel.type === TipoLineaTelefonica.MOBILE && tel.verificado);
158
+
159
+ // Agregar nuevo teléfono
160
+ persona.telefonos.push({
161
+ telefono: "999888777",
162
+ tipo: "Emergencia",
163
+ type: TipoLineaTelefonica.MOBILE,
164
+ whatsapp: true,
165
+ valido: true,
166
+ });
167
+
168
+ await persona.save();
169
+ ```
170
+
171
+ ## 📊 Esquema de Datos
172
+
173
+ ### ✅ Campo Obligatorio
174
+
175
+ | Campo | Tipo | Validación | Descripción |
176
+ | ---------- | -------- | -------------------------------- | --------------------------- |
177
+ | `telefono` | `String` | Required, trim, contiene dígitos | Número telefónico principal |
178
+
179
+ ### ⚙️ Campos Opcionales
180
+
181
+ | Campo | Tipo | Validación/Enum | Defecto | Descripción |
182
+ | --------------- | --------- | -------------------------- | --------- | -------------------------------- |
183
+ | `tipo` | `String` | Min 1 char, personalizable | "Trabajo" | Clasificación (Trabajo/Personal) |
184
+ | `countrycode` | `String` | ISO 2-3 chars, uppercase | - | Código país (PE, US, BR, etc.) |
185
+ | `country` | `String` | Max 100 chars | - | Nombre completo del país |
186
+ | `countrydial` | `String` | `+?\\d{1,4}` | - | Código marcado (+51, +1, +55) |
187
+ | `e164` | `String` | `+[1-9]\\d{1,14}` | - | Formato E.164 internacional |
188
+ | `international` | `String` | Libre | - | Formato internacional legible |
189
+ | `national` | `String` | Libre | - | Formato nacional del país |
190
+ | `uri` | `String` | Inicia con "tel:" | - | URI telefónica RFC 3966 |
191
+ | `type` | `Enum` | TipoLineaTelefonica | "MOBILE" | Clasificación técnica de línea |
192
+ | `whatsapp` | `Boolean` | true/false | false | Compatible con WhatsApp |
193
+ | `valido` | `Boolean` | true/false | false | Número técnicamente válido |
194
+ | `verificado` | `Boolean` | true/false | false | Verificado por el usuario |
195
+
196
+ ### 📱 Tipos de Línea Telefónica
197
+
198
+ ```typescript
199
+ enum TipoLineaTelefonica {
200
+ MOBILE = "MOBILE", // 📱 Teléfono móvil
201
+ FIXED_LINE = "FIXED_LINE", // 🏠 Línea fija
202
+ FIXED_LINE_OR_MOBILE = "FIXED_LINE_OR_MOBILE", // 🔄 Puede ser fijo o móvil
203
+ TOLL_FREE = "TOLL_FREE", // 🆓 Número gratuito
204
+ PREMIUM_RATE = "PREMIUM_RATE", // 💰 Tarifa premium
205
+ VOIP = "VOIP", // 🌐 Voz sobre IP
206
+ PERSONAL_NUMBER = "PERSONAL_NUMBER", // 👤 Número personal
207
+ SHARED_COST = "SHARED_COST", // 🤝 Costo compartido
208
+ PAGER = "PAGER", // 📟 Buscapersonas
209
+ UAN = "UAN", // 🔗 Acceso universal
210
+ VOICEMAIL = "VOICEMAIL", // 📧 Buzón de voz
211
+ UNKNOWN = "UNKNOWN", // ❓ Tipo desconocido
212
+ }
213
+ ```
214
+
215
+ ### 🏷️ Clasificaciones Personales
216
+
217
+ ```typescript
218
+ enum ClasificacionTelefono {
219
+ TRABAJO = "Trabajo", // 🏢 Teléfono laboral
220
+ PERSONAL = "Personal", // 👤 Teléfono personal
221
+ }
222
+ ```
223
+
224
+ ## 💡 Ejemplos de Datos
225
+
226
+ ### 📱 Móvil Personal (Completo)
227
+
228
+ ```typescript
229
+ const telefonoCompleto: ITelefono = {
230
+ telefono: "987 654 321",
231
+ tipo: "Personal",
232
+ countrycode: "PE",
233
+ country: "Peru",
234
+ countrydial: "+51",
235
+ e164: "+51987654321",
236
+ international: "+51 987 654 321",
237
+ national: "987 654 321",
238
+ uri: "tel:+51-987-654-321",
239
+ type: TipoLineaTelefonica.MOBILE,
240
+ whatsapp: true,
241
+ valido: true,
242
+ verificado: true,
243
+ };
244
+ ```
245
+
246
+ ### 🏢 Fijo de Trabajo
247
+
248
+ ```typescript
249
+ const telefonoTrabajo: ITelefono = {
250
+ telefono: "(01) 456-7890",
251
+ tipo: "Trabajo",
252
+ countrycode: "PE",
253
+ country: "Peru",
254
+ e164: "+5114567890",
255
+ international: "+51 1 456 7890",
256
+ national: "(01) 456-7890",
257
+ type: TipoLineaTelefonica.FIXED_LINE,
258
+ whatsapp: false,
259
+ valido: true,
260
+ };
261
+ ```
262
+
263
+ ### 🆓 Línea Gratuita
264
+
265
+ ```typescript
266
+ const lineaGratuita: ITelefono = {
267
+ telefono: "800-123-4567",
268
+ tipo: "Soporte",
269
+ countrycode: "US",
270
+ country: "United States",
271
+ type: TipoLineaTelefonica.TOLL_FREE,
272
+ whatsapp: false,
273
+ valido: true,
274
+ };
275
+ ```
276
+
277
+ ### 🌐 VOIP Internacional
278
+
279
+ ```typescript
280
+ const voipSkype: ITelefono = {
281
+ telefono: "echo123",
282
+ tipo: "Test VOIP",
283
+ type: TipoLineaTelefonica.VOIP,
284
+ whatsapp: false,
285
+ valido: true,
286
+ };
287
+ ```
288
+
289
+ ## 🔧 Configuración del Esquema
290
+
291
+ ```typescript
292
+ // Configuración Mongoose
293
+ {
294
+ strict: false, // Permite campos adicionales
295
+ timestamps: true, // createdAt, updatedAt automáticos
296
+ _id: true // Cada teléfono tiene su propio ID
297
+ }
298
+
299
+ // Configuración Joi
300
+ {
301
+ stripUnknown: false, // Mantiene campos extra
302
+ allowUnknown: true, // Permite propiedades no definidas
303
+ convert: true, // Conversión automática de tipos
304
+ abortEarly: false // Muestra todos los errores
305
+ }
306
+ ```
307
+
308
+ ## 📋 JSON Schema Standalone
309
+
310
+ El archivo `telefono.schema.json` se genera automáticamente en cada build:
311
+
312
+ ```bash
313
+ # Usar telefono.schema.json directamente
314
+ curl -O https://gitlab.com/tiny.node/schema/telefono/-/raw/main/dist/telefono.schema.json
315
+
316
+ # Validar con cualquier validador JSON Schema
317
+ cat data.json | ajv validate -s telefono.schema.json
318
+ ```
319
+
320
+ ## 🧪 Testing y Validación
321
+
322
+ ```typescript
323
+ // Test básico con Joi
324
+ import { JoiSchemaTelefono } from "@jysperu/schema-telefono";
325
+
326
+ const testCases = [
327
+ { telefono: "987654321", valid: true },
328
+ { telefono: "", valid: false }, // Vacío
329
+ { telefono: "abc", valid: false }, // Sin dígitos
330
+ { countrycode: "pe", expected: "PE" }, // Conversion
331
+ ];
332
+
333
+ testCases.forEach((test) => {
334
+ const result = JoiSchemaTelefono.validate(test);
335
+ console.log(`${test.telefono}: ${result.error ? "❌" : "✅"}`);
336
+ });
337
+ ```
338
+
339
+ ## 📦 Build y Distribución
340
+
341
+ ```bash
342
+ # Construir el proyecto
343
+ npm run build
344
+
345
+ # Genera automáticamente:
346
+ # └── dist/
347
+ # ├── telefono.es.js # ESM
348
+ # ├── telefono.cjs.js # CommonJS
349
+ # ├── telefono.umd.js # UMD
350
+ # ├── *.d.ts # TypeScript definitions
351
+ # └── telefono.schema.json # JSON Schema
352
+ ```
353
+
354
+ ## 🔗 Enlaces y Recursos
355
+
356
+ - 📘 **Repositorio**: [GitLab - schema-telefono](https://gitlab.com/tiny.node/schema/telefono)
357
+ - 🐛 **Issues**: [Reportar problemas](https://gitlab.com/tiny.node/schema/telefono/issues)
358
+ - 📦 **npm**: [@jysperu/schema-telefono](https://www.npmjs.com/package/@jysperu/schema-telefono)
359
+ - 📚 **Documentación Joi**: [@jysperu/joi-spanish](https://www.npmjs.com/package/@jysperu/joi-spanish)
360
+ - 🏢 **JYS Perú**: [www.jys.pe](https://www.jys.pe)
361
+
362
+ ## 📄 Licencia
363
+
364
+ **MIT License** - Consulta el archivo [LICENSE](./LICENSE) para detalles completos.
365
+
366
+ ```text
367
+ MIT License - Copyright (c) 2025 JYS Perú
368
+ ```
369
+
370
+ ---
371
+
372
+ Desarrollado con ❤️ por [**JYS Perú**](https://www.jys.pe)