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

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) {
@@ -358,41 +259,12 @@ function eliminarElementos(origen, elementosAEliminar, claves) {
358
259
  return !clavesSet.has(key);
359
260
  });
360
261
  }
361
-
362
- /**
363
- * Devuelve un valor de visualización para un elemento buscado.
364
- * Compatible con listas simples, objetos y campos múltiples.
365
- */
366
- 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
- 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();
381
- }
382
- return (vD[campos.campoValue] ?? '').trim();
383
- };
384
- if (esNumero(idxSel)) {
385
- if ((idxSel > 0 && campos.lista?.length) || (idxSel && typeof idxSel === 'object')) {
386
- return impDataMostrar();
387
- }
388
- }
389
- else if (campos.lista?.length) {
390
- return impDataMostrar();
391
- }
392
- return '';
393
- }
394
262
  /**
395
- * Filtra datos locales de un array basado en un valor de búsqueda.
263
+ * Filtra datos localmente según un valor de búsqueda
264
+ * @param data - Array de datos a filtrar
265
+ * @param value - Valor de búsqueda
266
+ * @param campoBuscar - Campo(s) por el cual buscar
267
+ * @returns Array filtrado
396
268
  */
397
269
  function filtrarDatosLocal(data, value, campoBuscar) {
398
270
  if (!value)
@@ -411,24 +283,242 @@ function filtrarDatosLocal(data, value, campoBuscar) {
411
283
  });
412
284
  });
413
285
  }
