@jvsoft/utils 0.0.13-alpha.2 → 0.0.13-alpha.3
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/fesm2022/jvsoft-utils-src-functions.mjs +260 -2
- package/fesm2022/jvsoft-utils-src-functions.mjs.map +1 -1
- package/fesm2022/jvsoft-utils.mjs +260 -2
- package/fesm2022/jvsoft-utils.mjs.map +1 -1
- package/functions/forms.d.ts +14 -1
- package/functions/number.d.ts +1 -0
- package/functions/objects-arrays.d.ts +10 -0
- package/functions/string.d.ts +22 -0
- package/package.json +6 -6
- package/src/functions/forms.d.ts +14 -1
- package/src/functions/number.d.ts +1 -0
- package/src/functions/objects-arrays.d.ts +10 -0
- package/src/functions/string.d.ts +22 -0
|
@@ -7,8 +7,8 @@ import CryptoJS from 'crypto-js';
|
|
|
7
7
|
import { formatDate } from '@angular/common';
|
|
8
8
|
import { saveAs } from 'file-saver';
|
|
9
9
|
import { ReactiveFormConfig } from '@rxweb/reactive-form-validators';
|
|
10
|
-
import swal from 'sweetalert2';
|
|
11
10
|
import moment from 'moment';
|
|
11
|
+
import swal from 'sweetalert2';
|
|
12
12
|
import { jwtDecode } from 'jwt-decode';
|
|
13
13
|
import * as i0 from '@angular/core';
|
|
14
14
|
import { Pipe } from '@angular/core';
|
|
@@ -209,6 +209,59 @@ function obtenerUltimoOrden(data, campo, incrementar = true) {
|
|
|
209
209
|
}, 0);
|
|
210
210
|
return incrementar ? max + 1 : max;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Elimina una o varias columnas específicas (por índice) de una tabla representada como array de arrays.
|
|
214
|
+
*
|
|
215
|
+
* @param data - Array de filas (cada fila debe ser un array).
|
|
216
|
+
* @param columnIndex - Índice o lista de índices de las columnas a eliminar.
|
|
217
|
+
* @returns Nuevo array con las columnas eliminadas.
|
|
218
|
+
*/
|
|
219
|
+
function eliminarColumnaPorIndex(data, columnIndex) {
|
|
220
|
+
if (!Array.isArray(data))
|
|
221
|
+
return [];
|
|
222
|
+
// Normalizar a array único y ordenado (descendente para evitar reindexación al splicing)
|
|
223
|
+
const indices = Array.isArray(columnIndex)
|
|
224
|
+
? [...new Set(columnIndex)].filter((i) => (typeof i === 'number' && i >= 0)).sort((a, b) => b - a)
|
|
225
|
+
: [columnIndex];
|
|
226
|
+
return data.map((row) => {
|
|
227
|
+
if (!Array.isArray(row))
|
|
228
|
+
return row;
|
|
229
|
+
const newRow = [...row];
|
|
230
|
+
for (const index of indices) {
|
|
231
|
+
if (index >= 0 && index < newRow.length) {
|
|
232
|
+
newRow.splice(index, 1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return newRow;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function eliminarDuplicados(array, claves) {
|
|
239
|
+
const unicos = new Map();
|
|
240
|
+
for (const item of array) {
|
|
241
|
+
const claveUnica = claves && claves.length > 0
|
|
242
|
+
? claves.map(k => item[k]).join('|')
|
|
243
|
+
: JSON.stringify(item);
|
|
244
|
+
if (!unicos.has(claveUnica)) {
|
|
245
|
+
unicos.set(claveUnica, item);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return Array.from(unicos.values());
|
|
249
|
+
}
|
|
250
|
+
function eliminarElementos(origen, elementosAEliminar, claves) {
|
|
251
|
+
const clavesSet = new Set();
|
|
252
|
+
for (const item of elementosAEliminar) {
|
|
253
|
+
const key = claves && claves.length > 0
|
|
254
|
+
? claves.map(k => item[k]).join('|')
|
|
255
|
+
: JSON.stringify(item);
|
|
256
|
+
clavesSet.add(key);
|
|
257
|
+
}
|
|
258
|
+
return origen.filter(item => {
|
|
259
|
+
const key = claves && claves.length > 0
|
|
260
|
+
? claves.map(k => item[k]).join('|')
|
|
261
|
+
: JSON.stringify(item);
|
|
262
|
+
return !clavesSet.has(key);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
212
265
|
|
|
213
266
|
function mostrarValorEnBusqueda(campos, idxSel) {
|
|
214
267
|
const impDataMostrar = () => {
|
|
@@ -767,6 +820,87 @@ function markAsTouchedWithoutEmitEvent(control) {
|
|
|
767
820
|
control.updateValueAndValidity({ emitEvent: false });
|
|
768
821
|
}
|
|
769
822
|
}
|
|
823
|
+
function setControlDesdeLista(config) {
|
|
824
|
+
const lista = config.lista$?.getValue() ?? [];
|
|
825
|
+
if (!lista.length)
|
|
826
|
+
return;
|
|
827
|
+
let seleccionado;
|
|
828
|
+
if (config.idProp && config.idValor !== undefined) {
|
|
829
|
+
seleccionado = lista.find((item) => item[config.idProp] === config.idValor);
|
|
830
|
+
}
|
|
831
|
+
else if (config.usarPrimeraOpcion) {
|
|
832
|
+
seleccionado = lista[0];
|
|
833
|
+
}
|
|
834
|
+
console.log(seleccionado);
|
|
835
|
+
if (!seleccionado)
|
|
836
|
+
return;
|
|
837
|
+
let valor;
|
|
838
|
+
if (config.selector) {
|
|
839
|
+
valor = config.selector(seleccionado);
|
|
840
|
+
}
|
|
841
|
+
else if (config.idProp) {
|
|
842
|
+
valor = seleccionado[config.idProp];
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
valor = seleccionado;
|
|
846
|
+
}
|
|
847
|
+
if (config.formControl) {
|
|
848
|
+
config.formControl.setValue(valor);
|
|
849
|
+
}
|
|
850
|
+
else if (config.formGroup && config.controlName) {
|
|
851
|
+
const control = config.formGroup.get(config.controlName);
|
|
852
|
+
if (control instanceof FormControl) {
|
|
853
|
+
control.setValue(valor);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
function transformarFechasPorNombreDeCampo(formValue) {
|
|
858
|
+
const retData = {};
|
|
859
|
+
Object.entries(formValue).forEach(([key, value]) => {
|
|
860
|
+
// ✅ No procesar Blob o File
|
|
861
|
+
if (value instanceof Blob || value instanceof File) {
|
|
862
|
+
retData[key] = value;
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
if (value instanceof Date) {
|
|
866
|
+
if (/^d[A-Za-z]+/.test(key)) {
|
|
867
|
+
retData[key] = moment(value).format('YYYY-MM-DD');
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
retData[key] = new Date(Date.UTC(value.getFullYear(), value.getMonth(), value.getDate(), value.getHours(), value.getMinutes(), value.getSeconds()));
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
else if (/^dt[A-Za-z]+/.test(key) && typeof value === 'string') {
|
|
874
|
+
if (/\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3}/.test(value)) {
|
|
875
|
+
retData[key] = new Date(value + 'Z');
|
|
876
|
+
}
|
|
877
|
+
else if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(value) || /\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}/.test(value)) {
|
|
878
|
+
retData[key] = new Date(value + ':00.000Z');
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
console.warn('FECHA INVALIDA AL ENVIAR (FormInter):', key, value);
|
|
882
|
+
retData[key] = value;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
else if (Array.isArray(value)) {
|
|
886
|
+
if (value.every(v => v instanceof File || v instanceof Blob)) {
|
|
887
|
+
retData[key] = value;
|
|
888
|
+
}
|
|
889
|
+
else {
|
|
890
|
+
retData[key] = value.map(item => typeof item === 'object' && item !== null
|
|
891
|
+
? transformarFechasPorNombreDeCampo(item)
|
|
892
|
+
: item);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
else if (typeof value === 'object' && value !== null) {
|
|
896
|
+
retData[key] = transformarFechasPorNombreDeCampo(value);
|
|
897
|
+
}
|
|
898
|
+
else {
|
|
899
|
+
retData[key] = value;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
return retData;
|
|
903
|
+
}
|
|
770
904
|
|
|
771
905
|
function mensajeAlerta(tipo, titulo, mensaje, opciones) {
|
|
772
906
|
opciones = {
|
|
@@ -1041,6 +1175,84 @@ function setLocalStorage(key, value = '') {
|
|
|
1041
1175
|
function roundToDecimal(number, decimal) {
|
|
1042
1176
|
return parseFloat(number.toFixed(decimal));
|
|
1043
1177
|
}
|
|
1178
|
+
function numberToWords(num) {
|
|
1179
|
+
if (num === 0)
|
|
1180
|
+
return 'cero';
|
|
1181
|
+
if (num < 0)
|
|
1182
|
+
return 'menos ' + numberToWords(Math.abs(num));
|
|
1183
|
+
if (num > 999999999999)
|
|
1184
|
+
return 'número demasiado grande';
|
|
1185
|
+
const ones = ['', 'un', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve'];
|
|
1186
|
+
const onesFinal = ['', 'uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve'];
|
|
1187
|
+
const tens = ['', 'diez', 'veinte', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta', 'ochenta', 'noventa'];
|
|
1188
|
+
const teens = ['diez', 'once', 'doce', 'trece', 'catorce', 'quince', 'dieciséis', 'diecisiete', 'dieciocho', 'diecinueve'];
|
|
1189
|
+
const hundreds = ['', 'ciento', 'doscientos', 'trescientos', 'cuatrocientos', 'quinientos', 'seiscientos', 'setecientos', 'ochocientos', 'novecientos'];
|
|
1190
|
+
// Función auxiliar para "un"/"uno"
|
|
1191
|
+
const getOneForm = (n, isFinal) => n === 1 ? (isFinal ? 'uno' : 'un') : onesFinal[n];
|
|
1192
|
+
let words = '';
|
|
1193
|
+
// Miles de millones (ahora sí se ejecuta)
|
|
1194
|
+
if (num >= 1000000000) {
|
|
1195
|
+
const billions = Math.floor(num / 1000000000);
|
|
1196
|
+
words += (billions === 1 ? 'mil' : numberToWords(billions) + ' mil') + ' millones ';
|
|
1197
|
+
num %= 1000000000;
|
|
1198
|
+
}
|
|
1199
|
+
// Millones
|
|
1200
|
+
if (num >= 1000000) {
|
|
1201
|
+
const millions = Math.floor(num / 1000000);
|
|
1202
|
+
words += millions === 1 ? 'un millón ' : numberToWords(millions) + ' millones ';
|
|
1203
|
+
num %= 1000000;
|
|
1204
|
+
}
|
|
1205
|
+
// Miles
|
|
1206
|
+
if (num >= 1000) {
|
|
1207
|
+
const thousands = Math.floor(num / 1000);
|
|
1208
|
+
words += thousands === 1 ? 'mil ' : numberToWords(thousands) + ' mil ';
|
|
1209
|
+
num %= 1000;
|
|
1210
|
+
}
|
|
1211
|
+
// Centenas (con tratamiento especial para "ciento uno")
|
|
1212
|
+
if (num >= 100) {
|
|
1213
|
+
if (num === 100) {
|
|
1214
|
+
words += 'cien';
|
|
1215
|
+
num = 0;
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
words += hundreds[Math.floor(num / 100)];
|
|
1219
|
+
num %= 100;
|
|
1220
|
+
if (num > 0) {
|
|
1221
|
+
words += ' ' + getOneForm(num, true); // Siempre "uno" después de ciento
|
|
1222
|
+
num = 0;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
// Decenas y unidades
|
|
1227
|
+
if (num > 0) {
|
|
1228
|
+
const isFinalWord = words === '';
|
|
1229
|
+
if (num < 10) {
|
|
1230
|
+
words += getOneForm(num, isFinalWord);
|
|
1231
|
+
}
|
|
1232
|
+
else if (num < 20) {
|
|
1233
|
+
words += teens[num - 10];
|
|
1234
|
+
}
|
|
1235
|
+
else if (num < 30) {
|
|
1236
|
+
if (num === 21)
|
|
1237
|
+
words += 'veintiuno';
|
|
1238
|
+
else if (num === 22)
|
|
1239
|
+
words += 'veintidós';
|
|
1240
|
+
else if (num === 23)
|
|
1241
|
+
words += 'veintitrés';
|
|
1242
|
+
else if (num === 26)
|
|
1243
|
+
words += 'veintiséis';
|
|
1244
|
+
else
|
|
1245
|
+
words += `veinti${onesFinal[num % 10]}`;
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
words += tens[Math.floor(num / 10)];
|
|
1249
|
+
if (num % 10 > 0) {
|
|
1250
|
+
words += ' y ' + getOneForm(num % 10, isFinalWord);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
return words.trim().replace(/\s+/g, ' ');
|
|
1255
|
+
}
|
|
1044
1256
|
|
|
1045
1257
|
function objectPropertiesToType(formFields) {
|
|
1046
1258
|
Object.keys(formFields).filter(control => !!formFields[control]).forEach(control => {
|
|
@@ -1084,6 +1296,52 @@ function generateRandomString(length) {
|
|
|
1084
1296
|
}
|
|
1085
1297
|
return result;
|
|
1086
1298
|
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Obtiene el host (hostname) de una URL o cadena host[:port].
|
|
1301
|
+
* Opcionalmente puede devolver también el puerto si está presente.
|
|
1302
|
+
*
|
|
1303
|
+
* - Acepta inputs como:
|
|
1304
|
+
* 'https://example.com/path', 'example.com:3000', 'localhost', 'http://[::1]:4200'
|
|
1305
|
+
* - Usa la API URL cuando es posible (más robusta) y cae a un regex de respaldo.
|
|
1306
|
+
*
|
|
1307
|
+
* @param url Cadena que representa una URL o host
|
|
1308
|
+
* @param options
|
|
1309
|
+
* @param options.includePort Si es true, incluye":puerto" cuando exista (por defecto false)
|
|
1310
|
+
* @param options.includeProtocol Incluye "http://" o "https://" según corresponda (por defecto false)
|
|
1311
|
+
*/
|
|
1312
|
+
function obtenerHostDesdeUrl(url, options) {
|
|
1313
|
+
if (!url)
|
|
1314
|
+
return null;
|
|
1315
|
+
const includePort = !!options?.includePort;
|
|
1316
|
+
const includeProtocol = !!options?.includeProtocol;
|
|
1317
|
+
// Intentar con API URL
|
|
1318
|
+
try {
|
|
1319
|
+
const candidate = url.includes('://') ? url : `http://${url}`;
|
|
1320
|
+
const parsed = new URL(candidate);
|
|
1321
|
+
const protocol = includeProtocol ? `${parsed.protocol}//` : '';
|
|
1322
|
+
const hostname = parsed.hostname;
|
|
1323
|
+
const port = parsed.port;
|
|
1324
|
+
if (!hostname)
|
|
1325
|
+
return null;
|
|
1326
|
+
return `${protocol}${hostname}${includePort && port ? `:${port}` : ''}`;
|
|
1327
|
+
}
|
|
1328
|
+
catch {
|
|
1329
|
+
// Regex fallback
|
|
1330
|
+
const regex = /^(?:(?<protocol>[a-z]+):\/\/)?(?:www\.)?(?<host>\[[^\]]+\]|[A-Za-z0-9.-]+)(?::(?<port>\d{1,5}))?/;
|
|
1331
|
+
const match = String(url).match(regex);
|
|
1332
|
+
if (!match?.groups)
|
|
1333
|
+
return null;
|
|
1334
|
+
let host = match.groups['host'];
|
|
1335
|
+
if (host.startsWith('[') && host.endsWith(']')) {
|
|
1336
|
+
host = host.slice(1, -1);
|
|
1337
|
+
}
|
|
1338
|
+
const port = match.groups['port'];
|
|
1339
|
+
const protocol = includeProtocol ? `${match.groups['protocol'] ?? 'http'}://` : '';
|
|
1340
|
+
return `${protocol}${host}${includePort && port ? `:${port}` : ''}`;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
/** @deprecated Alias compatible (deprecated) — preferir usar `obtenerHostDesdeUrl`. */
|
|
1344
|
+
const extraerDominio = (url, options) => obtenerHostDesdeUrl(url, options);
|
|
1087
1345
|
|
|
1088
1346
|
function verificarRUC(ruc) {
|
|
1089
1347
|
const f = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
@@ -1522,5 +1780,5 @@ function zeroFill(value, digitos, ...args) {
|
|
|
1522
1780
|
* Generated bundle index. Do not edit.
|
|
1523
1781
|
*/
|
|
1524
1782
|
|
|
1525
|
-
export { DataEnListaPipe, DataModel, DateDiffStringPipe, FiltroPipe, FormControlIsRequiredPipe, JsonParsePipe, NoSanitizePipe, TipoValorFuncionPipe, ZeroFillPipe, b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, convertirBytes, dataEnLista, dateDiffString, deepClone, deepMerge, delLocalStorage, desencriptar, downLoadFileStream, encriptar, esNumero, establecerQuitarRequired, formControlIsRequired, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, groupBy, inicializarVariablesSessionStorage, isEmail, jwtToken, jwtTokenData, jwtTokenExpiracion, jwtTokenExpiracionFaltante, localStorageKeys, markAsTouchedWithoutEmitEvent, maskEmail, mensajeAlerta, mensajeConfirmacion, mensajeTimer, mensajeToast, mensajesDeError, mensajesErrorFormControl, mostrarValorEnBusqueda, nestGroupsBy, objectPropertiesBoolean, objectPropertiesToType, obtenerMimeType, obtenerUltimoOrden, ordenarArray, ordenarPorPropiedad, ordenarPorPropiedades, roundToDecimal, sanitizarNombreArchivo, seleccionarTextoInput, setCambiarPwd, setJwtTokenData, setLocalStorage, sumarObjetos, sumarPropiedades, tipoValorFuncion, toFormData, verificarRUC, zeroFill };
|
|
1783
|
+
export { DataEnListaPipe, DataModel, DateDiffStringPipe, FiltroPipe, FormControlIsRequiredPipe, JsonParsePipe, NoSanitizePipe, TipoValorFuncionPipe, ZeroFillPipe, b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, convertirBytes, dataEnLista, dateDiffString, deepClone, deepMerge, delLocalStorage, desencriptar, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encriptar, esNumero, establecerQuitarRequired, extraerDominio, formControlIsRequired, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, groupBy, inicializarVariablesSessionStorage, isEmail, jwtToken, jwtTokenData, jwtTokenExpiracion, jwtTokenExpiracionFaltante, localStorageKeys, markAsTouchedWithoutEmitEvent, maskEmail, mensajeAlerta, mensajeConfirmacion, mensajeTimer, mensajeToast, mensajesDeError, mensajesErrorFormControl, mostrarValorEnBusqueda, nestGroupsBy, numberToWords, objectPropertiesBoolean, objectPropertiesToType, obtenerHostDesdeUrl, obtenerMimeType, obtenerUltimoOrden, ordenarArray, ordenarPorPropiedad, ordenarPorPropiedades, roundToDecimal, sanitizarNombreArchivo, seleccionarTextoInput, setCambiarPwd, setControlDesdeLista, setJwtTokenData, setLocalStorage, sumarObjetos, sumarPropiedades, tipoValorFuncion, toFormData, transformarFechasPorNombreDeCampo, verificarRUC, zeroFill };
|
|
1526
1784
|
//# sourceMappingURL=jvsoft-utils.mjs.map
|