@gnpdev/rpa-tools 1.0.17 → 1.0.19

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/README.md CHANGED
@@ -92,9 +92,25 @@ if (credentials) {
92
92
  }
93
93
  ```
94
94
 
95
- ### 4. Capturas de Pantalla bajo demanda (Playwright)
96
- Activa el watcher pasando la instancia de `page`. El bot detectará cambios en la tabla de la DB para tomar screenshots automáticamente.
95
+ ### 4. Verificar Estado del Bot (Kill Switch)
96
+ Permite consultar si el bot debe seguir en ejecución según la base de datos (columna `estado` en `bots.tb_bots`). Útil para implementar una parada de emergencia desde el panel de control.
97
97
 
98
+ ```javascript
99
+ import { rpa, logger } from './lib/rpa.js';
100
+
101
+ const active = await rpa.isActive();
102
+
103
+ if (!active) {
104
+ logger.warn('El bot ha sido desactivado desde la base de datos. Finalizando...');
105
+ await rpa.destroy();
106
+ process.exit(0);
107
+ }
108
+ ```
109
+
110
+ ### 5. Capturas de Pantalla bajo demanda (Playwright / Puppeteer)
111
+ Activa el watcher pasando la instancia de `page`. El bot detectará cambios en la tabla de la DB para tomar screenshots automáticamente. Compatible con ambos motores.
112
+
113
+ #### Ejemplo con Playwright
98
114
  ```javascript
99
115
  import { chromium } from 'playwright';
100
116
  import { rpa } from './lib/rpa.js';
@@ -102,20 +118,25 @@ import { rpa } from './lib/rpa.js';
102
118
  const browser = await chromium.launch();
103
119
  const page = await browser.newPage();
104
120
 
105
- // Inicia el monitoreo (polling cada 3s por defecto)
106
121
  rpa.watchDebugFlag(page);
122
+ ```
107
123
 
124
+ #### Ejemplo con Puppeteer
125
+ ```javascript
126
+ import puppeteer from 'puppeteer';
127
+ import { rpa } from './lib/rpa.js';
108
128
 
109
- // Al terminar el proceso del bot
110
- rpa.destroy();
129
+ const browser = await puppeteer.launch();
130
+ const page = await browser.newPage();
111
131
 
112
- // Sugerencia: limpiar al desconectar
113
- browser.on('disconnected', () => rpa.destroy());
132
+ rpa.watchDebugFlag(page);
114
133
  ```
115
134
 
116
- ### 5. Captura Automática de Errores (Screenshot + Trace)
135
+ ### 6. Captura Automática de Errores (Screenshot + Trace)
117
136
  Captura el estado completo del bot cuando ocurre una excepción. **`captureError` detecta automáticamente el paso actual** definido con `step()`.
118
137
 
138
+ > **Nota:** El soporte de `tracing` (archivos .zip de depuración) es exclusivo de **Playwright**. En **Puppeteer** se capturará el error y el screenshot, pero el `traceKey` será nulo.
139
+
119
140
  ```javascript
120
141
  import { chromium } from 'playwright';
121
142
  import { rpa, logger, step } from './lib/rpa.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gnpdev/rpa-tools",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Libreria para logs y screenshot de bots",
5
5
  "author": "Sergio Antonio Trujillo del Valle",
6
6
  "main": "src/index.js",