286
+
287
+ function mostrarValorEnBusqueda(campos, idxSel) {
288
+ const impDataMostrar = () => {
289
+ let vD;
290
+ if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
291
+ console.log(campos);
292
+ vD = campos.lista.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
293
+ console.log(vD);
294
+ }
295
+ else {
296
+ vD = campos.lista.find((x) => x[campos.campoId] == idxSel);
297
+ }
298
+ if (!vD && campos.opcExtra) {
299
+ console.log('eval ', campos.opcExtra);
300
+ if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
301
+ console.log(campos);
302
+ vD = campos.opcExtra.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
303
+ console.log(vD);
304
+ }
305
+ else {
306
+ vD = campos.opcExtra.find((x) => x[campos.campoId] == idxSel);
307
+ }
308
+ }
309
+ if (vD) {
310
+ let txtFinal = '';
311
+ if (Array.isArray(campos.campoValue)) {
312
+ campos.campoValue.forEach((vCampo, idx) => {
313
+ txtFinal += (vD[vCampo] ?? '');
314
+ if (idx < campos.campoValue.length - 1) {
315
+ txtFinal += ' - ';
316
+ }
317
+ });
318
+ }
319
+ else {
320
+ txtFinal = vD[campos.campoValue] ?? '';
321
+ }
322
+ return txtFinal.trim();
323
+ }
324
+ else {
325
+ console.log('ASSSSS ----- SSSS ');
326
+ }
327
+ return '';
328
+ };
329
+ if (esNumero(idxSel)) {
330
+ if (idxSel > 0 && campos.lista?.length > 0) {
331
+ return impDataMostrar();
332
+ }
333
+ else if (idxSel && typeof idxSel == 'object') {
334
+ return impDataMostrar();
335
+ }
336
+ }
337
+ else {
338
+ if (campos.lista?.length > 0) {
339
+ return impDataMostrar();
340
+ }
341
+ }
342
+ return '';
343
+ }
344
+ function changeSelectData(objThis, dataFiltro) {
345
+ objThis['filtrados'][dataFiltro.variableResultado] = dataFiltro.formControl.valueChanges.pipe(untilDestroyed(objThis)).pipe(startWith(''), map(value => {
346
+ const varN = dataFiltro.data;
347
+ if (varN) {
348
+ if (value) {
349
+ return varN.map(x => x).filter(dat => {
350
+ if (Array.isArray(dataFiltro.campoBuscar)) {
351
+ let encontrado = false;
352
+ for (const vCampo of dataFiltro.campoBuscar) {
353
+ // console.log(vCampo, value, dat[vCampo]);
354
+ if (isNaN(Number(value))) {
355
+ // NO ES NUMERO
356
+ if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
357
+ encontrado = true;
358
+ break;
359
+ }
360
+ }
361
+ else {
362
+ if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
363
+ encontrado = true;
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ return encontrado;
369
+ }
370
+ else {
371
+ if (isNaN(Number(value))) {
372
+ return dat[dataFiltro.campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
373
+ }
374
+ else {
375
+ return dat[dataFiltro.campoBuscar].toString().includes(value?.toString());
376
+ }
377
+ }
378
+ });
379
+ }
380
+ return varN;
381
+ }
382
+ return false;
383
+ }));
384
+ }
385
+ function changeSelect(control, formControl, tipo, campoBuscar, campoFiltro = null) {
386
+ // console.log(formControl);
387
+ // const formGroup = formControl.parent.controls;
388
+ // console.warn( Object.keys(formGroup).find(name => formControl === formGroup[name]) || null );
389
+ if (!campoFiltro) {
390
+ campoFiltro = tipo;
391
+ }
392
+ control['filtrados'][campoFiltro ?? '__'] = formControl.valueChanges.pipe(untilDestroyed(control)).pipe(startWith(''), map(value => {
393
+ // console.warn(value);
394
+ const partes = tipo.split('.');
395
+ let varN;
396
+ if (control['dataServidor']) {
397
+ varN = (partes.length > 1) ? control['dataServidor'][partes[0]][partes[1]] : control['dataServidor'][tipo];
398
+ }
399
+ else if (control['dataServidorSuscripcion']) {
400
+ varN = control['dataServidorSuscripcion'][tipo].getValue();
401
+ }
402
+ if (varN) {
403
+ if (value) {
404
+ return varN.map((x) => x).filter((dat) => {
405
+ if (Array.isArray(campoBuscar)) {
406
+ let encontrado = false;
407
+ for (const vCampo of campoBuscar) {
408
+ // console.log(vCampo, value, dat[vCampo]);
409
+ if (isNaN(Number(value))) {
410
+ // NO ES NUMERO
411
+ if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
412
+ encontrado = true;
413
+ break;
414
+ }
415
+ }
416
+ else {
417
+ if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
418
+ encontrado = true;
419
+ break;
420
+ }
421
+ }
422
+ }
423
+ return encontrado;
424
+ }
425
+ else {
426
+ if (isNaN(Number(value))) {
427
+ return dat[campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
428
+ }
429
+ else {
430
+ return dat[campoBuscar].toString().includes(value?.toString());
431
+ }
432
+ }
433
+ });
434
+ }
435
+ return varN;
436
+ }
437
+ return false;
438
+ }));
439
+ }
440
+ function changeSelectDataApi(objThis, dataFiltro) {
441
+ if (!dataFiltro.variableResultado) {
442
+ dataFiltro.variableResultado = dataFiltro.tipoReq;
443
+ }
444
+ const idFiltrado = dataFiltro.variableResultado;
445
+ dataFiltro.formControl.valueChanges.pipe(debounceTime(500), tap(() => {
446
+ objThis.filtrados[dataFiltro.variableResultado + 'tmp'] = isObservable(objThis.filtrados[idFiltrado]) ? [] : objThis.filtrados[idFiltrado] || [];
447
+ if (objThis.filtrados[idFiltrado] !== objThis.filtrados[idFiltrado + 'tmp']) {
448
+ objThis.filtrados[idFiltrado] = [];
449
+ }
450
+ objThis.isLoading = true;
451
+ }), switchMap(value => {
452
+ if (dataFiltro.campoId) {
453
+ const busquedaActual2 = objThis.filtrados[idFiltrado + 'tmp'].findIndex((item) => item[dataFiltro.campoId ?? '--'] === value);
454
+ if (busquedaActual2 >= 0) {
455
+ return of({ [dataFiltro.tipoReq]: objThis.filtrados[idFiltrado + 'tmp'] });
456
+ }
457
+ }
458
+ return !value || value.length < (dataFiltro.minLength ?? 3) ? [] : (dataFiltro.queryService.getDataMethod('GET', dataFiltro.tipoReq, {
459
+ ...(dataFiltro.dataExtra ?? {}),
460
+ ...(dataFiltro.dataExtraVariable ? Object.fromEntries(dataFiltro.dataExtraVariable.map((objData) => [objData.campo, objData.ctrlValue.value])) : {}),
461
+ txtBuscar: value,
462
+ }, dataFiltro.anonimo).pipe(finalize(() => objThis.isLoading = false)));
463
+ })).subscribe((data) => {
464
+ objThis.filtrados[idFiltrado] = data[dataFiltro.tipoReq] ?? [];
465
+ });
466
+ }
467
+ function changeSelectApi(control, queryService, formControl, tipo, dataExtra = {}, dataExtraVariable = null, minLength = 1, anonimo = false) {
468
+ formControl.valueChanges.pipe(debounceTime(500), tap((value) => {
469
+ control['filtrados'][tipo + 'tmp'] = isObservable(control['filtrados'][tipo]) ? [] : control['filtrados'][tipo];
470
+ if (control['filtrados'][tipo] != control['filtrados'][tipo + 'tmp']) {
471
+ control['filtrados'][tipo] = [];
472
+ }
473
+ control['isLoading'] = true;
474
+ }), switchMap(value => {
475
+ const formGroup = formControl.parent?.controls;
476
+ const nombreControl = Object.keys(formGroup).find(name => formControl === formGroup[name]) || null;
477
+ if (nombreControl && control['filtrados'][tipo + 'tmp'] && control['filtrados'][tipo + 'tmp'].length > 0) {
478
+ const busquedaActual = control['filtrados'][tipo + 'tmp'].findIndex((item) => item[nombreControl] == value);
479
+ if (busquedaActual >= 0) {
480
+ const vRet = {};
481
+ vRet[tipo] = control['filtrados'][tipo + 'tmp'];
482
+ control['isLoading'] = false;
483
+ return of(vRet);
484
+ }
485
+ }
486
+ if (!value || value.length < minLength) {
487
+ return [];
488
+ }
489
+ const dataExtraVariableData = {};
490
+ if (dataExtraVariable) {
491
+ // @ts-ignore
492
+ for (const objData of dataExtraVariable) {
493
+ dataExtraVariableData[objData.campo] = objData.ctrlValue.value;
494
+ }
495
+ }
496
+ return queryService.getDataMethod('GET', tipo, { ...dataExtra, ...dataExtraVariableData, ...{ txtBuscar: value } }, anonimo).pipe(finalize(() => {
497
+ control['isLoading'] = false;
498
+ }));
499
+ })).subscribe((data) => {
500
+ if (data[tipo] == undefined) {
501
+ control['filtrados'][tipo] = [];
502
+ }
503
+ else {
504
+ control['filtrados'][tipo] = data[tipo];
505
+ }
506
+ });
507
+ }
414
508
  /**
415
- * Vincula un FormControl a datos locales para autocompletado.
509
+ * Comprueba si un valor es una Promesa
510
+ * @param valor - Valor a verificar
511
+ * @returns true si es una Promise
416
512
  */
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) : []));
513
+ function esPromise(valor) {
514
+ return !!valor && typeof valor.then === 'function';
419
515
  }
