@jvsoft/utils 0.0.13-alpha.5 → 1.0.0-alpha.4

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.
@@ -11,14 +11,6 @@ import moment from 'moment';
11
11
  import swal from 'sweetalert2';
12
12
  import { jwtDecode } from 'jwt-decode';
13
13
 
14
- /**
15
- * Realiza una fusión profunda entre dos objetos, sin modificar el original.
16
- * Si el valor en target no es un objeto, lo reemplaza directamente.
17
- *
18
- * @param source - Objeto fuente que se clonará y fusionará.
19
- * @param target - Objeto destino cuyos valores se fusionarán.
20
- * @returns Un nuevo objeto con la fusión profunda.
21
- */
22
14
  function deepMerge(source, target) {
23
15
  // Crea un clon profundo sin usar JSON.parse(JSON.stringify)
24
16
  let cloneSource = deepClone(source);
@@ -40,12 +32,7 @@ function deepMerge(source, target) {
40
32
  }
41
33
  return cloneSource; // Retorna el clon y no modifica el original
42
34
  }
43
- /**
44
- * Realiza una clonación profunda de un objeto, manejando funciones, fechas y arrays.
45
- *
46
- * @param obj - Objeto a clonar.
47
- * @returns Una copia profunda del objeto.
48
- */
35
+ // Función de clonación profunda que maneja funciones, fechas y otros tipos especiales
49
36
  function deepClone(obj) {
50
37
  if (obj === null || typeof obj !== 'object') {
51
38
  return obj; // Devuelve el valor si no es un objeto
@@ -71,7 +58,6 @@ function deepClone(obj) {
71
58
  /**
72
59
  * Busca un elemento en un array o jerarquía de objetos según un campo y valor especificado.
73
60
  *
74
- * @param datosFn - Objeto con los parámetros de búsqueda: items, campo, valor y opcionalmente campoHijo.
75
61
  * @returns El elemento encontrado o undefined si no existe.
76
62
  */
77
63
  function buscarPorCampo(datosFn) {
@@ -98,33 +84,13 @@ function buscarPorCampo(datosFn) {
98
84
  // Si no se encuentra nada, retorna undefined
99
85
  return undefined;
100
86
  }
101
- /**
102
- * Suma los valores de las propiedades especificadas de un objeto.
103
- *
104
- * @param item - Objeto con las propiedades a sumar.
105
- * @param campos - Array de nombres de las propiedades a sumar.
106
- * @returns La suma de los valores de las propiedades.
107
- */
108
87
  function sumarPropiedades(item, campos) {
109
88
  const datosSumar = campos.map(campo => (item[campo] * 1));
110
89
  return datosSumar.reduce((a, b) => a + b, 0);
111
90
  }
112
- /**
113
- * Verifica si el valor proporcionado es un número válido.
114
- *
115
- * @param value - Valor a verificar.
116
- * @returns true si es un número, false en caso contrario.
117
- */
118
91
  function esNumero(value) {
119
92
  return !isNaN(Number(value));
120
93
  }
121
- /**
122
- * Suma los valores de las propiedades especificadas en un array de objetos.
123
- *
124
- * @param arrayObjetos - Array de objetos a procesar.
125
- * @param campos - Array de nombres de las propiedades a sumar.
126
- * @returns Objeto con la suma de cada propiedad.
127
- */
128
94
  function sumarObjetos(arrayObjetos, campos) {
129
95
  return arrayObjetos.reduce((accumulator, item) => {
130
96
  campos.forEach(campo => {
@@ -136,22 +102,9 @@ function sumarObjetos(arrayObjetos, campos) {
136
102
  return accumulator;
137
103
  }, {});
138
104
  }
139
- /**
140
- * Obtiene los valores únicos de un array.
141
- *
142
- * @param array - Array de valores.
143
- * @returns Array con los valores únicos.
144
- */
145
105
  function getUniqueValues(array) {
146
106
  return array.filter((currentValue, index, arr) => (arr.indexOf(currentValue) === index));
147
107
  }
148
- /**
149
- * Obtiene los objetos únicos de un array según una propiedad específica.
150
- *
151
- * @param objetos - Array de objetos.
152
- * @param campo - Nombre de la propiedad para determinar unicidad.
153
- * @returns Array de objetos únicos por la propiedad.
154
- */
155
108
  function getUniqueValuesByProperty(objetos, campo) {
156
109
  const objetosUnicos = {};
157
110
  objetos.forEach(objeto => {
@@ -167,14 +120,6 @@ function getUniqueValuesByProperty(objetos, campo) {
167
120
  // Convertir el objeto de claves únicas de vuelta a una lista de objetos
168
121
  return Object.values(objetosUnicos);
169
122
  }
170
- /**
171
- * Ordena un array de valores numéricos o alfabéticos.
172
- *
173
- * @param array - Array a ordenar.
174
- * @param numeros - Si es true, ordena como números.
175
- * @param sentido - 'ASC' para ascendente, 'DESC' para descendente.
176
- * @returns Array ordenado.
177
- */
178
123
  function ordenarArray(array, numeros = false, sentido = 'ASC') {
179
124
  if (numeros) {
180
125
  if (sentido != 'ASC') {
@@ -184,24 +129,9 @@ function ordenarArray(array, numeros = false, sentido = 'ASC') {
184
129
  }
185
130
  return array.sort((a, b) => (a > b) ? 1 : ((b > a) ? -1 : 0));
186
131
  }
187
- /**
188
- * Ordena un array de objetos por una propiedad específica.
189
- *
190
- * @param objData - Array de objetos a ordenar.
191
- * @param propiedad - Propiedad por la que se ordena.
192
- * @param numeros - (Obsoleto) Si es true, ordena como números.
193
- * @returns Array ordenado.
194
- */
195
132
  function ordenarPorPropiedad(objData, propiedad, /**@deprecated*/ numeros = false) {
196
133
  return ordenarPorPropiedades(objData, { propiedades: [propiedad], direcciones: ['asc'] });
197
134
  }
198
- /**
199
- * Ordena un array de objetos por varias propiedades y direcciones.
200
- *
201
- * @param arr - Array de objetos a ordenar.
202
- * @param options - Opciones con propiedades y direcciones de orden.
203
- * @returns Array ordenado.
204
- */
205
135
  function ordenarPorPropiedades(arr, options) {
206
136
  const { propiedades, direcciones = [] } = options;
207
137
  const orden = direcciones.map(d => d === 'desc' ? -1 : 1);
@@ -221,13 +151,6 @@ function ordenarPorPropiedades(arr, options) {
221
151
  }, 0);
222
152
  });
223
153
  }
224
- /**
225
- * Agrupa los elementos de un array según una clave o función de clave.
226
- *
227
- * @param array - Array de objetos a agrupar.
228
- * @param key - Propiedad o función para agrupar.
229
- * @returns Objeto con los grupos por clave.
230
- */
231
154
  function groupBy(array, key) {
232
155
  const keyFn = key instanceof Function ? key : (obj) => obj[key];
233
156
  return array.reduce((objectsByKeyValue, obj) => {
@@ -236,13 +159,6 @@ function groupBy(array, key) {
236
159
  return objectsByKeyValue;
237
160
  }, {});
238
161
  }
239
- /**
240
- * Agrupa y anida los elementos de un array según una lista de propiedades.
241
- *
242
- * @param arr - Array de objetos a agrupar.
243
- * @param properties - Propiedades para agrupar de forma anidada.
244
- * @returns Objeto anidado por los grupos de propiedades.
245
- */
246
162
  function nestGroupsBy(arr, properties) {
247
163
  const fnGroupBy = (conversions, property2) => {
248
164
  return conversions.reduce((acc, obj) => {
@@ -316,13 +232,6 @@ function eliminarColumnaPorIndex(data, columnIndex) {
316
232
  return newRow;
317
233
  });
318
234
  }
319
- /**
320
- * Elimina elementos duplicados de un array de objetos según claves específicas.
321
- *
322
- * @param array - Array de objetos.
323
- * @param claves - Claves para determinar unicidad. Si no se especifica, compara todo el objeto.
324
- * @returns Array sin duplicados.
325
- */
326
235
  function eliminarDuplicados(array, claves) {
327
236
  const unicos = new Map();
328
237
  for (const item of array) {
@@ -335,14 +244,6 @@ function eliminarDuplicados(array, claves) {
335
244
  }
336
245
  return Array.from(unicos.values());
337
246
  }
338
- /**
339
- * Elimina elementos de un array origen que estén presentes en otro array, según claves específicas.
340
- *
341
- * @param origen - Array original.
342
- * @param elementosAEliminar - Elementos a eliminar del array origen.
343
- * @param claves - Claves para comparar los objetos. Si no se especifica, compara todo el objeto.
344
- * @returns Array filtrado sin los elementos eliminados.
345
- */
346
247
  function eliminarElementos(origen, elementosAEliminar, claves) {
347
248
  const clavesSet = new Set();
348
249
  for (const item of elementosAEliminar) {
@@ -359,152 +260,227 @@ function eliminarElementos(origen, elementosAEliminar, claves) {
359
260
  });
360
261
  }
361
262
 
362
- /**
363
- * Devuelve un valor de visualización para un elemento buscado.
364
- * Compatible con listas simples, objetos y campos múltiples.
365
- */
366
263
  function mostrarValorEnBusqueda(campos, idxSel) {
367
- const buscarEnLista = (lista) => {
368
- if (!lista)
369
- return null;
370
- if (campos.campoId === '*object*' || campos.campoId === '*objeto*') {
371
- return lista.find((x) => JSON.stringify(x).trim() === JSON.stringify(idxSel).trim());
372
- }
373
- return lista.find((x) => x[campos.campoId] === idxSel);
374
- };
375
264
  const impDataMostrar = () => {
376
- let vD = buscarEnLista(campos.lista) || (campos.opcExtra && buscarEnLista(campos.opcExtra));
377
- if (!vD)
378
- return '';
379
- if (Array.isArray(campos.campoValue)) {
380
- return campos.campoValue.map((vCampo) => vD[vCampo] ?? '').join(' - ').trim();
265
+ let vD;
266
+ if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
267
+ console.log(campos);
268
+ vD = campos.lista.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
269
+ console.log(vD);
270
+ }
271
+ else {
272
+ vD = campos.lista.find((x) => x[campos.campoId] == idxSel);
273
+ }
274
+ if (!vD && campos.opcExtra) {
275
+ console.log('eval ', campos.opcExtra);
276
+ if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
277
+ console.log(campos);
278
+ vD = campos.opcExtra.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
279
+ console.log(vD);
280
+ }
281
+ else {
282
+ vD = campos.opcExtra.find((x) => x[campos.campoId] == idxSel);
283
+ }
284
+ }
285
+ if (vD) {
286
+ let txtFinal = '';
287
+ if (Array.isArray(campos.campoValue)) {
288
+ campos.campoValue.forEach((vCampo, idx) => {
289
+ txtFinal += (vD[vCampo] ?? '');
290
+ if (idx < campos.campoValue.length - 1) {
291
+ txtFinal += ' - ';
292
+ }
293
+ });
294
+ }
295
+ else {
296
+ txtFinal = vD[campos.campoValue] ?? '';
297
+ }
298
+ return txtFinal.trim();
299
+ }
300
+ else {
301
+ console.log('ASSSSS ----- SSSS ');
381
302
  }
382
- return (vD[campos.campoValue] ?? '').trim();
303
+ return '';
383
304
  };
384
305
  if (esNumero(idxSel)) {
385
- if ((idxSel > 0 && campos.lista?.length) || (idxSel && typeof idxSel === 'object')) {
306
+ if (idxSel > 0 && campos.lista?.length > 0) {
307
+ return impDataMostrar();
308
+ }
309
+ else if (idxSel && typeof idxSel == 'object') {
386
310
  return impDataMostrar();
387
311
  }
388
312
  }
389
- else if (campos.lista?.length) {
390
- return impDataMostrar();
313
+ else {
314
+ if (campos.lista?.length > 0) {
315
+ return impDataMostrar();
316
+ }
391
317
  }
392
318
  return '';
393
319
  }
394
- /**
395
- * Filtra datos locales de un array basado en un valor de búsqueda.
396
- */
397
- function filtrarDatosLocal(data, value, campoBuscar) {
398
- if (!value)
399
- return data;
400
- const normalizar = (val) => val?.toString()?.toLowerCase() ?? '';
401
- const esNum = !isNaN(Number(value));
402
- return data.filter(item => {
403
- const campos = Array.isArray(campoBuscar) ? campoBuscar : [campoBuscar];
404
- return campos.some(campo => {
405
- const campoVal = item[campo];
406
- if (campoVal == null)
407
- return false;
408
- return esNum
409
- ? campoVal.toString().includes(value.toString())
410
- : normalizar(campoVal).includes(normalizar(value));
411
- });
412
- });
413
- }
414
- /**
415
- * Vincula un FormControl a datos locales para autocompletado.
416
- */
417
- function changeSelectData(objThis, { formControl, data, campoBuscar, variableResultado }) {
418
- objThis.filtrados[variableResultado] = formControl.valueChanges.pipe(untilDestroyed(objThis)).pipe(startWith(''), map(value => data ? filtrarDatosLocal(data, value, campoBuscar) : []));
320
+ function changeSelectData(objThis, dataFiltro) {
321
+ objThis['filtrados'][dataFiltro.variableResultado] = dataFiltro.formControl.valueChanges.pipe(untilDestroyed(objThis)).pipe(startWith(''), map(value => {
322
+ const varN = dataFiltro.data;
323
+ if (varN) {
324
+ if (value) {
325
+ return varN.map(x => x).filter(dat => {
326
+ if (Array.isArray(dataFiltro.campoBuscar)) {
327
+ let encontrado = false;
328
+ for (const vCampo of dataFiltro.campoBuscar) {
329
+ // console.log(vCampo, value, dat[vCampo]);
330
+ if (isNaN(Number(value))) {
331
+ // NO ES NUMERO
332
+ if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
333
+ encontrado = true;
334
+ break;
335
+ }
336
+ }
337
+ else {
338
+ if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
339
+ encontrado = true;
340
+ break;
341
+ }
342
+ }
343
+ }
344
+ return encontrado;
345
+ }
346
+ else {
347
+ if (isNaN(Number(value))) {
348
+ return dat[dataFiltro.campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
349
+ }
350
+ else {
351
+ return dat[dataFiltro.campoBuscar].toString().includes(value?.toString());
352
+ }
353
+ }
354
+ });
355
+ }
356
+ return varN;
357
+ }
358
+ return false;
359
+ }));
419
360
  }
420
- /**
421
- * Vincula un FormControl a datos locales obtenidos de dataServidor o dataServidorSuscripcion.
422
- */
423
361
  function changeSelect(control, formControl, tipo, campoBuscar, campoFiltro = null) {
424
- const filtro = campoFiltro ?? tipo;
425
- control.filtrados[filtro] = formControl.valueChanges.pipe(untilDestroyed(control)).pipe(startWith(''), map(value => {
362
+ // console.log(formControl);
363
+ // const formGroup = formControl.parent.controls;
364
+ // console.warn( Object.keys(formGroup).find(name => formControl === formGroup[name]) || null );
365
+ if (!campoFiltro) {
366
+ campoFiltro = tipo;
367
+ }
368
+ control['filtrados'][campoFiltro ?? '__'] = formControl.valueChanges.pipe(untilDestroyed(control)).pipe(startWith(''), map(value => {
369
+ // console.warn(value);
426
370
  const partes = tipo.split('.');
427
- const varN = control.dataServidor?.[partes[0]]?.[partes[1]] ??
428
- control.dataServidor?.[tipo] ??
429
- control.dataServidorSuscripcion?.[tipo]?.getValue();
430
- return varN ? filtrarDatosLocal(varN, value, campoBuscar) : [];
371
+ let varN;
372
+ if (control['dataServidor']) {
373
+ varN = (partes.length > 1) ? control['dataServidor'][partes[0]][partes[1]] : control['dataServidor'][tipo];
374
+ }
375
+ else if (control['dataServidorSuscripcion']) {
376
+ varN = control['dataServidorSuscripcion'][tipo].getValue();
377
+ }
378
+ if (varN) {
379
+ if (value) {
380
+ return varN.map((x) => x).filter((dat) => {
381
+ if (Array.isArray(campoBuscar)) {
382
+ let encontrado = false;
383
+ for (const vCampo of campoBuscar) {
384
+ // console.log(vCampo, value, dat[vCampo]);
385
+ if (isNaN(Number(value))) {
386
+ // NO ES NUMERO
387
+ if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
388
+ encontrado = true;
389
+ break;
390
+ }
391
+ }
392
+ else {
393
+ if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
394
+ encontrado = true;
395
+ break;
396
+ }
397
+ }
398
+ }
399
+ return encontrado;
400
+ }
401
+ else {
402
+ if (isNaN(Number(value))) {
403
+ return dat[campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
404
+ }
405
+ else {
406
+ return dat[campoBuscar].toString().includes(value?.toString());
407
+ }
408
+ }
409
+ });
410
+ }
411
+ return varN;
412
+ }
413
+ return false;
431
414
  }));
432
415
  }
433
- /**
434
- * Función genérica para vincular un FormControl con datos desde API o Promise.
435
- * Preparada para migrar a signals en el futuro.
436
- */
437
- function changeSelectReformateado(config) {
438
- const { objThis, tipoReq, formControl, queryService, campoId, minLength = 3, dataExtra = {}, dataExtraVariable = [], anonimo = false, variableResultado = tipoReq, } = config;
439
- formControl.valueChanges.pipe(debounceTime(500), tap(() => {
440
- objThis.filtrados[variableResultado + 'tmp'] = isObservable(objThis.filtrados[variableResultado])
441
- ? []
442
- : objThis.filtrados[variableResultado] || [];
443
- if (objThis.filtrados[variableResultado] !== objThis.filtrados[variableResultado + 'tmp']) {
444
- objThis.filtrados[variableResultado] = [];
416
+ function changeSelectDataApi(objThis, dataFiltro) {
417
+ if (!dataFiltro.variableResultado) {
418
+ dataFiltro.variableResultado = dataFiltro.tipoReq;
419
+ }
420
+ const idFiltrado = dataFiltro.variableResultado;
421
+ dataFiltro.formControl.valueChanges.pipe(debounceTime(500), tap(() => {
422
+ objThis.filtrados[dataFiltro.variableResultado + 'tmp'] = isObservable(objThis.filtrados[idFiltrado]) ? [] : objThis.filtrados[idFiltrado] || [];
423
+ if (objThis.filtrados[idFiltrado] !== objThis.filtrados[idFiltrado + 'tmp']) {
424
+ objThis.filtrados[idFiltrado] = [];
445
425
  }
446
426
  objThis.isLoading = true;
447
427
  }), switchMap(value => {
448
- if (campoId) {
449
- const existe = objThis.filtrados[variableResultado + 'tmp']
450
- .findIndex((item) => item[campoId] === value);
451
- if (existe >= 0) {
452
- return of({ [tipoReq]: objThis.filtrados[variableResultado + 'tmp'] });
428
+ if (dataFiltro.campoId) {
429
+ const busquedaActual2 = objThis.filtrados[idFiltrado + 'tmp'].findIndex((item) => item[dataFiltro.campoId ?? '--'] === value);
430
+ if (busquedaActual2 >= 0) {
431
+ return of({ [dataFiltro.tipoReq]: objThis.filtrados[idFiltrado + 'tmp'] });
453
432
  }
454
433
  }
455
- if (!value || value.length < minLength) {
456
- objThis.isLoading = false;
457
- return of({ [tipoReq]: [] });
458
- }
459
- const extraVars = Object.fromEntries(dataExtraVariable.map(v => [v.campo, v.ctrlValue.value]));
460
- const query = queryService.getDataMethod('GET', tipoReq, { ...dataExtra, ...extraVars, txtBuscar: value }, anonimo);
461
- if (esPromise(query)) {
462
- return query.then((data) => ({ [tipoReq]: data[tipoReq] ?? [] }))
463
- .finally(() => { objThis.isLoading = false; });
464
- }
465
- return query.pipe(finalize(() => { objThis.isLoading = false; }));
434
+ return !value || value.length < (dataFiltro.minLength ?? 3) ? [] : (dataFiltro.queryService.getDataMethod('GET', dataFiltro.tipoReq, {
435
+ ...(dataFiltro.dataExtra ?? {}),
436
+ ...(dataFiltro.dataExtraVariable ? Object.fromEntries(dataFiltro.dataExtraVariable.map((objData) => [objData.campo, objData.ctrlValue.value])) : {}),
437
+ txtBuscar: value,
438
+ }, dataFiltro.anonimo).pipe(finalize(() => objThis.isLoading = false)));
466
439
  })).subscribe((data) => {
467
- objThis.filtrados[variableResultado] = data[tipoReq] ?? [];
468
- });
469
- }
470
- /**
471
- * Alias para compatibilidad.
472
- */
473
- function changeSelectDataApi(objThis, dataFiltro) {
474
- return changeSelectReformateado({
475
- objThis,
476
- tipoReq: dataFiltro.tipoReq,
477
- formControl: dataFiltro.formControl,
478
- queryService: dataFiltro.queryService,
479
- campoId: dataFiltro.campoId,
480
- minLength: dataFiltro.minLength,
481
- dataExtra: dataFiltro.dataExtra,
482
- dataExtraVariable: dataFiltro.dataExtraVariable,
483
- anonimo: dataFiltro.anonimo,
484
- variableResultado: dataFiltro.variableResultado,
440
+ objThis.filtrados[idFiltrado] = data[dataFiltro.tipoReq] ?? [];
485
441
  });
486
442
  }
487
- /**
488
- * Alias para compatibilidad.
489
- */
490
443
  function changeSelectApi(control, queryService, formControl, tipo, dataExtra = {}, dataExtraVariable = null, minLength = 1, anonimo = false) {
491
- return changeSelectReformateado({
492
- objThis: control,
493
- tipoReq: tipo,
494
- formControl,
495
- queryService,
496
- minLength,
497
- dataExtra,
498
- dataExtraVariable: dataExtraVariable ?? [],
499
- anonimo,
444
+ formControl.valueChanges.pipe(debounceTime(500), tap((value) => {
445
+ control['filtrados'][tipo + 'tmp'] = isObservable(control['filtrados'][tipo]) ? [] : control['filtrados'][tipo];
446
+ if (control['filtrados'][tipo] != control['filtrados'][tipo + 'tmp']) {
447
+ control['filtrados'][tipo] = [];
448
+ }
449
+ control['isLoading'] = true;
450
+ }), switchMap(value => {
451
+ const formGroup = formControl.parent?.controls;
452
+ const nombreControl = Object.keys(formGroup).find(name => formControl === formGroup[name]) || null;
453
+ if (nombreControl && control['filtrados'][tipo + 'tmp'] && control['filtrados'][tipo + 'tmp'].length > 0) {
454
+ const busquedaActual = control['filtrados'][tipo + 'tmp'].findIndex((item) => item[nombreControl] == value);
455
+ if (busquedaActual >= 0) {
456
+ const vRet = {};
457
+ vRet[tipo] = control['filtrados'][tipo + 'tmp'];
458
+ control['isLoading'] = false;
459
+ return of(vRet);
460
+ }
461
+ }
462
+ if (!value || value.length < minLength) {
463
+ return [];
464
+ }
465
+ const dataExtraVariableData = {};
466
+ if (dataExtraVariable) {
467
+ // @ts-ignore
468
+ for (const objData of dataExtraVariable) {
469
+ dataExtraVariableData[objData.campo] = objData.ctrlValue.value;
470
+ }
471
+ }
472
+ return queryService.getDataMethod('GET', tipo, { ...dataExtra, ...dataExtraVariableData, ...{ txtBuscar: value } }, anonimo).pipe(finalize(() => {
473
+ control['isLoading'] = false;
474
+ }));
475
+ })).subscribe((data) => {
476
+ if (data[tipo] == undefined) {
477
+ control['filtrados'][tipo] = [];
478
+ }
479
+ else {
480
+ control['filtrados'][tipo] = data[tipo];
481
+ }
500
482
  });
501
483
  }
502
- /**
503
- * Comprueba si un valor es una Promesa.
504
- */
505
- function esPromise(valor) {
506
- return !!valor && typeof valor.then === 'function';
507
- }
508
484
 
509
485
  function seleccionarTextoInput(event) {
510
486
  event.target.select();
@@ -580,6 +556,147 @@ function formatearFechaCadena(fecha) {
580
556
  return new Date(year, month, day);
581
557
  }
582
558
 
559
+ /**
560
+ * Configuración global para las utilidades de logging
561
+ */
562
+ let isProductionMode = false;
563
+ /**
564
+ * Configura el modo de producción para las utilidades de logging
565
+ * @param production - true si está en modo producción, false para desarrollo
566
+ *
567
+ * @example
568
+ * ```typescript
569
+ * import { setProductionMode } from '@jvsoft/utils';
570
+ * import { environment } from './environments/environment';
571
+ *
572
+ * setProductionMode(environment.production);
573
+ * ```
574
+ */
575
+ function setProductionMode(production) {
576
+ isProductionMode = production;
577
+ }
578
+ /**
579
+ * Obtiene el estado actual del modo de producción
580
+ * @returns true si está en modo producción, false en desarrollo
581
+ */
582
+ function isProduction() {
583
+ return isProductionMode;
584
+ }
585
+ /**
586
+ * Muestra mensajes de log solo en modo desarrollo
587
+ * @param args - Argumentos a mostrar en consola
588
+ *
589
+ * @example
590
+ * ```typescript
591
+ * devLog('Usuario cargado:', usuario);
592
+ * devLog('Estado:', { activo: true, rol: 'admin' });
593
+ * ```
594
+ */
595
+ function devLog(...args) {
596
+ if (!isProductionMode) {
597
+ console.log(...args);
598
+ }
599
+ }
600
+ /**
601
+ * Muestra advertencias solo en modo desarrollo
602
+ * @param args - Argumentos a mostrar como advertencia
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * devWarn('Función deprecada, usar nuevaFuncion() en su lugar');
607
+ * ```
608
+ */
609
+ function devWarn(...args) {
610
+ if (!isProductionMode) {
611
+ console.warn(...args);
612
+ }
613
+ }
614
+ /**
615
+ * Muestra errores en consola (siempre, incluso en producción)
616
+ * @param args - Argumentos a mostrar como error
617
+ *
618
+ * @example
619
+ * ```typescript
620
+ * devError('Error al cargar datos:', error);
621
+ * ```
622
+ */
623
+ function devError(...args) {
624
+ console.error(...args);
625
+ }
626
+ /**
627
+ * Crea un grupo de logs solo en modo desarrollo
628
+ * @param label - Etiqueta del grupo
629
+ * @param collapsed - Si el grupo debe estar colapsado por defecto
630
+ *
631
+ * @example
632
+ * ```typescript
633
+ * devGroup('Datos del usuario');
634
+ * devLog('Nombre:', usuario.nombre);
635
+ * devLog('Email:', usuario.email);
636
+ * devGroupEnd();
637
+ * ```
638
+ */
639
+ function devGroup(label, collapsed = false) {
640
+ if (!isProductionMode) {
641
+ if (collapsed) {
642
+ console.groupCollapsed(label);
643
+ }
644
+ else {
645
+ console.group(label);
646
+ }
647
+ }
648
+ }
649
+ /**
650
+ * Cierra el grupo de logs actual
651
+ */
652
+ function devGroupEnd() {
653
+ if (!isProductionMode) {
654
+ console.groupEnd();
655
+ }
656
+ }
657
+ /**
658
+ * Muestra una tabla en consola solo en modo desarrollo
659
+ * @param data - Datos a mostrar en formato tabla
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * devTable([
664
+ * { nombre: 'Juan', edad: 25 },
665
+ * { nombre: 'María', edad: 30 }
666
+ * ]);
667
+ * ```
668
+ */
669
+ function devTable(data) {
670
+ if (!isProductionMode) {
671
+ console.table(data);
672
+ }
673
+ }
674
+ /**
675
+ * Inicia un temporizador solo en modo desarrollo
676
+ * @param label - Etiqueta del temporizador
677
+ *
678
+ * @example
679
+ * ```typescript
680
+ * devTime('carga-datos');
681
+ * // ... código a medir
682
+ * devTimeEnd('carga-datos'); // Muestra: carga-datos: 123.45ms
683
+ * ```
684
+ */
685
+ function devTime(label) {
686
+ if (!isProductionMode) {
687
+ console.time(label);
688
+ }
689
+ }
690
+ /**
691
+ * Finaliza un temporizador y muestra el tiempo transcurrido
692
+ * @param label - Etiqueta del temporizador
693
+ */
694
+ function devTimeEnd(label) {
695
+ if (!isProductionMode) {
696
+ console.timeEnd(label);
697
+ }
698
+ }
699
+
583
700
  function maskEmail(email) {
584
701
  const [user, domain] = email.split("@");
585
702
  if (user.length <= 2) {
@@ -1387,5 +1504,5 @@ function verificarRUC(ruc) {
1387
1504
  * Generated bundle index. Do not edit.
1388
1505
  */
1389
1506
 
1390
- export { b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, changeSelectReformateado, convertirBytes, deepClone, deepMerge, delLocalStorage, desencriptar, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encriptar, esNumero, establecerQuitarRequired, extraerDominio, 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, toFormData, transformarFechasPorNombreDeCampo, verificarRUC };
1507
+ export { b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, convertirBytes, deepClone, deepMerge, delLocalStorage, desencriptar, devError, devGroup, devGroupEnd, devLog, devTable, devTime, devTimeEnd, devWarn, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encriptar, esNumero, establecerQuitarRequired, extraerDominio, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, groupBy, inicializarVariablesSessionStorage, isEmail, isProduction, 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, setProductionMode, sumarObjetos, sumarPropiedades, toFormData, transformarFechasPorNombreDeCampo, verificarRUC };
1391
1508
  //# sourceMappingURL=jvsoft-utils-src-functions.mjs.map