@@ -35,13 +35,13 @@ function errorPrefix(botId) {
35
35
 
36
36
  /**
37
37
  * Captura el estado completo cuando ocurre un error:
38
- * - Screenshot WebP de la página actual
39
- * - Trace de Playwright (.zip con video, red, consola, DOM snapshots)
38
+ * - Screenshot WebP de la página actual (Playwright/Puppeteer)
39
+ * - Trace de Playwright (.zip con video, red, consola, DOM snapshots) [Opcional]
40
40
  * - Registro en bots.tb_error_bots
41
41
  *
42
42
  * @param {object} p
43
- * @param {import('playwright').Page} p.page
44
- * @param {import('playwright').BrowserContext} p.context
43
+ * @param {any} p.page - Instancia de Page (Playwright o Puppeteer)
44
+ * @param {any} [p.context] - BrowserContext (solo Playwright para tracing)
45
45
  * @param {Error} p.err
46
46
  * @param {string} p.botId - UUID del bot
47
47
  * @param {import('pg').Pool} p.pool
package/src/index.d.ts CHANGED
@@ -74,6 +74,12 @@ export interface RpaTools {
74
74
  */
75
75
  getCredentials: (nombre: string) => Promise<{ usuario: string; password: string; idUsuario: string } | null>;
76
76
 
77
+ /**
78
+ * Consulta si el bot está activo en la base de datos (columna 'estado').
79
+ * @returns {Promise<boolean>}
80
+ */
81
+ isActive: () => Promise<boolean>;
82
+
77
83
  /**
78
84
  * Captura screenshot, trace y registra error en base de datos.
79
85
  */
package/src/index.js CHANGED
@@ -14,7 +14,7 @@ const { captureError } = require('./errorCapture');
14
14
  * @param {object} opts.minio - config de MinIO
15
15
  * @param {object} [opts.log] - opciones de Pino
16
16
  *
17
- * @returns {{ logger, watchDebugFlag, getCredentials, destroy }}
17
+ * @returns {{ logger, state, step, watchDebugFlag, getCredentials, isActive, captureError, destroy }}
18
18
  */
19
19
  async function createRpaTools(opts = {}) {
20
20
  const {
@@ -55,8 +55,33 @@ async function createRpaTools(opts = {}) {
55
55
  state.currentStep = name;
56
56
  logger.info(name + ' - Nuevo paso');
57
57
  },
58
+ /**
59
+ * Inicia el polling que activa/desactiva screenshots según bot_debug_config.
60
+ * @param {any} page - Objeto Page de Playwright o Puppeteer
61
+ * @param {number} [pollMs=3000] - Intervalo de polling en ms
62
+ */
58
63
  watchDebugFlag: (page, pollMs) => watcher.watch(page, pollMs),
59
64
  getCredentials: (nombre) => credentials.getAppCredentials(nombre),
65
+ /**
66
+ * Consulta si el bot está activo en la base de datos (columna 'estado').
67
+ * @returns {Promise<boolean>}
68
+ */
69
+ isActive: async () => {
70
+ try {
71
+ const { rows } = await db.query(
72
+ 'SELECT estado FROM bots.tb_bots WHERE id = $1',
73
+ [botId]
74
+ );
75
+ return rows.length > 0 ? rows[0].estado : false;
76
+ } catch (err) {
77
+ logger.error({ err }, 'Error consultando estado en isActive');
78
+ return false;
79
+ }
80
+ },
81
+ /**
82
+ * Captura screenshot y registra error en base de datos.
83
+ * Soporta Playwright (con tracing opcional) y Puppeteer.
84
+ */
60
85
  captureError: ({ page, context, err, step }) => captureError({
61
86
  page,
62
87
  context,
package/src/watcher.js CHANGED
@@ -1,137 +1,139 @@
1
- 'use strict';
2
- const { uploadScreenshot } = require('./storage');
3
-
4
- class ScreenshotWatcher {
5
- /**
6
- * @param {object} p
7
- * @param {string} p.botId
8
- * @param {import('pg').Pool} p.pool
9
- * @param {import('minio').Client} p.minioClient
10
- * @param {string} p.bucket
11
- * @param {import('pino').Logger} p.logger
12
- * @param {object} [p.screenshot]
13
- * @param {'webp'|'jpeg'} [p.screenshot.format='webp']
14
- * @param {number} [p.screenshot.quality=70] - calidad conversión 1-100
15
- * @param {number} [p.screenshot.captureQuality=90] - calidad captura Playwright
16
- */
17
- constructor({ botId, pool, minioClient, bucket, logger, screenshot = {} }) {
18
- this.botId = botId;
19
- this.pool = pool;
20
- this.minioClient = minioClient;
21
- this.bucket = bucket;
22
- this.logger = logger;
23
-
24
- this.screenshotOpts = {
25
- format: screenshot.format ?? 'webp',
26
- quality: screenshot.quality ?? 70,
27
- captureQuality: screenshot.captureQuality ?? 90,
28
- };
29
-
30
- this._watchTimer = null;
31
- this._shotTimer = null;
32
- }
33
-
34
- /**
35
- * Inicia el polling que activa/desactiva screenshots según bot_debug_config.
36
- * Llama una sola vez al arrancar el bot.
37
- *
38
- * @param {import('playwright').Page} page
39
- * @param {number} [pollMs=3000] - cada cuántos ms revisar la BD
40
- */
41
- watch(page, pollMs = 3000) {
42
- if (this._watchTimer) {
43
- this.logger.warn('ScreenshotWatcher ya está corriendo, ignorando llamada duplicada');
44
- return;
45
- }
46
-
47
- this.logger.info({ pollMs }, 'Iniciando polling de debug config');
48
-
49
- this._watchTimer = setInterval(async () => {
50
- try {
51
- const { rows } = await this.pool.query(
52
- `SELECT screenshots_activo, intervalo_sec
53
- FROM bots.tb_bots
54
- WHERE id = $1`,
55
- [this.botId]
56
- );
57
-
58
- const cfg = rows[0];
59
- // console.log('DEBUG CONFIG', cfg); // <-- loguear config para debug
60
-
61
- if (!cfg) {
62
- this.logger.debug('Sin config en bot_debug_config para este bot');
63
- return;
64
- }
65
-
66
- if (cfg.screenshots_activo && !this._shotTimer) {
67
- this.logger.info({ intervalSec: cfg.intervalo_sec }, 'Screenshots activados');
68
- this._startScreenshots(page, cfg.intervalo_sec * 1000);
69
- return;
70
- }
71
-
72
- if (!cfg.screenshots_activo && this._shotTimer) {
73
- this.logger.info('Screenshots desactivados');
74
- this._stopScreenshots();
75
- }
76
- } catch (err) {
77
- this.logger.error({ err }, 'Error leyendo bot_debug_config');
78
- }
79
- }, pollMs);
80
- }
81
-
82
- /**
83
- * @private
84
- */
85
- _startScreenshots(page, intervalMs) {
86
- this._shotTimer = setInterval(async () => {
87
- const t0 = Date.now();
88
-
89
- try {
90
- // Playwright captura en jpeg (más rápido), sharp convierte a WebP después
91
- const rawBuffer = await page.screenshot({
92
- type: 'jpeg',
93
- quality: this.screenshotOpts.captureQuality,
94
- fullPage: false,
95
- });
96
-
97
- const key = await uploadScreenshot(
98
- this.minioClient,
99
- this.bucket,
100
- this.botId,
101
- rawBuffer,
102
- {
103
- format: this.screenshotOpts.format,
104
- quality: this.screenshotOpts.quality,
105
- }
106
- );
107
-
108
- this.logger.debug(
109
- { key, ms: Date.now() - t0 },
110
- 'Screenshot subido'
111
- );
112
- } catch (err) {
113
- this.logger.error({ err }, 'Error capturando o subiendo screenshot');
114
- }
115
- }, intervalMs);
116
- }
117
-
118
- /**
119
- * @private
120
- */
121
- _stopScreenshots() {
122
- clearInterval(this._shotTimer);
123
- this._shotTimer = null;
124
- }
125
-
126
- /**
127
- * Detiene todos los intervalos. Llamar siempre al cerrar el bot.
128
- */
129
- destroy() {
130
- this._stopScreenshots();
131
- clearInterval(this._watchTimer);
132
- this._watchTimer = null;
133
- this.logger.info('ScreenshotWatcher destruido');
134
- }
135
- }
136
-
1
+ 'use strict';
2
+ const { uploadScreenshot } = require('./storage');
3
+
4
+ class ScreenshotWatcher {
5
+ /**
6
+ * @param {object} p
7
+ * @param {string} p.botId
8
+ * @param {import('pg').Pool} p.pool
9
+ * @param {import('minio').Client} p.minioClient
10
+ * @param {string} p.bucket
11
+ * @param {import('pino').Logger} p.logger
12
+ * @param {object} [p.screenshot]
13
+ * @param {'webp'|'jpeg'} [p.screenshot.format='webp']
14
+ * @param {number} [p.screenshot.quality=70] - calidad conversión 1-100
15
+ * @param {number} [p.screenshot.captureQuality=90] - calidad captura Playwright
16
+ */
17
+ constructor({ botId, pool, minioClient, bucket, logger, screenshot = {} }) {
18
+ this.botId = botId;
19
+ this.pool = pool;
20
+ this.minioClient = minioClient;
21
+ this.bucket = bucket;
22
+ this.logger = logger;
23
+
24
+ this.screenshotOpts = {
25
+ format: screenshot.format ?? 'webp',
26
+ quality: screenshot.quality ?? 70,
27
+ captureQuality: screenshot.captureQuality ?? 90,
28
+ };
29
+
30
+ this._watchTimer = null;
31
+ this._shotTimer = null;
32
+ }
33
+
34
+ /**
35
+ * Inicia el polling que activa/desactiva screenshots según bot_debug_config.
36
+ * Llama una sola vez al arrancar el bot.
37
+ *
38
+ * @param {any} page - Objeto Page de Playwright o Puppeteer
39
+ * @param {number} [pollMs=3000] - cada cuántos ms revisar la BD
40
+ */
41
+ watch(page, pollMs = 3000) {
42
+ if (this._watchTimer) {
43
+ this.logger.warn('ScreenshotWatcher ya está corriendo, ignorando llamada duplicada');
44
+ return;
45
+ }
46
+
47
+ this.logger.info({ pollMs }, 'Iniciando polling de debug config');
48
+
49
+ this._watchTimer = setInterval(async () => {
50
+ try {
51
+ const { rows } = await this.pool.query(
52
+ `SELECT screenshots_activo, intervalo_sec
53
+ FROM bots.tb_bots
54
+ WHERE id = $1`,
55
+ [this.botId]
56
+ );
57
+
58
+ const cfg = rows[0];
59
+ // console.log('DEBUG CONFIG', cfg); // <-- loguear config para debug
60
+
61
+ if (!cfg) {
62
+ this.logger.debug('Sin config en bot_debug_config para este bot');
63
+ return;
64
+ }
65
+
66
+ if (cfg.screenshots_activo && !this._shotTimer) {
67
+ this.logger.info({ intervalSec: cfg.intervalo_sec }, 'Screenshots activados');
68
+ this._startScreenshots(page, cfg.intervalo_sec * 1000);
69
+ return;
70
+ }
71
+
72
+ if (!cfg.screenshots_activo && this._shotTimer) {
73
+ this.logger.info('Screenshots desactivados');
74
+ this._stopScreenshots();
75
+ }
76
+ } catch (err) {
77
+ this.logger.error({ err }, 'Error leyendo bot_debug_config');
78
+ }
79
+ }, pollMs);
80
+ }
81
+
82
+ /**
83
+ * @private
84
+ */
85
+ _startScreenshots(page, intervalMs) {
86
+ this._shotTimer = setInterval(async () => {
87
+ const t0 = Date.now();
88
+
89
+ try {
90
+ // Playwright captura en jpeg (más rápido), sharp convierte a WebP después
91
+ const rawBuffer = await page.screenshot({
92
+ type: 'jpeg',
93
+ quality: this.screenshotOpts.captureQuality,
94
+ fullPage: false,
95
+ });
96
+
97
+ const key = await uploadScreenshot(
98
+ this.minioClient,
99
+ this.bucket,
100
+ this.botId,
101
+ rawBuffer,
102
+ {
103
+ format: this.screenshotOpts.format,
104
+ quality: this.screenshotOpts.quality,
105
+ pool: this.pool,
106
+ logger: this.logger,
107
+ }
108
+ );
109
+
110
+ this.logger.debug(
111
+ { key, ms: Date.now() - t0 },
112
+ 'Screenshot subido'
113
+ );
114
+ } catch (err) {
115
+ this.logger.error({ err }, 'Error capturando o subiendo screenshot');
116
+ }
117
+ }, intervalMs);
118
+ }
119
+
120
+ /**
121
+ * @private
122
+ */
123
+ _stopScreenshots() {
124
+ clearInterval(this._shotTimer);
125
+ this._shotTimer = null;
126
+ }
127
+
128
+ /**
129
+ * Detiene todos los intervalos. Llamar siempre al cerrar el bot.
130
+ */
131
+ destroy() {
132
+ this._stopScreenshots();
133
+ clearInterval(this._watchTimer);
134
+ this._watchTimer = null;
135
+ this.logger.info('ScreenshotWatcher destruido');
136
+ }
137
+ }
138
+
137
139
  module.exports = { ScreenshotWatcher };