420
516
  /**
421
- * Vincula un FormControl a datos locales obtenidos de dataServidor o dataServidorSuscripcion.
517
+ * Selecciona todo el texto de un input
518
+ * @param event - Evento del input
422
519
  */
423
- 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 => {
426
- 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) : [];
431
- }));
520
+ function seleccionarTextoInput$1(event) {
521
+ event.target.select();
432
522
  }
433
523
  /**
434
524
  * Función genérica para vincular un FormControl con datos desde API o Promise.
@@ -456,10 +546,11 @@ function changeSelectReformateado(config) {
456
546
  objThis.isLoading = false;
457
547
  return of({ [tipoReq]: [] });
458
548
  }
459
- const extraVars = Object.fromEntries(dataExtraVariable.map(v => [v.campo, v.ctrlValue.value]));
549
+ const extraVars = Object.fromEntries(dataExtraVariable.map((v) => [v.campo, v.ctrlValue.value]));
460
550
  const query = queryService.getDataMethod('GET', tipoReq, { ...dataExtra, ...extraVars, txtBuscar: value }, anonimo);
461
551
  if (esPromise(query)) {
462
- return query.then((data) => ({ [tipoReq]: data[tipoReq] ?? [] }))
552
+ return query
553
+ .then((data) => ({ [tipoReq]: data[tipoReq] ?? [] }))
463
554
  .finally(() => { objThis.isLoading = false; });
464
555
  }
465
556
  return query.pipe(finalize(() => { objThis.isLoading = false; }));
@@ -467,57 +558,39 @@ function changeSelectReformateado(config) {
467
558
  objThis.filtrados[variableResultado] = data[tipoReq] ?? [];
468
559
  });
469
560
  }
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,
485
- });
486
- }
487
- /**
488
- * Alias para compatibilidad.
489
- */
490
- 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,
500
- });
501
- }
502
- /**
503
- * Comprueba si un valor es una Promesa.
504
- */
505
- function esPromise(valor) {
506
- return !!valor && typeof valor.then === 'function';
507
- }
508
561
 
