@gzl10/ts-helpers 4.2.1
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/CHANGELOG.md +320 -0
- package/README.md +233 -0
- package/USAGE-GUIDE.md +800 -0
- package/dist/browser/async.js +15 -0
- package/dist/browser/async.js.map +1 -0
- package/dist/browser/chunk-4O7ZPIJN.js +383 -0
- package/dist/browser/chunk-4O7ZPIJN.js.map +1 -0
- package/dist/browser/chunk-75XNTC34.js +60 -0
- package/dist/browser/chunk-75XNTC34.js.map +1 -0
- package/dist/browser/chunk-C3D7YZVE.js +299 -0
- package/dist/browser/chunk-C3D7YZVE.js.map +1 -0
- package/dist/browser/chunk-CZL6C2EI.js +452 -0
- package/dist/browser/chunk-CZL6C2EI.js.map +1 -0
- package/dist/browser/chunk-D4FZFIVA.js +240 -0
- package/dist/browser/chunk-D4FZFIVA.js.map +1 -0
- package/dist/browser/chunk-IL7NG7IC.js +72 -0
- package/dist/browser/chunk-IL7NG7IC.js.map +1 -0
- package/dist/browser/chunk-NSBPE2FW.js +17 -0
- package/dist/browser/chunk-NSBPE2FW.js.map +1 -0
- package/dist/browser/chunk-SLQVNPTH.js +27 -0
- package/dist/browser/chunk-SLQVNPTH.js.map +1 -0
- package/dist/browser/chunk-WG7ILCUB.js +195 -0
- package/dist/browser/chunk-WG7ILCUB.js.map +1 -0
- package/dist/browser/chunk-WJA4JDMZ.js +278 -0
- package/dist/browser/chunk-WJA4JDMZ.js.map +1 -0
- package/dist/browser/chunk-ZFVYLUTT.js +65 -0
- package/dist/browser/chunk-ZFVYLUTT.js.map +1 -0
- package/dist/browser/chunk-ZYTSVMTI.js +263 -0
- package/dist/browser/chunk-ZYTSVMTI.js.map +1 -0
- package/dist/browser/dates.js +78 -0
- package/dist/browser/dates.js.map +1 -0
- package/dist/browser/environment-detection.js +21 -0
- package/dist/browser/environment-detection.js.map +1 -0
- package/dist/browser/environment.js +34 -0
- package/dist/browser/environment.js.map +1 -0
- package/dist/browser/errors.js +18 -0
- package/dist/browser/errors.js.map +1 -0
- package/dist/browser/index.js +412 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/math.js +51 -0
- package/dist/browser/math.js.map +1 -0
- package/dist/browser/number.js +10 -0
- package/dist/browser/number.js.map +1 -0
- package/dist/browser/objects.js +31 -0
- package/dist/browser/objects.js.map +1 -0
- package/dist/browser/strings.js +80 -0
- package/dist/browser/strings.js.map +1 -0
- package/dist/browser/validation-core.js +54 -0
- package/dist/browser/validation-core.js.map +1 -0
- package/dist/browser/validation-crypto.js +28 -0
- package/dist/browser/validation-crypto.js.map +1 -0
- package/dist/browser/validators.js +98 -0
- package/dist/browser/validators.js.map +1 -0
- package/dist/cjs/async.js +86 -0
- package/dist/cjs/async.js.map +1 -0
- package/dist/cjs/dates.js +285 -0
- package/dist/cjs/dates.js.map +1 -0
- package/dist/cjs/environment-detection.js +84 -0
- package/dist/cjs/environment-detection.js.map +1 -0
- package/dist/cjs/environment.js +261 -0
- package/dist/cjs/environment.js.map +1 -0
- package/dist/cjs/errors.js +80 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +2035 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/math.js +388 -0
- package/dist/cjs/math.js.map +1 -0
- package/dist/cjs/number.js +37 -0
- package/dist/cjs/number.js.map +1 -0
- package/dist/cjs/objects.js +249 -0
- package/dist/cjs/objects.js.map +1 -0
- package/dist/cjs/strings.js +253 -0
- package/dist/cjs/strings.js.map +1 -0
- package/dist/cjs/validation.js +450 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/esm/async.js +15 -0
- package/dist/esm/async.js.map +1 -0
- package/dist/esm/chunk-4O7ZPIJN.js +383 -0
- package/dist/esm/chunk-4O7ZPIJN.js.map +1 -0
- package/dist/esm/chunk-75XNTC34.js +60 -0
- package/dist/esm/chunk-75XNTC34.js.map +1 -0
- package/dist/esm/chunk-BDOBKBKA.js +72 -0
- package/dist/esm/chunk-BDOBKBKA.js.map +1 -0
- package/dist/esm/chunk-C3D7YZVE.js +299 -0
- package/dist/esm/chunk-C3D7YZVE.js.map +1 -0
- package/dist/esm/chunk-CZL6C2EI.js +452 -0
- package/dist/esm/chunk-CZL6C2EI.js.map +1 -0
- package/dist/esm/chunk-EBLSTOEC.js +263 -0
- package/dist/esm/chunk-EBLSTOEC.js.map +1 -0
- package/dist/esm/chunk-NSBPE2FW.js +17 -0
- package/dist/esm/chunk-NSBPE2FW.js.map +1 -0
- package/dist/esm/chunk-SLQVNPTH.js +27 -0
- package/dist/esm/chunk-SLQVNPTH.js.map +1 -0
- package/dist/esm/chunk-WG7ILCUB.js +195 -0
- package/dist/esm/chunk-WG7ILCUB.js.map +1 -0
- package/dist/esm/chunk-WJA4JDMZ.js +278 -0
- package/dist/esm/chunk-WJA4JDMZ.js.map +1 -0
- package/dist/esm/chunk-ZFVYLUTT.js +65 -0
- package/dist/esm/chunk-ZFVYLUTT.js.map +1 -0
- package/dist/esm/dates.js +78 -0
- package/dist/esm/dates.js.map +1 -0
- package/dist/esm/environment-detection.js +21 -0
- package/dist/esm/environment-detection.js.map +1 -0
- package/dist/esm/environment.js +34 -0
- package/dist/esm/environment.js.map +1 -0
- package/dist/esm/errors.js +18 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +380 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/math.js +51 -0
- package/dist/esm/math.js.map +1 -0
- package/dist/esm/number.js +10 -0
- package/dist/esm/number.js.map +1 -0
- package/dist/esm/objects.js +31 -0
- package/dist/esm/objects.js.map +1 -0
- package/dist/esm/strings.js +80 -0
- package/dist/esm/strings.js.map +1 -0
- package/dist/esm/validation.js +54 -0
- package/dist/esm/validation.js.map +1 -0
- package/dist/node/async.js +93 -0
- package/dist/node/async.js.map +1 -0
- package/dist/node/csv.js +102 -0
- package/dist/node/csv.js.map +1 -0
- package/dist/node/data.js +880 -0
- package/dist/node/data.js.map +1 -0
- package/dist/node/dates.js +324 -0
- package/dist/node/dates.js.map +1 -0
- package/dist/node/environment.js +278 -0
- package/dist/node/environment.js.map +1 -0
- package/dist/node/errors.js +89 -0
- package/dist/node/errors.js.map +1 -0
- package/dist/node/index.js +3151 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/json.js +107 -0
- package/dist/node/json.js.map +1 -0
- package/dist/node/math.js +413 -0
- package/dist/node/math.js.map +1 -0
- package/dist/node/number.js +42 -0
- package/dist/node/number.js.map +1 -0
- package/dist/node/objects.js +264 -0
- package/dist/node/objects.js.map +1 -0
- package/dist/node/strings.js +293 -0
- package/dist/node/strings.js.map +1 -0
- package/dist/node/tree.js +89 -0
- package/dist/node/tree.js.map +1 -0
- package/dist/node/validation-core.js +477 -0
- package/dist/node/validation-core.js.map +1 -0
- package/dist/node/validation-crypto.js +179 -0
- package/dist/node/validation-crypto.js.map +1 -0
- package/dist/node/validation.js +677 -0
- package/dist/node/validation.js.map +1 -0
- package/dist/node/validators.js +123 -0
- package/dist/node/validators.js.map +1 -0
- package/dist/node-esm/async.js +15 -0
- package/dist/node-esm/async.js.map +1 -0
- package/dist/node-esm/chunk-3YOF7NPT.js +299 -0
- package/dist/node-esm/chunk-3YOF7NPT.js.map +1 -0
- package/dist/node-esm/chunk-64TBXJQS.js +263 -0
- package/dist/node-esm/chunk-64TBXJQS.js.map +1 -0
- package/dist/node-esm/chunk-75XNTC34.js +60 -0
- package/dist/node-esm/chunk-75XNTC34.js.map +1 -0
- package/dist/node-esm/chunk-C4PKXIPB.js +278 -0
- package/dist/node-esm/chunk-C4PKXIPB.js.map +1 -0
- package/dist/node-esm/chunk-CMDFZME3.js +452 -0
- package/dist/node-esm/chunk-CMDFZME3.js.map +1 -0
- package/dist/node-esm/chunk-DZZPUYMP.js +74 -0
- package/dist/node-esm/chunk-DZZPUYMP.js.map +1 -0
- package/dist/node-esm/chunk-HTSEHRHI.js +195 -0
- package/dist/node-esm/chunk-HTSEHRHI.js.map +1 -0
- package/dist/node-esm/chunk-JCAUVOPH.js +27 -0
- package/dist/node-esm/chunk-JCAUVOPH.js.map +1 -0
- package/dist/node-esm/chunk-KBHE3K2F.js +505 -0
- package/dist/node-esm/chunk-KBHE3K2F.js.map +1 -0
- package/dist/node-esm/chunk-LYTET5NX.js +65 -0
- package/dist/node-esm/chunk-LYTET5NX.js.map +1 -0
- package/dist/node-esm/chunk-PZ5AY32C.js +10 -0
- package/dist/node-esm/chunk-PZ5AY32C.js.map +1 -0
- package/dist/node-esm/chunk-UKGXL2QO.js +383 -0
- package/dist/node-esm/chunk-UKGXL2QO.js.map +1 -0
- package/dist/node-esm/chunk-XAEYT23H.js +164 -0
- package/dist/node-esm/chunk-XAEYT23H.js.map +1 -0
- package/dist/node-esm/csv.js +63 -0
- package/dist/node-esm/csv.js.map +1 -0
- package/dist/node-esm/data.js +32 -0
- package/dist/node-esm/data.js.map +1 -0
- package/dist/node-esm/dates.js +78 -0
- package/dist/node-esm/dates.js.map +1 -0
- package/dist/node-esm/environment.js +34 -0
- package/dist/node-esm/environment.js.map +1 -0
- package/dist/node-esm/errors.js +18 -0
- package/dist/node-esm/errors.js.map +1 -0
- package/dist/node-esm/index.js +426 -0
- package/dist/node-esm/index.js.map +1 -0
- package/dist/node-esm/json.js +68 -0
- package/dist/node-esm/json.js.map +1 -0
- package/dist/node-esm/math.js +51 -0
- package/dist/node-esm/math.js.map +1 -0
- package/dist/node-esm/number.js +10 -0
- package/dist/node-esm/number.js.map +1 -0
- package/dist/node-esm/objects.js +31 -0
- package/dist/node-esm/objects.js.map +1 -0
- package/dist/node-esm/strings.js +80 -0
- package/dist/node-esm/strings.js.map +1 -0
- package/dist/node-esm/tree.js +8 -0
- package/dist/node-esm/tree.js.map +1 -0
- package/dist/node-esm/validation-core.js +54 -0
- package/dist/node-esm/validation-core.js.map +1 -0
- package/dist/node-esm/validation-crypto.js +26 -0
- package/dist/node-esm/validation-crypto.js.map +1 -0
- package/dist/node-esm/validation.js +606 -0
- package/dist/node-esm/validation.js.map +1 -0
- package/dist/node-esm/validators.js +98 -0
- package/dist/node-esm/validators.js.map +1 -0
- package/dist/types/async-C8gvbSG-.d.ts +453 -0
- package/dist/types/async.d.ts +1 -0
- package/dist/types/csv.d.ts +226 -0
- package/dist/types/data.d.ts +1561 -0
- package/dist/types/dates-hTiE0Z11.d.ts +298 -0
- package/dist/types/dates.d.ts +1 -0
- package/dist/types/environment-B8eLS7KT.d.ts +420 -0
- package/dist/types/environment-detection.d.ts +102 -0
- package/dist/types/environment.d.ts +1 -0
- package/dist/types/errors.d.ts +147 -0
- package/dist/types/index.d.ts +211 -0
- package/dist/types/json.d.ts +284 -0
- package/dist/types/math-BQ9Lwdp7.d.ts +2060 -0
- package/dist/types/math.d.ts +1 -0
- package/dist/types/number-CYnQfLWj.d.ts +44 -0
- package/dist/types/number.d.ts +1 -0
- package/dist/types/objects-BohS8GCS.d.ts +1185 -0
- package/dist/types/objects.d.ts +1 -0
- package/dist/types/strings-CiqRPYLL.d.ts +1349 -0
- package/dist/types/strings.d.ts +1 -0
- package/dist/types/tree.d.ts +284 -0
- package/dist/types/validation-core-DfHF8rCG.d.ts +238 -0
- package/dist/types/validation-crypto-browser.d.ts +56 -0
- package/dist/types/validation-crypto-node.d.ts +31 -0
- package/dist/types/validation.d.ts +1 -0
- package/dist/types/validators.d.ts +216 -0
- package/package.json +253 -0
package/USAGE-GUIDE.md
ADDED
|
@@ -0,0 +1,800 @@
|
|
|
1
|
+
# @g10/ts-helpers v4.1.x - Guía Técnica Completa
|
|
2
|
+
|
|
3
|
+
🚀 **v4.1.0** - Nuevas funciones para manejo de configuración, parsing de env
|
|
4
|
+
vars y manipulación de objetos anidados.
|
|
5
|
+
|
|
6
|
+
## 📦 Instalación y Configuración
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Instalación
|
|
10
|
+
pnpm add @g10/ts-helpers # Recomendado
|
|
11
|
+
npm install @g10/ts-helpers
|
|
12
|
+
|
|
13
|
+
# Requisitos
|
|
14
|
+
Node.js >=18.0.0
|
|
15
|
+
TypeScript >=5.0.0
|
|
16
|
+
pnpm >=8.0.0 (recomendado)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 🎯 Patrones de Uso v4.0.0
|
|
20
|
+
|
|
21
|
+
### 1. API Plana (Recomendado - 150+ funciones)
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import g from '@g10/ts-helpers'
|
|
25
|
+
|
|
26
|
+
// 🔐 Validación Española (30+ funciones)
|
|
27
|
+
g.validateNIF('12345678Z') // Validador NIF
|
|
28
|
+
g.validateNIE('X0000000T') // Validador NIE
|
|
29
|
+
g.validateCIF('A12345674') // Validador CIF
|
|
30
|
+
g.isValidSpanishIBAN('ES...') // IBAN español
|
|
31
|
+
g.isValidSpanishPhone('+34612345678') // Teléfono móvil
|
|
32
|
+
g.isValidSpanishPostalCode('28001') // Código postal
|
|
33
|
+
|
|
34
|
+
// 🔧 Generadores Españoles (15+ funciones)
|
|
35
|
+
g.generateSpanishNIF() // '12345678Z'
|
|
36
|
+
g.generateSpanishNIE() // 'X1234567L'
|
|
37
|
+
g.generateSpanishCIF() // 'A12345674'
|
|
38
|
+
g.generateSpanishIBAN() // 'ES9121000418450200051332'
|
|
39
|
+
g.generateSpanishPostalCode() // '28001'
|
|
40
|
+
g.generatePassword({ length: 12 }) // Contraseña segura
|
|
41
|
+
|
|
42
|
+
// 📝 String Manipulation (25+ funciones)
|
|
43
|
+
g.toCamelCase('hello-world') // 'helloWorld'
|
|
44
|
+
g.toKebabCase('HelloWorld') // 'hello-world'
|
|
45
|
+
g.toSnakeCase('HelloWorld') // 'hello_world'
|
|
46
|
+
g.toPascalCase('hello-world') // 'HelloWorld'
|
|
47
|
+
g.capitalizeFirst('hello') // 'Hello'
|
|
48
|
+
g.sanitizeString('<script>alert</script>') // ''
|
|
49
|
+
g.removeAccents('café') // 'cafe'
|
|
50
|
+
g.truncateString('long text', 10) // 'long te...'
|
|
51
|
+
|
|
52
|
+
// 🗂️ Objects & Arrays (20+ funciones)
|
|
53
|
+
g.deepEqual(obj1, obj2) // Comparación profunda
|
|
54
|
+
g.setDeepValue(config, 'database.host', 'localhost') // 🆕 v4.1.0
|
|
55
|
+
g.getDeepValue(config, 'database.port', 5432) // 🆕 v4.1.0
|
|
56
|
+
g.updateArrayElementsBy(array, criteria, updates)
|
|
57
|
+
g.deleteArrayElementsBy(array, criteria)
|
|
58
|
+
g.getShallowProperties(obj) // Solo propiedades primitivas
|
|
59
|
+
g.calculateDifferences(oldObj, newObj)
|
|
60
|
+
g.generateCrcHash(data) // Hash CRC32
|
|
61
|
+
|
|
62
|
+
// 📅 Fechas con dayjs (25+ funciones)
|
|
63
|
+
g.formatNow('DD/MM/YYYY') // '15/01/2025'
|
|
64
|
+
g.format(date, 'DD/MM/YYYY HH:mm') // Formato personalizado
|
|
65
|
+
g.addDays(date, 7) // Añadir días
|
|
66
|
+
g.diffDays(date1, date2) // Diferencia en días
|
|
67
|
+
g.diffBusinessDays(date1, date2) // Días laborables
|
|
68
|
+
g.isWeekday(date) // true si es día laborable
|
|
69
|
+
g.fromNow(date) // 'hace 2 horas'
|
|
70
|
+
|
|
71
|
+
// 🔢 Math & Statistics (30+ funciones)
|
|
72
|
+
g.calculateMedian([1, 2, 3, 4, 5]) // 3
|
|
73
|
+
g.calculateMode([1, 1, 2, 3]) // [1]
|
|
74
|
+
g.calculateStandardDeviation(data) // Desviación estándar
|
|
75
|
+
g.calculatePercentile(data, 95) // Percentil 95
|
|
76
|
+
g.calculateNPV([-1000, 300, 400], 0.1) // NPV financiero
|
|
77
|
+
g.calculateIRR(cashFlows) // Tasa interna retorno
|
|
78
|
+
g.simpleKMeans(points, 3) // Clustering K-means
|
|
79
|
+
|
|
80
|
+
// ⏱️ Async Operations (5+ funciones)
|
|
81
|
+
await g.sleep(1000) // Pausa 1 segundo
|
|
82
|
+
await g.wait(1000) // Alias de sleep
|
|
83
|
+
await g.runBatch(promises, 5) // Ejecuta en lotes de 5
|
|
84
|
+
|
|
85
|
+
// 📊 Data Import/Export (17+ funciones)
|
|
86
|
+
await g.exportData(data, 'file.csv') // Auto-detecta formato
|
|
87
|
+
await g.exportData(data, 'file.json')
|
|
88
|
+
await g.importData('file.xlsx') // Importa automáticamente
|
|
89
|
+
g.detectFormatFromFilename('file.csv') // 'csv'
|
|
90
|
+
|
|
91
|
+
// 📁 Detección Universal de Formatos (80+ tipos)
|
|
92
|
+
g.detectFileExtension('report.xlsx') // 'xlsx'
|
|
93
|
+
g.detectFileExtension('presentation.pptx') // 'pptx'
|
|
94
|
+
g.detectUniversalFormat('document.pdf')
|
|
95
|
+
// { extension: 'pdf', category: 'document', mimeType: 'application/pdf', isText: false, isBinary: true }
|
|
96
|
+
|
|
97
|
+
// 🌍 Environment Detection (15+ funciones)
|
|
98
|
+
g.isNode // true en Node.js
|
|
99
|
+
g.isBrowser // true en browser
|
|
100
|
+
g.isDevelopment() // true en desarrollo
|
|
101
|
+
g.isDevelopment(req) // Con soporte Express
|
|
102
|
+
g.isProduction() // true en producción
|
|
103
|
+
g.parseEnvValue('true') // true (boolean) 🆕 v4.1.0
|
|
104
|
+
g.parseEnvValue('[1,2,3]') // [1,2,3] (array) 🆕 v4.1.0
|
|
105
|
+
g.parseEnvValue('{"key":"val"}') // {key: 'val'} 🆕 v4.1.0
|
|
106
|
+
g.detectProtocol(req) // 'https' con headers proxy
|
|
107
|
+
g.detectHostname(req) // Hostname con X-Forwarded-Host
|
|
108
|
+
g.isLocalhost('localhost') // true
|
|
109
|
+
g.isPrivateIP('192.168.1.1') // true
|
|
110
|
+
|
|
111
|
+
// ⚙️ Path & Config Utilities (5+ funciones) 🆕 v4.1.0
|
|
112
|
+
g.matchPathPattern('features.auth', 'features.*') // true
|
|
113
|
+
g.matchPathPattern('features.auth.enabled', 'features.*.enabled') // true
|
|
114
|
+
g.isValidDotNotationPath('database.host') // true
|
|
115
|
+
g.isValidDotNotationPath('.invalid') // false
|
|
116
|
+
g.envKeyToPath('NX_FEATURES_AUTH') // 'features.auth'
|
|
117
|
+
g.pathToEnvKey('features.auth', 'APP') // 'APP_FEATURES_AUTH'
|
|
118
|
+
g.getEnvironmentInfo(req) // Info completa con criterios
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 2. Importaciones Específicas (Tree-shaking)
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Módulos específicos para bundles mínimos
|
|
125
|
+
import {
|
|
126
|
+
validateNIF,
|
|
127
|
+
generateSpanishNIF,
|
|
128
|
+
isValidCIF,
|
|
129
|
+
} from '@g10/ts-helpers/validation'
|
|
130
|
+
import {
|
|
131
|
+
toCamelCase,
|
|
132
|
+
sanitizeString,
|
|
133
|
+
removeAccents,
|
|
134
|
+
} from '@g10/ts-helpers/strings'
|
|
135
|
+
import { deepEqual, updateArrayElementsBy } from '@g10/ts-helpers/objects'
|
|
136
|
+
import { formatNow, addDays, diffDays } from '@g10/ts-helpers/dates'
|
|
137
|
+
import { calculateNPV, calculateMedian } from '@g10/ts-helpers/math'
|
|
138
|
+
import { sleep, runBatch } from '@g10/ts-helpers/async'
|
|
139
|
+
import { exportData, importData } from '@g10/ts-helpers/data'
|
|
140
|
+
import {
|
|
141
|
+
isDevelopment,
|
|
142
|
+
detectProtocol,
|
|
143
|
+
getEnvironmentInfo,
|
|
144
|
+
parseEnvValue, // 🆕 v4.1.0
|
|
145
|
+
} from '@g10/ts-helpers/environment'
|
|
146
|
+
import {
|
|
147
|
+
setDeepValue, // 🆕 v4.1.0
|
|
148
|
+
getDeepValue, // 🆕 v4.1.0
|
|
149
|
+
deepEqual,
|
|
150
|
+
updateArrayElementsBy,
|
|
151
|
+
} from '@g10/ts-helpers/objects'
|
|
152
|
+
import {
|
|
153
|
+
matchPathPattern, // 🆕 v4.1.0
|
|
154
|
+
envKeyToPath, // 🆕 v4.1.0
|
|
155
|
+
pathToEnvKey, // 🆕 v4.1.0
|
|
156
|
+
toCamelCase,
|
|
157
|
+
sanitizeString,
|
|
158
|
+
} from '@g10/ts-helpers/strings'
|
|
159
|
+
import {
|
|
160
|
+
isValidDotNotationPath, // 🆕 v4.1.0
|
|
161
|
+
validateNIF,
|
|
162
|
+
} from '@g10/ts-helpers/validation'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## 🆕 Novedades v4.1.0: Casos de Uso Prácticos
|
|
166
|
+
|
|
167
|
+
### Caso 1: Configuración desde Variables de Entorno
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import g from '@g10/ts-helpers'
|
|
171
|
+
|
|
172
|
+
// Parsing automático de env vars a tipos nativos
|
|
173
|
+
const config = {
|
|
174
|
+
debug: g.parseEnvValue(process.env.DEBUG), // 'true' → true
|
|
175
|
+
port: g.parseEnvValue(process.env.PORT), // '3000' → 3000
|
|
176
|
+
features: g.parseEnvValue(process.env.FEATURES), // 'auth,api' → ['auth','api']
|
|
177
|
+
database: g.parseEnvValue(process.env.DB_CONFIG), // '{"host":"localhost"}' → object
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Construir config anidada desde env vars planas
|
|
181
|
+
const appConfig = {}
|
|
182
|
+
Object.entries(process.env).forEach(([key, value]) => {
|
|
183
|
+
if (key.startsWith('APP_')) {
|
|
184
|
+
const path = g.envKeyToPath(key, 'APP') // 'APP_DATABASE_HOST' → 'database.host'
|
|
185
|
+
g.setDeepValue(appConfig, path, g.parseEnvValue(value))
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
// Resultado: { database: { host: 'localhost', port: 5432 }, cache: { ttl: 3600 } }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Caso 2: Sistema de Permisos con Wildcards
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import g from '@g10/ts-helpers'
|
|
195
|
+
|
|
196
|
+
const userPermissions = [
|
|
197
|
+
'admin.users.read',
|
|
198
|
+
'admin.users.write',
|
|
199
|
+
'reports.view',
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
// Verificar permisos con patrones
|
|
203
|
+
function hasPermission(requiredPermission: string): boolean {
|
|
204
|
+
return userPermissions.some(perm =>
|
|
205
|
+
g.matchPathPattern(perm, requiredPermission)
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
hasPermission('admin.users.*') // true (tiene read y write)
|
|
210
|
+
hasPermission('admin.*.write') // true (tiene admin.users.write)
|
|
211
|
+
hasPermission('admin.products.*') // false (no tiene permisos de productos)
|
|
212
|
+
|
|
213
|
+
// Feature flags con wildcards
|
|
214
|
+
const enabledFeatures = [
|
|
215
|
+
'features.auth.oauth',
|
|
216
|
+
'features.auth.saml',
|
|
217
|
+
'features.payments.stripe',
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
const hasAuthFeature = enabledFeatures.some(f =>
|
|
221
|
+
g.matchPathPattern(f, 'features.auth.*')
|
|
222
|
+
)
|
|
223
|
+
// true
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Caso 3: Configuración Dinámica con Validación
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import g from '@g10/ts-helpers'
|
|
230
|
+
|
|
231
|
+
class ConfigManager {
|
|
232
|
+
private config: Record<string, any> = {}
|
|
233
|
+
|
|
234
|
+
set(path: string, value: any): void {
|
|
235
|
+
// Validar path antes de establecer
|
|
236
|
+
if (!g.isValidDotNotationPath(path)) {
|
|
237
|
+
throw new Error(`Invalid config path: ${path}`)
|
|
238
|
+
}
|
|
239
|
+
g.setDeepValue(this.config, path, value)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
get<T = any>(path: string, defaultValue?: T): T | undefined {
|
|
243
|
+
if (!g.isValidDotNotationPath(path)) {
|
|
244
|
+
throw new Error(`Invalid config path: ${path}`)
|
|
245
|
+
}
|
|
246
|
+
return g.getDeepValue(this.config, path, defaultValue)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const config = new ConfigManager()
|
|
251
|
+
config.set('database.host', 'localhost')
|
|
252
|
+
config.set('database.port', 5432)
|
|
253
|
+
config.get('database.host') // 'localhost'
|
|
254
|
+
config.get('database.timeout', 5000) // 5000 (default)
|
|
255
|
+
config.set('.invalid', 'value') // throws Error
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Caso 4: Generación de .env desde Configuración
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import g from '@g10/ts-helpers'
|
|
262
|
+
|
|
263
|
+
const config = {
|
|
264
|
+
database: { host: 'localhost', port: 5432 },
|
|
265
|
+
cache: { ttl: 3600, enabled: true },
|
|
266
|
+
features: { auth: true, payments: false },
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function generateEnvFile(obj: any, prefix = 'APP', currentPath = ''): string[] {
|
|
270
|
+
const lines: string[] = []
|
|
271
|
+
|
|
272
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
273
|
+
const path = currentPath ? `${currentPath}.${key}` : key
|
|
274
|
+
|
|
275
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
276
|
+
// Recursivo para objetos anidados
|
|
277
|
+
lines.push(...generateEnvFile(value, prefix, path))
|
|
278
|
+
} else {
|
|
279
|
+
const envKey = g.pathToEnvKey(path, prefix)
|
|
280
|
+
const envValue = Array.isArray(value)
|
|
281
|
+
? JSON.stringify(value)
|
|
282
|
+
: String(value)
|
|
283
|
+
lines.push(`${envKey}=${envValue}`)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return lines
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const envFile = generateEnvFile(config).join('\n')
|
|
291
|
+
console.log(envFile)
|
|
292
|
+
// APP_DATABASE_HOST=localhost
|
|
293
|
+
// APP_DATABASE_PORT=5432
|
|
294
|
+
// APP_CACHE_TTL=3600
|
|
295
|
+
// APP_CACHE_ENABLED=true
|
|
296
|
+
// APP_FEATURES_AUTH=true
|
|
297
|
+
// APP_FEATURES_PAYMENTS=false
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 📋 Catálogo Completo de Funciones
|
|
301
|
+
|
|
302
|
+
### 🔐 Validation Module (validation.ts)
|
|
303
|
+
|
|
304
|
+
**Validadores Españoles:**
|
|
305
|
+
|
|
306
|
+
- `validateNIF(nif)` - Valida NIF español
|
|
307
|
+
- `validateNIE(nie)` - Valida NIE español
|
|
308
|
+
- `validateCIF(cif)` - Valida CIF español
|
|
309
|
+
- `isValidSpanishIBAN(iban)` - IBAN español
|
|
310
|
+
- `isValidSpanishPhone(phone)` - Teléfono español
|
|
311
|
+
- `isValidSpanishPostalCode(code)` - Código postal
|
|
312
|
+
|
|
313
|
+
**Validadores Generales:**
|
|
314
|
+
|
|
315
|
+
- `isValidEmail(email)` - Email válido
|
|
316
|
+
- `isValidURL(url)` - URL válida (incluye localhost)
|
|
317
|
+
- `isValidJSON(str)` - JSON válido
|
|
318
|
+
- `isValidBase64(str)` - Base64 válido
|
|
319
|
+
- `isValidJWTFormat(token)` - Formato JWT
|
|
320
|
+
- `validatePassword(password, options)` - Contraseña segura
|
|
321
|
+
|
|
322
|
+
**Generadores:**
|
|
323
|
+
|
|
324
|
+
- `generateSpanishNIF()` - NIF aleatorio válido
|
|
325
|
+
- `generateSpanishNIE()` - NIE aleatorio válido
|
|
326
|
+
- `generateSpanishCIF()` - CIF aleatorio válido
|
|
327
|
+
- `generateSpanishIBAN()` - IBAN español válido
|
|
328
|
+
- `generateSpanishPostalCode()` - Código postal español
|
|
329
|
+
- `generatePassword(options)` - Contraseña segura
|
|
330
|
+
- `generateSecureToken(length)` - Token criptográfico
|
|
331
|
+
- `generateNonce(length)` - Nonce único
|
|
332
|
+
|
|
333
|
+
### 📝 Strings Module (strings.ts)
|
|
334
|
+
|
|
335
|
+
**Transformaciones de Caso:**
|
|
336
|
+
|
|
337
|
+
- `toCamelCase(str)` - camelCase
|
|
338
|
+
- `toKebabCase(str)` - kebab-case
|
|
339
|
+
- `toSnakeCase(str)` - snake_case
|
|
340
|
+
- `toPascalCase(str)` - PascalCase
|
|
341
|
+
- `toLowerCase(str)` - minúsculas
|
|
342
|
+
- `toUpperCase(str)` - MAYÚSCULAS
|
|
343
|
+
|
|
344
|
+
**Capitalización:**
|
|
345
|
+
|
|
346
|
+
- `capitalizeFirst(str)` - Primera letra mayúscula
|
|
347
|
+
- `capitalizeEachWord(str)` - Cada palabra capitalizada
|
|
348
|
+
|
|
349
|
+
**Seguridad:**
|
|
350
|
+
|
|
351
|
+
- `sanitizeString(str)` - Elimina caracteres peligrosos
|
|
352
|
+
- `sanitizeHtml(html)` - Sanitiza HTML
|
|
353
|
+
- `escapeHtmlChars(str)` - Escapa caracteres HTML
|
|
354
|
+
- `unescapeHtmlChars(str)` - Desescapa HTML
|
|
355
|
+
- `removeDangerousChars(str)` - Elimina caracteres peligrosos
|
|
356
|
+
- `escapeShellCommand(cmd)` - Escapa comandos shell
|
|
357
|
+
|
|
358
|
+
**Manipulación:**
|
|
359
|
+
|
|
360
|
+
- `removeAccents(str)` - Elimina acentos y tildes
|
|
361
|
+
- `truncateString(str, length)` - Trunca con '...'
|
|
362
|
+
- `padStart(str, length, char)` - Rellena al inicio
|
|
363
|
+
- `padEnd(str, length, char)` - Rellena al final
|
|
364
|
+
- `repeatString(str, times)` - Repite string
|
|
365
|
+
- `reverseString(str)` - Invierte string
|
|
366
|
+
- `trim/trimStart/trimEnd(str)` - Elimina espacios
|
|
367
|
+
|
|
368
|
+
### 🗂️ Objects Module (objects.ts)
|
|
369
|
+
|
|
370
|
+
**Comparación:**
|
|
371
|
+
|
|
372
|
+
- `deepEqual(obj1, obj2)` - Comparación profunda
|
|
373
|
+
- `comparator(obj1, obj2, options)` - Comparador personalizable
|
|
374
|
+
- `hasSameType(obj1, obj2)` - Mismo tipo incluyendo typed arrays
|
|
375
|
+
|
|
376
|
+
**Manipulación de Arrays:**
|
|
377
|
+
|
|
378
|
+
- `updateArrayElementsBy(array, criteria, updates)` - Actualiza elementos
|
|
379
|
+
- `updateArrayElementById(array, id, updates)` - Actualiza por ID
|
|
380
|
+
- `deleteArrayElementsBy(array, criteria)` - Elimina elementos
|
|
381
|
+
|
|
382
|
+
**Análisis de Objetos:**
|
|
383
|
+
|
|
384
|
+
- `getShallowProperties(obj)` - Solo propiedades primitivas
|
|
385
|
+
- `calculateDifferences(oldObj, newObj, tolerance)` - Diferencias con tolerancia
|
|
386
|
+
- `formatToReadableString(obj)` - String legible del objeto
|
|
387
|
+
|
|
388
|
+
**Hash y Utilidades:**
|
|
389
|
+
|
|
390
|
+
- `generateCrcHash(data)` - Hash CRC32 de datos
|
|
391
|
+
- `hashString(str)` - Hash simple de string
|
|
392
|
+
|
|
393
|
+
### 📅 Dates Module (dates.ts)
|
|
394
|
+
|
|
395
|
+
**Formato:**
|
|
396
|
+
|
|
397
|
+
- `formatNow(format)` - Fecha actual formateada
|
|
398
|
+
- `format(date, format)` - Formato personalizado
|
|
399
|
+
- `toISO(date)` - Formato ISO
|
|
400
|
+
- `fromNow(date)` - Tiempo relativo ('hace 2 horas')
|
|
401
|
+
|
|
402
|
+
**Manipulación:**
|
|
403
|
+
|
|
404
|
+
- `addDays/addMonths/addYears(date, amount)` - Añadir tiempo
|
|
405
|
+
- `addNowDays/addNowMonths/addNowYears(amount)` - Añadir a fecha actual
|
|
406
|
+
|
|
407
|
+
**Cálculos:**
|
|
408
|
+
|
|
409
|
+
- `diffDays/diffMonths/diffYears(date1, date2)` - Diferencias
|
|
410
|
+
- `diffBusinessDays(date1, date2)` - Días laborables
|
|
411
|
+
- `diffMilliseconds(date1, date2)` - Diferencia en ms
|
|
412
|
+
|
|
413
|
+
**Utilidades:**
|
|
414
|
+
|
|
415
|
+
- `isWeekday(date)` - Es día laborable
|
|
416
|
+
- `dayOfWeek(date)` - Día de la semana
|
|
417
|
+
- `weekOfYear(date)` - Semana del año
|
|
418
|
+
- `getFirstDayOfYear/getLastDayOfYear(year)` - Primer/último día
|
|
419
|
+
|
|
420
|
+
### 🔢 Math Module (math.ts)
|
|
421
|
+
|
|
422
|
+
**Estadísticas Básicas:**
|
|
423
|
+
|
|
424
|
+
- `calculateMedian(numbers)` - Mediana
|
|
425
|
+
- `calculateMode(numbers)` - Moda (valores más frecuentes)
|
|
426
|
+
- `calculateStandardDeviation(numbers)` - Desviación estándar
|
|
427
|
+
- `calculateVariance(numbers)` - Varianza
|
|
428
|
+
- `calculatePercentile(numbers, percentile)` - Percentil específico
|
|
429
|
+
|
|
430
|
+
**Estadísticas Avanzadas:**
|
|
431
|
+
|
|
432
|
+
- `calculateQuartiles(numbers)` - Q1, Q2, Q3
|
|
433
|
+
- `calculateIQR(numbers)` - Rango intercuartílico
|
|
434
|
+
- `detectOutliers(numbers, multiplier)` - Detección de outliers
|
|
435
|
+
- `calculateCorrelation(x, y)` - Correlación de Pearson
|
|
436
|
+
|
|
437
|
+
**Finanzas:**
|
|
438
|
+
|
|
439
|
+
- `calculateNPV(cashFlows, discountRate)` - Valor presente neto
|
|
440
|
+
- `calculateIRR(cashFlows)` - Tasa interna de retorno
|
|
441
|
+
- `calculateFutureValue(pv, rate, periods)` - Valor futuro
|
|
442
|
+
- `calculatePresentValue(fv, rate, periods)` - Valor presente
|
|
443
|
+
- `calculateAnnuityPayment(pv, rate, periods)` - Pago de anualidad
|
|
444
|
+
|
|
445
|
+
**Machine Learning:**
|
|
446
|
+
|
|
447
|
+
- `simpleKMeans(points, k, maxIterations)` - Clustering K-means
|
|
448
|
+
- `calculateEuclideanDistance(point1, point2)` - Distancia euclidiana
|
|
449
|
+
- `calculateManhattanDistance(point1, point2)` - Distancia Manhattan
|
|
450
|
+
|
|
451
|
+
### ⏱️ Async Module (async.ts)
|
|
452
|
+
|
|
453
|
+
- `sleep(ms)` - Pausa asíncrona
|
|
454
|
+
- `wait(ms)` - Alias de sleep
|
|
455
|
+
- `runBatch(promises, batchSize)` - Ejecuta promesas en lotes
|
|
456
|
+
- `handleOperation(operation, options)` - Manejo con retry
|
|
457
|
+
|
|
458
|
+
### 📊 Data Module (data.ts)
|
|
459
|
+
|
|
460
|
+
**Detección de Formato:**
|
|
461
|
+
|
|
462
|
+
- `detectFormatFromFilename(filename)` - Auto-detecta por extensión
|
|
463
|
+
|
|
464
|
+
**Export/Import:**
|
|
465
|
+
|
|
466
|
+
- `exportData(data, filename)` - Exporta con auto-detección
|
|
467
|
+
- `importData(filename)` - Importa con auto-detección
|
|
468
|
+
- `exportTree(data, filename)` - Exporta estructura de árbol
|
|
469
|
+
- `importTree(filename)` - Importa estructura de árbol
|
|
470
|
+
- `exportTxt(data, filename, options)` - Exporta como texto
|
|
471
|
+
- `importTxt(filename, options)` - Importa texto con validación
|
|
472
|
+
|
|
473
|
+
**Validación:**
|
|
474
|
+
|
|
475
|
+
- `validateExportData(data)` - Valida datos para export
|
|
476
|
+
- `validateCSVData(data)` - Alias para validación CSV
|
|
477
|
+
|
|
478
|
+
### 🌍 Environment Module (environment.ts)
|
|
479
|
+
|
|
480
|
+
**Detección de Plataforma:**
|
|
481
|
+
|
|
482
|
+
- `isNodeEnvironment()` - Detecta runtime Node.js
|
|
483
|
+
- `isBrowserEnvironment()` - Detecta runtime browser
|
|
484
|
+
- `isNode` - Alias para isNodeEnvironment
|
|
485
|
+
- `isBrowser` - Alias para isBrowserEnvironment
|
|
486
|
+
|
|
487
|
+
**Detección de Entorno:**
|
|
488
|
+
|
|
489
|
+
- `isDevelopment(req?)` - Detecta desarrollo (NODE_ENV, puertos, localhost)
|
|
490
|
+
- `isProduction()` - Detecta producción
|
|
491
|
+
- `getEnvironmentInfo(req?)` - Info completa con criterios debugging
|
|
492
|
+
|
|
493
|
+
**Detección de Red:**
|
|
494
|
+
|
|
495
|
+
- `detectProtocol(req?)` - Protocolo HTTP/HTTPS con soporte proxy
|
|
496
|
+
- `detectHostname(req?)` - Hostname con headers X-Forwarded-Host
|
|
497
|
+
- `isLocalhost(hostname)` - Es localhost o .local/.localhost
|
|
498
|
+
- `isPrivateIP(hostname)` - Es IP privada (RFC 1918) o IPv6 local
|
|
499
|
+
|
|
500
|
+
## 🔄 Migración Detallada desde v3.x
|
|
501
|
+
|
|
502
|
+
### Cambios en la API
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
// ❌ v3.x - Estructura anidada redundante
|
|
506
|
+
import g from '@g10/ts-helpers'
|
|
507
|
+
|
|
508
|
+
// Validación
|
|
509
|
+
g.validation.validators.validateNIF('12345678Z')
|
|
510
|
+
g.validation.generators.generateSpanishNIF()
|
|
511
|
+
|
|
512
|
+
// Strings
|
|
513
|
+
g.primitives.string.toCamelCase('hello-world')
|
|
514
|
+
g.primitives.string.capitalizeFirst('hello')
|
|
515
|
+
|
|
516
|
+
// Objetos
|
|
517
|
+
g.primitives.object.deepEqual(obj1, obj2)
|
|
518
|
+
g.primitives.array.updateArrayElementsBy(array, criteria, updates)
|
|
519
|
+
|
|
520
|
+
// Async
|
|
521
|
+
g.core.async.sleep(1000)
|
|
522
|
+
g.core.async.runBatch(promises, 5)
|
|
523
|
+
|
|
524
|
+
// Data
|
|
525
|
+
g.data.exportData(data, 'file.csv')
|
|
526
|
+
g.data.importData('file.json')
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// ✅ v4.0.0 - API completamente plana
|
|
531
|
+
import g from '@g10/ts-helpers'
|
|
532
|
+
|
|
533
|
+
// Validación - acceso directo
|
|
534
|
+
g.validateNIF('12345678Z')
|
|
535
|
+
g.generateSpanishNIF()
|
|
536
|
+
|
|
537
|
+
// Strings - acceso directo
|
|
538
|
+
g.toCamelCase('hello-world')
|
|
539
|
+
g.capitalizeFirst('hello')
|
|
540
|
+
|
|
541
|
+
// Objetos - acceso directo
|
|
542
|
+
g.deepEqual(obj1, obj2)
|
|
543
|
+
g.updateArrayElementsBy(array, criteria, updates)
|
|
544
|
+
|
|
545
|
+
// Async - acceso directo
|
|
546
|
+
g.sleep(1000)
|
|
547
|
+
g.runBatch(promises, 5)
|
|
548
|
+
|
|
549
|
+
// Data - acceso directo
|
|
550
|
+
g.exportData(data, 'file.csv')
|
|
551
|
+
g.importData('file.json')
|
|
552
|
+
|
|
553
|
+
// Environment - acceso directo
|
|
554
|
+
g.isDevelopment()
|
|
555
|
+
g.detectProtocol(req)
|
|
556
|
+
g.getEnvironmentInfo(req)
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Re-exportaciones Eliminadas
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
// ❌ v3.x - Re-exportaciones incluidas
|
|
563
|
+
import g from '@g10/ts-helpers'
|
|
564
|
+
g.lodash.isNull(value) // Eliminado
|
|
565
|
+
g.axios.get('/api/data') // Eliminado
|
|
566
|
+
g.dayjs().format('DD/MM/YYYY') // Eliminado
|
|
567
|
+
g.numeral(1234).format('0,0') // Eliminado
|
|
568
|
+
|
|
569
|
+
// ✅ v4.0.0 - Instalar dependencias por separado
|
|
570
|
+
npm install lodash axios dayjs numeral
|
|
571
|
+
|
|
572
|
+
import _ from 'lodash'
|
|
573
|
+
import axios from 'axios'
|
|
574
|
+
import dayjs from 'dayjs'
|
|
575
|
+
import numeral from 'numeral'
|
|
576
|
+
|
|
577
|
+
_.isNull(value)
|
|
578
|
+
axios.get('/api/data')
|
|
579
|
+
dayjs().format('DD/MM/YYYY')
|
|
580
|
+
numeral(1234).format('0,0')
|
|
581
|
+
|
|
582
|
+
// O usar implementaciones nativas de @g10/ts-helpers
|
|
583
|
+
import g from '@g10/ts-helpers'
|
|
584
|
+
g.formatNow('DD/MM/YYYY') // Reemplazo nativo para dayjs
|
|
585
|
+
g.deepEqual(obj1, obj2) // Reemplazo nativo para lodash
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
## ⚡ Optimización de Bundle
|
|
589
|
+
|
|
590
|
+
### Tree-shaking Efectivo
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
// Bundle mínimo - solo importa funciones específicas
|
|
594
|
+
import { validateNIF, isValidEmail } from '@g10/ts-helpers/validation'
|
|
595
|
+
import { toCamelCase } from '@g10/ts-helpers/strings'
|
|
596
|
+
import { sleep } from '@g10/ts-helpers/async'
|
|
597
|
+
|
|
598
|
+
// Resultado: ~5KB vs ~185KB completo
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Comparación de Tamaños
|
|
602
|
+
|
|
603
|
+
```
|
|
604
|
+
v3.x: 603KB (con re-exportaciones)
|
|
605
|
+
v4.0.0: 185KB (-69% reducción)
|
|
606
|
+
Tree-shaking específico: ~5-20KB según funciones usadas
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
## 🧪 Testing y Calidad
|
|
610
|
+
|
|
611
|
+
La librería incluye **270 tests** que cubren todas las funciones:
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
pnpm test # Ejecuta todos los tests
|
|
615
|
+
pnpm test:watch # Modo watch
|
|
616
|
+
pnpm test:coverage # Cobertura de código
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**Cobertura actual: 100% de funciones principales**
|
|
620
|
+
|
|
621
|
+
## 🔧 Configuración de Desarrollo
|
|
622
|
+
|
|
623
|
+
```bash
|
|
624
|
+
# Instalación para desarrollo
|
|
625
|
+
git clone https://gitlab.gzl10.com/g10libs/ts-helpers.git
|
|
626
|
+
cd ts-helpers
|
|
627
|
+
pnpm install
|
|
628
|
+
|
|
629
|
+
# Comandos disponibles
|
|
630
|
+
pnpm run build # Build completo (~40ms)
|
|
631
|
+
pnpm run typecheck # Verificación TypeScript
|
|
632
|
+
pnpm run lint # ESLint con auto-fix
|
|
633
|
+
pnpm run format # Prettier con auto-fix
|
|
634
|
+
pnpm run quality # Todo junto (sin tests)
|
|
635
|
+
|
|
636
|
+
# Gestión de versiones con Changeset
|
|
637
|
+
pnpm release:prepare # Crear changeset
|
|
638
|
+
pnpm release:version # Actualizar versión y CHANGELOG
|
|
639
|
+
pnpm release:publish # Publicar a npm
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
## 📁 Universal Format Detection
|
|
643
|
+
|
|
644
|
+
### Detección Simple de Extensiones
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
import g from '@g10/ts-helpers'
|
|
648
|
+
|
|
649
|
+
// Extrae solo la extensión del archivo
|
|
650
|
+
g.detectFileExtension('report.xlsx') // 'xlsx'
|
|
651
|
+
g.detectFileExtension('image.png') // 'png'
|
|
652
|
+
g.detectFileExtension('archive.tar.gz') // 'gz' (última extensión)
|
|
653
|
+
g.detectFileExtension('filename') // null (sin extensión)
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### Detección Inteligente con Categorización
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
// Análisis completo con 80+ formatos soportados
|
|
660
|
+
const analysis = g.detectUniversalFormat('presentation.pptx')
|
|
661
|
+
// {
|
|
662
|
+
// extension: 'pptx',
|
|
663
|
+
// category: 'presentation',
|
|
664
|
+
// mimeType: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
665
|
+
// isText: false,
|
|
666
|
+
// isBinary: true
|
|
667
|
+
// }
|
|
668
|
+
|
|
669
|
+
// Microsoft Office
|
|
670
|
+
g.detectUniversalFormat('report.xlsx') // { category: 'spreadsheet' }
|
|
671
|
+
g.detectUniversalFormat('document.docx') // { category: 'document' }
|
|
672
|
+
g.detectUniversalFormat('slides.pptx') // { category: 'presentation' }
|
|
673
|
+
|
|
674
|
+
// Programación
|
|
675
|
+
g.detectUniversalFormat('app.ts') // { category: 'code', isText: true }
|
|
676
|
+
g.detectUniversalFormat('script.py') // { category: 'code', isText: true }
|
|
677
|
+
g.detectUniversalFormat('Main.java') // { category: 'code', isText: true }
|
|
678
|
+
|
|
679
|
+
// Media
|
|
680
|
+
g.detectUniversalFormat('video.mp4') // { category: 'video', isBinary: true }
|
|
681
|
+
g.detectUniversalFormat('song.mp3') // { category: 'audio', isBinary: true }
|
|
682
|
+
g.detectUniversalFormat('photo.jpg') // { category: 'image', isBinary: true }
|
|
683
|
+
|
|
684
|
+
// Archivos
|
|
685
|
+
g.detectUniversalFormat('backup.zip') // { category: 'archive' }
|
|
686
|
+
g.detectUniversalFormat('package.7z') // { category: 'archive' }
|
|
687
|
+
|
|
688
|
+
// Fuentes
|
|
689
|
+
g.detectUniversalFormat('font.ttf') // { category: 'font' }
|
|
690
|
+
g.detectUniversalFormat('webfont.woff2') // { category: 'font' }
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### Formatos Soportados (80+)
|
|
694
|
+
|
|
695
|
+
#### Microsoft Office
|
|
696
|
+
|
|
697
|
+
- **Documentos**: doc, docx, odt (LibreOffice)
|
|
698
|
+
- **Hojas de cálculo**: xls, xlsx, ods
|
|
699
|
+
- **Presentaciones**: ppt, pptx, odp
|
|
700
|
+
|
|
701
|
+
#### Programación
|
|
702
|
+
|
|
703
|
+
- **JavaScript/TypeScript**: js, mjs, jsx, ts, tsx
|
|
704
|
+
- **Backend**: py, java, php, rb, go, rs, c, cpp, cs
|
|
705
|
+
- **Shell**: sh, bash, ps1
|
|
706
|
+
|
|
707
|
+
#### Web Development
|
|
708
|
+
|
|
709
|
+
- **Estilos**: css, scss, sass, less
|
|
710
|
+
- **Markup**: html, htm, xml, svg
|
|
711
|
+
|
|
712
|
+
#### Media
|
|
713
|
+
|
|
714
|
+
- **Imágenes**: jpg, jpeg, png, gif, svg, webp, avif, bmp, tiff, ico, psd
|
|
715
|
+
- **Audio**: mp3, wav, flac, ogg, aac, m4a, wma
|
|
716
|
+
- **Video**: mp4, avi, mov, wmv, flv, webm, mkv, 3gp
|
|
717
|
+
|
|
718
|
+
#### Archivos y Configuración
|
|
719
|
+
|
|
720
|
+
- **Archivos**: zip, rar, 7z, tar, gz, bz2, xz
|
|
721
|
+
- **Configuración**: ini, cfg, conf, toml, env, yaml, yml
|
|
722
|
+
- **Fuentes**: ttf, otf, woff, woff2, eot
|
|
723
|
+
|
|
724
|
+
#### Datos
|
|
725
|
+
|
|
726
|
+
- **Estructurados**: json, csv, xml, yaml, sql
|
|
727
|
+
- **Base de datos**: db, sqlite
|
|
728
|
+
- **Documentos**: pdf, epub, mobi, rtf
|
|
729
|
+
|
|
730
|
+
### Casos de Uso
|
|
731
|
+
|
|
732
|
+
```typescript
|
|
733
|
+
// Validación de uploads
|
|
734
|
+
const uploadValidator = (filename: string) => {
|
|
735
|
+
const format = g.detectUniversalFormat(filename)
|
|
736
|
+
|
|
737
|
+
if (format.category === 'image' && format.extension !== 'svg') {
|
|
738
|
+
return { allowed: true, type: 'image' }
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (format.category === 'document') {
|
|
742
|
+
return { allowed: true, type: 'document' }
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return { allowed: false, reason: 'Formato no permitido' }
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Content-Type automático
|
|
749
|
+
const getContentType = (filename: string) => {
|
|
750
|
+
const format = g.detectUniversalFormat(filename)
|
|
751
|
+
return format.mimeType || 'application/octet-stream'
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Procesamiento condicional
|
|
755
|
+
const processFile = (filename: string, content: string | Buffer) => {
|
|
756
|
+
const format = g.detectUniversalFormat(filename)
|
|
757
|
+
|
|
758
|
+
if (format.isText) {
|
|
759
|
+
return content.toString('utf-8') // Procesar como texto
|
|
760
|
+
} else {
|
|
761
|
+
return content // Mantener como binario
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
## 📈 Performance
|
|
767
|
+
|
|
768
|
+
### Build Performance
|
|
769
|
+
|
|
770
|
+
```
|
|
771
|
+
TypeScript Compiler: ~45s
|
|
772
|
+
tsup (v4.0.0): ~40ms
|
|
773
|
+
Mejora: 70-90% más rápido
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Bundle Optimization
|
|
777
|
+
|
|
778
|
+
```
|
|
779
|
+
Antes (v3.x): 603KB
|
|
780
|
+
Después (v4.0.0): 185KB
|
|
781
|
+
Reducción: 69%
|
|
782
|
+
Tree-shaking: 5-20KB según uso
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
### Runtime Performance
|
|
786
|
+
|
|
787
|
+
- **Funciones nativas**: Sin overhead de dependencias externas
|
|
788
|
+
- **Tree-shaking preservado**: Solo código usado en bundle final
|
|
789
|
+
- **TypeScript strict**: Optimización máxima del compilador
|
|
790
|
+
|
|
791
|
+
---
|
|
792
|
+
|
|
793
|
+
**🎉 @g10/ts-helpers v4.0.4 - Ready for Production**
|
|
794
|
+
|
|
795
|
+
Para más información, consulta:
|
|
796
|
+
|
|
797
|
+
- [README.md](README.md) - Overview y instalación
|
|
798
|
+
- [CHANGELOG.md](CHANGELOG.md) - Historial de cambios
|
|
799
|
+
- [GitLab Issues](https://gitlab.gzl10.com/g10libs/ts-helpers/-/issues) -
|
|
800
|
+
Reportar bugs
|