@runnerpro/backend 1.19.1 → 1.19.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.
package/README.md CHANGED
@@ -63,20 +63,3 @@ Wait X miliseconds to execute next line
63
63
  3. Change the version number of the package ([using this convenction](https://docs.npmjs.com/about-semantic-versioning))
64
64
  4. Run `npm login`
65
65
  5. Run `npm run publish`
66
-
67
- ### Testing
68
-
69
- 1. Install developer dependencies using the following command in your terminal `npm i -D mocha @types/mocha chai @types/chai ts-node`
70
- 1. Create a new file `.mocharc.json` in the root directory with the following contents:
71
- ```json
72
- {
73
- "extension": ["ts"],
74
- "spec": "./**/*.spec.ts",
75
- "require": "ts-node/register"
76
- }
77
- ```
78
- 1. Create a `tests` folder
79
- 1. Create an `index.spec.ts` file in the `tests` folder
80
- 1. Write unit tests in the `index.spec.ts` file to test the code in `index.ts`
81
- 1. Add a `"test"` property in the `package.json` file and give it a value of `"mocha"`
82
- 1. Run `npm test` in your terminal from the root folder of the project
@@ -66,23 +66,23 @@ exports.conversationRoute = conversationRoute;
66
66
  const getConversation = (req, res, { isClient }) => __awaiter(void 0, void 0, void 0, function* () {
67
67
  const idCliente = isClient ? req.session.userid : req.query.id;
68
68
  const [header] = yield (0, index_1.query)('SELECT [NAME], [PREFERRED LANGUAGE] FROM [CLIENTE] WHERE [ID] = ?', [idCliente]);
69
- let messages = yield (0, index_1.query)(`SELECT "CHAT MESSAGE".*,
70
- "WORKOUT"."DATE" AS "WORKOUT DATE", "WORKOUT"."TYPE" AS "WORKOUT TYPE", "WORKOUT"."TITLE" AS "WORKOUT TITLE", "WORKOUT"."TITLE PREFERRED LANGUAGE" AS "WORKOUT TITLE",
71
- "WORKOUT"."DURATION" AS "WORKOUT DURATION", "WORKOUT"."DISTANCE" AS "WORKOUT DISTANCE", "WORKOUT"."RESUMEN" AS "WORKOUT RESUMEN",
72
- "WORKOUT"."PHOTO URL SHARE" AS "WORKOUT PHOTO URL SHARE", "WORKOUT"."PHOTO URL" AS "WORKOUT PHOTO URL", "FEELINGS", "FEELINGS DESCRIPTION", "FEELINGS PACE", "FEELINGS PACE VALUE",
73
- "ENTRENADOR"."NAME" AS "ENTRENADOR NAME", "ENTRENADOR"."PHOTO" AS "ENTRENADOR PHOTO",
74
- (SELECT "NAME" FROM "ENTRENADOR" WHERE "ID" = "CHAT MESSAGE"."ID SENDER") AS "ENTRENADOR REAL NAME"
75
- FROM "CHAT MESSAGE"
76
- LEFT JOIN "WORKOUT" ON "WORKOUT"."ID" = "CHAT MESSAGE"."ID WORKOUT"
77
- LEFT JOIN "CLIENTE" ON "CLIENTE"."ID" = "CHAT MESSAGE"."ID CLIENTE"
78
- LEFT JOIN "ENTRENADOR" ON "ENTRENADOR"."ID" = COALESCE("CHAT MESSAGE"."ID SENDER VIEW", "CLIENTE"."ID ENTRENADOR PRINCIPAL")
79
- AND "CHAT MESSAGE"."ID CLIENTE" != "CHAT MESSAGE"."ID SENDER"
80
- WHERE "CHAT MESSAGE"."ID CLIENTE" = ? AND (${isClient} = FALSE OR "CHAT MESSAGE"."SHOW CLIENT" = TRUE)
81
- ORDER BY "CHAT MESSAGE"."DATE" DESC
69
+ let messages = yield (0, index_1.query)(`SELECT "CHAT MESSAGE".*,
70
+ "WORKOUT"."DATE" AS "WORKOUT DATE", "WORKOUT"."TYPE" AS "WORKOUT TYPE", "WORKOUT"."TITLE" AS "WORKOUT TITLE", "WORKOUT"."TITLE PREFERRED LANGUAGE" AS "WORKOUT TITLE",
71
+ "WORKOUT"."DURATION" AS "WORKOUT DURATION", "WORKOUT"."DISTANCE" AS "WORKOUT DISTANCE", "WORKOUT"."RESUMEN" AS "WORKOUT RESUMEN",
72
+ "WORKOUT"."PHOTO URL SHARE" AS "WORKOUT PHOTO URL SHARE", "WORKOUT"."PHOTO URL" AS "WORKOUT PHOTO URL", "FEELINGS", "FEELINGS DESCRIPTION", "FEELINGS PACE", "FEELINGS PACE VALUE",
73
+ "ENTRENADOR"."NAME" AS "ENTRENADOR NAME", "ENTRENADOR"."PHOTO" AS "ENTRENADOR PHOTO",
74
+ (SELECT "NAME" FROM "ENTRENADOR" WHERE "ID" = "CHAT MESSAGE"."ID SENDER") AS "ENTRENADOR REAL NAME"
75
+ FROM "CHAT MESSAGE"
76
+ LEFT JOIN "WORKOUT" ON "WORKOUT"."ID" = "CHAT MESSAGE"."ID WORKOUT"
77
+ LEFT JOIN "CLIENTE" ON "CLIENTE"."ID" = "CHAT MESSAGE"."ID CLIENTE"
78
+ LEFT JOIN "ENTRENADOR" ON "ENTRENADOR"."ID" = COALESCE("CHAT MESSAGE"."ID SENDER VIEW", "CLIENTE"."ID ENTRENADOR PRINCIPAL")
79
+ AND "CHAT MESSAGE"."ID CLIENTE" != "CHAT MESSAGE"."ID SENDER"
80
+ WHERE "CHAT MESSAGE"."ID CLIENTE" = ? AND (${isClient} = FALSE OR "CHAT MESSAGE"."SHOW CLIENT" = TRUE)
81
+ ORDER BY "CHAT MESSAGE"."DATE" DESC
82
82
  LIMIT 100`, [idCliente]);
83
- const reacciones = messages.length > 0 ? yield (0, index_1.query)('SELECT [ID], [EMOJI], [ID CHAT], [ID SENDER] FROM [CHAT MESSAGE REACCION] WHERE [ID CHAT] IN (?)', [
84
- messages.map((m) => m.id),
85
- ]) : [];
83
+ const reacciones = messages.length > 0
84
+ ? yield (0, index_1.query)('SELECT [ID], [EMOJI], [ID CHAT], [ID SENDER] FROM [CHAT MESSAGE REACCION] WHERE [ID CHAT] IN (?)', [messages.map((m) => m.id)])
85
+ : [];
86
86
  messages = messages.reverse();
87
87
  // Si el cliente no habla español, se muestran los mensajes en el idioma del cliente. El entrenador siempre ve los mensajes en español que están en la columna [TEXT]
88
88
  if (header.preferredLanguage !== common_1.LANGUAGES.ES && isClient) {
@@ -577,9 +577,34 @@ const markReadMessage = ({ isClient, idCliente }) => __awaiter(void 0, void 0, v
577
577
  if (!isClient)
578
578
  yield (0, saveResponseTime_1.saveResponseTime)(idCliente);
579
579
  });
580
+ const EMOJI_REGEX = /\p{Extended_Pictographic}/gu;
580
581
  /**
581
- * Corrige la ortografía del texto y adapta español latinoamericano a español de España
582
- * NO modifica el tono, significado ni estructura de las frases
582
+ * Elimina de forma determinista los emojis que aparecen en `corregido` pero no estaban en `original`.
583
+ * Respeta la cantidad exacta de cada emoji del texto original.
584
+ *
585
+ * @param original - Texto antes de la corrección
586
+ * @param corregido - Texto después de la corrección (puede contener emojis añadidos por el modelo)
587
+ * @returns Texto corregido sin emojis nuevos
588
+ */
589
+ const eliminarEmojisNuevos = (original, corregido) => {
590
+ const emojisOriginales = original.match(EMOJI_REGEX) || [];
591
+ const inventario = new Map();
592
+ for (const emoji of emojisOriginales) {
593
+ inventario.set(emoji, (inventario.get(emoji) || 0) + 1);
594
+ }
595
+ return corregido.replace(EMOJI_REGEX, (emoji) => {
596
+ const count = inventario.get(emoji) || 0;
597
+ if (count > 0) {
598
+ inventario.set(emoji, count - 1);
599
+ return emoji;
600
+ }
601
+ return '';
602
+ });
603
+ };
604
+ /**
605
+ * Corrige la ortografía del texto y adapta español latinoamericano a español de España.
606
+ * NO modifica el tono, significado ni estructura de las frases.
607
+ * Garantiza que no se añadan emojis nuevos respecto al texto original.
583
608
  *
584
609
  * @param text - Texto a corregir
585
610
  * @returns Promise<string> - Texto con ortografía corregida
@@ -594,17 +619,18 @@ const corregirOrtografia = (text) => __awaiter(void 0, void 0, void 0, function*
594
619
  try {
595
620
  let { text: textCorregido } = yield (0, prompt_1.generateText)({
596
621
  model: (0, prompt_1.createGoogleModel)('LITE'),
597
- system: `Actúa como un corrector de estilo nativo de España (castellano).
598
- Instrucciones estrictas:
599
- - Vocabulario: Sustituye términos latinos por sus equivalentes en España (ej: celular -> móvil, computadora -> ordenador, video -> vídeo, costo -> coste, chequear -> comprobar, entreno -> entrenamiento).
600
- - Ortografía: Corrige cualquier falta ortográfica o de acentuación.
601
- - URLs: Copia los links exactos. NO los abras, NO los leas y NO añadas resúmenes.
602
- - Formato: Entrega texto plano y limpio. NO uses asteriscos (*), negritas, ni símbolos de Markdown. Solo texto y emojis.
603
- - Tono: Mantén la energía y la intención del entrenador, pero asegúrate de que suene 100% nativo de España.
604
-
622
+ system: `Actúa como un corrector de estilo nativo de España (castellano).
623
+ Instrucciones estrictas:
624
+ - Vocabulario: Sustituye términos latinos por sus equivalentes en España (ej: celular -> móvil, computadora -> ordenador, video -> vídeo, costo -> coste, chequear -> comprobar, entreno -> entrenamiento).
625
+ - Ortografía: Corrige cualquier falta ortográfica o de acentuación.
626
+ - URLs: Copia los links exactos. NO los abras, NO los leas y NO añadas resúmenes.
627
+ - Formato: Entrega texto plano y limpio. NO uses asteriscos (*), negritas, ni símbolos de Markdown. Solo texto y emojis.
628
+ - Tono: Mantén la energía y la intención del entrenador, pero asegúrate de que suene 100% nativo de España.
629
+
605
630
  Devuelve SOLO el texto corregido final.`,
606
631
  prompt: text,
607
632
  });
633
+ textCorregido = eliminarEmojisNuevos(text, textCorregido);
608
634
  textCorregido = textCorregido.replace(/[¡¿]/g, '');
609
635
  textCorregido = textCorregido.trim().replace(/\.$/, '');
610
636
  return textCorregido;
@@ -20,13 +20,12 @@ const pool = new Pool({
20
20
  database: process.env.DB_NAME,
21
21
  password: process.env.DB_PASSWORD,
22
22
  host: process.env.DB_HOST,
23
- port: 5432,
24
- max: 10,
23
+ port: Number(process.env.DB_PORT) || 5432,
24
+ max: 20,
25
25
  idleTimeoutMillis: 30000,
26
26
  connectionTimeoutMillis: 30000, // Aumentado a 30 segundos
27
27
  keepAlive: true,
28
28
  keepAliveInitialDelayMillis: 0,
29
- statement_timeout: 30000, // Timeout para queries
30
29
  query_timeout: 30000,
31
30
  });
32
31
  exports.pool = pool;
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;AA0EF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,uBAAuB,qCAAkC,GAAG,iBAwCjE,CAAC;AAmGF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,WAAW,0EAAuE,GAAG,kBAkE1F,CAAC;AAEF,QAAA,MAAM,gBAAgB;;;;mBAqBrB,CAAC;AAqRF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;AA2EF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,uBAAuB,qCAAkC,GAAG,iBAwCjE,CAAC;AAmGF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,WAAW,0EAAuE,GAAG,kBAkE1F,CAAC;AAEF,QAAA,MAAM,gBAAgB;;;;mBAqBrB,CAAC;AAkTF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,IAAI,CAAC;AAI5B,QAAA,MAAM,IAAI,iBAaR,CAAC;AASH,QAAA,MAAM,KAAK,cAAqB,MAAM,WAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,iBAyB5E,CAAC;AAGF,QAAA,MAAM,eAAe,cAAqB,MAAM,WAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,0BAmDtF,CAAC;AAGF,QAAA,MAAM,UAAU,YAAmB,GAAG,EAAE,uCAmBvC,CAAC;AAGF,QAAA,MAAM,gBAAgB,cACT,MAAM,WACT,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,qCAyBtC,CAAC;AAGF,QAAA,MAAM,SAAS,QAAS,MAAM,EAAE,WAM/B,CAAC;AAoJF,OAAO,EACL,KAAK,EAAE,oCAAoC;AAC3C,eAAe,EAAE,wBAAwB;AACzC,gBAAgB,EAAE,uBAAuB;AACzC,UAAU,EAAE,aAAa;AACzB,SAAS,EAAE,WAAW;AACtB,IAAI,GACL,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,IAAI,CAAC;AAI5B,QAAA,MAAM,IAAI,iBAYR,CAAC;AASH,QAAA,MAAM,KAAK,cAAqB,MAAM,WAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,iBAyB5E,CAAC;AAGF,QAAA,MAAM,eAAe,cAAqB,MAAM,WAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,0BAmDtF,CAAC;AAGF,QAAA,MAAM,UAAU,YAAmB,GAAG,EAAE,uCAmBvC,CAAC;AAGF,QAAA,MAAM,gBAAgB,cACT,MAAM,WACT,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,qCAyBtC,CAAC;AAGF,QAAA,MAAM,SAAS,QAAS,MAAM,EAAE,WAM/B,CAAC;AAoJF,OAAO,EACL,KAAK,EAAE,oCAAoC;AAC3C,eAAe,EAAE,wBAAwB;AACzC,gBAAgB,EAAE,uBAAuB;AACzC,UAAU,EAAE,aAAa;AACzB,SAAS,EAAE,WAAW;AACtB,IAAI,GACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runnerpro/backend",
3
- "version": "1.19.1",
3
+ "version": "1.19.4",
4
4
  "description": "A collection of common backend functions",
5
5
  "exports": {
6
6
  ".": "./lib/cjs/index.js"
@@ -17,8 +17,7 @@
17
17
  "semantic-release": "semantic-release",
18
18
  "lint": "eslint --ext .ts --ignore-path .gitignore .",
19
19
  "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
20
- "prepare": "husky",
21
- "test": "jest"
20
+ "prepare": "husky"
22
21
  },
23
22
  "release": {
24
23
  "branches": [
@@ -37,7 +36,6 @@
37
36
  "devDependencies": {
38
37
  "@eslint/js": "^9.6.0",
39
38
  "@types/eslint__js": "^8.42.3",
40
- "@types/jest": "^30.0.0",
41
39
  "@types/nodemailer": "^6.4.15",
42
40
  "@types/pg": "^8.11.3",
43
41
  "del-cli": "5.1.0",
@@ -47,9 +45,7 @@
47
45
  "eslint-plugin-exception-handling": "^1.0.2",
48
46
  "eslint-plugin-sonarjs": "^1.0.3",
49
47
  "husky": "^9.0.11",
50
- "jest": "^29.7.0",
51
48
  "semantic-release": "23.0.2",
52
- "ts-jest": "^29.4.6",
53
49
  "ts-node": "10.9.2",
54
50
  "typescript": "5.3.3",
55
51
  "typescript-eslint": "^7.15.0"