509
562
  function seleccionarTextoInput(event) {
510
563
  event.target.select();
511
564
  }
512
565
 
566
+ /**
567
+ * Codifica un string a base64 (método legacy)
568
+ * @param val - String a codificar
569
+ * @returns String codificado en base64
570
+ * @deprecated Use encodeBase64String() en su lugar
571
+ */
513
572
  function b64Encode(val) {
514
573
  return Buffer.from(val, 'binary').toString('base64');
515
574
  }
575
+ /**
576
+ * Decodifica un string desde base64 (método legacy)
577
+ * @param val - String en base64 a decodificar
578
+ * @returns String decodificado
579
+ * @deprecated Use decodeBase64String() en su lugar
580
+ */
516
581
  function b64Decode(val) {
517
582
  return Buffer.from(val, 'base64').toString('binary');
518
583
  }
519
584
  /**
520
585
  * Codificar string a Base64 (UTF-8 seguro)
586
+ * @param str - String a codificar
587
+ * @returns String codificado en base64
588
+ *
589
+ * @example
590
+ * ```typescript
591
+ * const encoded = encodeBase64String('Hola Mundo ñ');
592
+ * // encoded: "SG9sYSBNdW5kbyDDsQ=="
593
+ * ```
521
594
  */
522
595
  function encodeBase64String(str) {
523
596
  const encoder = new TextEncoder();
@@ -528,6 +601,14 @@ function encodeBase64String(str) {
528
601
  }
529
602
  /**
530
603
  * Decodificar Base64 a string (UTF-8 seguro)
604
+ * @param b64 - String en base64 a decodificar
605
+ * @returns String decodificado
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * const decoded = decodeBase64String('SG9sYSBNdW5kbyDDsQ==');
610
+ * // decoded: "Hola Mundo ñ"
611
+ * ```
531
612
  */
532
613
  function decodeBase64String(b64) {
533
614
  const binary = atob(b64);
@@ -540,18 +621,43 @@ function decodeBase64String(b64) {
540
621
  }
541
622
  /**
542
623
  * Codificar un objeto a base64 (UTF-8 seguro)
624
+ * @param obj - Objeto a codificar
625
+ * @returns String codificado en base64
626
+ *
627
+ * @example
628
+ * ```typescript
629
+ * const obj = { nombre: 'Juan', edad: 25 };
630
+ * const encoded = encodeBase64Object(obj);
631
+ * ```
543
632
  */
544
633
  function encodeBase64Object(obj) {
545
634
  return encodeBase64String(JSON.stringify(obj));
546
635
  }
547
636
  /**
548
637
  * Decodificar un base64 y obtener el objeto original
638
+ * @param b64 - String en base64 a decodificar
639
+ * @returns Objeto decodificado
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * const obj = decodeBase64Object<{ nombre: string, edad: number }>(encoded);
644
+ * // obj: { nombre: 'Juan', edad: 25 }
645
+ * ```
549
646
  */
550
647
  function decodeBase64Object(b64) {
551
648
  return JSON.parse(decodeBase64String(b64));
552
649
  }
553
650
  /**
554
651
  * Codificar archivo a Base64 (retorna solo el contenido, sin "data:...")
652
+ * @param file - Archivo o Blob a codificar
653
+ * @returns Promise con el string en base64
654
+ *
655
+ * @example
656
+ * ```typescript
657
+ * const file = event.target.files[0];
658
+ * const base64 = await encodeBase64File(file);
659
+ * // base64: "iVBORw0KGgoAAAANSUhEUgAA..."
660
+ * ```
555
661
  */
556
662
  function encodeBase64File(file) {
557
663
  return new Promise((resolve, reject) => {
@@ -566,6 +672,16 @@ function encodeBase64File(file) {
566
672
  }
567
673
  /**
568
674
  * Decodificar Base64 a Blob (para reconstruir archivos en Angular)
675
+ * @param b64 - String en base64
676
+ * @param mimeType - Tipo MIME del archivo (opcional)
677
+ * @returns Blob con el contenido decodificado
678
+ *
679
+ * @example
680
+ * ```typescript
681
+ * const blob = decodeBase64ToBlob(base64String, 'image/png');
682
+ * const url = URL.createObjectURL(blob);
683
+ * // Usar url para mostrar imagen o descargar
684
+ * ```
569
685
  */
570
686
  function decodeBase64ToBlob(b64, mimeType = 'application/octet-stream') {
571
687
  const byteChars = atob(b64);
@@ -639,6 +755,147 @@ function formatearFechaCadena(fecha) {
639
755
  return new Date(year, month, day);
640
756
  }
641
757
 
758
+ /**
759
+ * Configuración global para las utilidades de logging
760
+ */
761
+ let isProductionMode = false;
762
+ /**
763
+ * Configura el modo de producción para las utilidades de logging
764
+ * @param production - true si está en modo producción, false para desarrollo
765
+ *
766
+ * @example
767
+ * ```typescript
768
+ * import { setProductionMode } from '@jvsoft/utils';
769
+ * import { environment } from './environments/environment';
770
+ *
771
+ * setProductionMode(environment.production);
772
+ * ```
773
+ */
774
+ function setProductionMode(production) {
775
+ isProductionMode = production;
776
+ }
777
+ /**
778
+ * Obtiene el estado actual del modo de producción
779
+ * @returns true si está en modo producción, false en desarrollo
780
+ */
781
+ function isProduction() {
782
+ return isProductionMode;
783
+ }
784
+ /**
785
+ * Muestra mensajes de log solo en modo desarrollo
786
+ * @param args - Argumentos a mostrar en consola
787
+ *
788
+ * @example
789
+ * ```typescript
790
+ * devLog('Usuario cargado:', usuario);
791
+ * devLog('Estado:', { activo: true, rol: 'admin' });
792
+ * ```
793
+ */
794
+ function devLog(...args) {
795
+ if (!isProductionMode) {
796
+ console.log(...args);
797
+ }
798
+ }
799
+ /**
800
+ * Muestra advertencias solo en modo desarrollo
801
+ * @param args - Argumentos a mostrar como advertencia
802
+ *
803
+ * @example
804
+ * ```typescript
805
+ * devWarn('Función deprecada, usar nuevaFuncion() en su lugar');
806
+ * ```
807
+ */
808
+ function devWarn(...args) {
809
+ if (!isProductionMode) {
810
+ console.warn(...args);
811
+ }
812
+ }
813
+ /**
814
+ * Muestra errores en consola (siempre, incluso en producción)
815
+ * @param args - Argumentos a mostrar como error
816
+ *
817
+ * @example
818
+ * ```typescript
819
+ * devError('Error al cargar datos:', error);
820
+ * ```
821
+ */
822
+ function devError(...args) {
823
+ console.error(...args);
824
+ }
825
+ /**
826
+ * Crea un grupo de logs solo en modo desarrollo
827
+ * @param label - Etiqueta del grupo
828
+ * @param collapsed - Si el grupo debe estar colapsado por defecto
829
+ *
830
+ * @example
831
+ * ```typescript
832
+ * devGroup('Datos del usuario');
833
+ * devLog('Nombre:', usuario.nombre);
834
+ * devLog('Email:', usuario.email);
835
+ * devGroupEnd();
836
+ * ```
837
+ */
838
+ function devGroup(label, collapsed = false) {
839
+ if (!isProductionMode) {
840
+ if (collapsed) {
841
+ console.groupCollapsed(label);
842
+ }
843
+ else {
844
+ console.group(label);
845
+ }
846
+ }
847
+ }
848
+ /**
849
+ * Cierra el grupo de logs actual
850
+ */
851
+ function devGroupEnd() {
852
+ if (!isProductionMode) {
853
+ console.groupEnd();
854
+ }
855
+ }
856
+ /**
857
+ * Muestra una tabla en consola solo en modo desarrollo
858
+ * @param data - Datos a mostrar en formato tabla
859
+ *
860
+ * @example
861
+ * ```typescript
862
+ * devTable([
863
+ * { nombre: 'Juan', edad: 25 },
864
+ * { nombre: 'María', edad: 30 }
865
+ * ]);
866
+ * ```
867
+ */
868
+ function devTable(data) {
869
+ if (!isProductionMode) {
870
+ console.table(data);
871
+ }
872
+ }
873
+ /**
874
+ * Inicia un temporizador solo en modo desarrollo
875
+ * @param label - Etiqueta del temporizador
876
+ *
877
+ * @example
878
+ * ```typescript
879
+ * devTime('carga-datos');
880
+ * // ... código a medir
881
+ * devTimeEnd('carga-datos'); // Muestra: carga-datos: 123.45ms
882
+ * ```
883
+ */
884
+ function devTime(label) {
885
+ if (!isProductionMode) {
886
+ console.time(label);
887
+ }
888
+ }
889
+ /**
890
+ * Finaliza un temporizador y muestra el tiempo transcurrido
891
+ * @param label - Etiqueta del temporizador
892
+ */
893
+ function devTimeEnd(label) {
894
+ if (!isProductionMode) {
895
+ console.timeEnd(label);
896
+ }
897
+ }
898
+
642
899
  function maskEmail(email) {
643
900
  const [user, domain] = email.split("@");
644
901
  if (user.length <= 2) {
@@ -1446,5 +1703,5 @@ function verificarRUC(ruc) {
1446
1703
  * Generated bundle index. Do not edit.
1447
1704
  */
1448
1705
 
1449
- export { b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, changeSelectReformateado, convertirBytes, decodeBase64Object, decodeBase64String, decodeBase64ToBlob, deepClone, deepMerge, delLocalStorage, desencriptar, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encodeBase64File, encodeBase64Object, encodeBase64String, 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 };
1706
+ export { b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, changeSelectReformateado, convertirBytes, decodeBase64Object, decodeBase64String, decodeBase64ToBlob, deepClone, deepMerge, delLocalStorage, desencriptar, devError, devGroup, devGroupEnd, devLog, devTable, devTime, devTimeEnd, devWarn, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encodeBase64File, encodeBase64Object, encodeBase64String, encriptar, esNumero, esPromise, establecerQuitarRequired, extraerDominio, filtrarDatosLocal, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, getValueByPath, 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 };
1450
1707
  //# sourceMappingURL=jvsoft-utils-src-functions.mjs.map