@runnerpro/backend 1.14.7 → 1.14.9
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/lib/cjs/chat/api/conversation.js +25 -16
- package/lib/cjs/db/index.js +8 -28
- package/lib/cjs/index.js +1 -2
- package/lib/cjs/types/chat/api/conversation.d.ts.map +1 -1
- package/lib/cjs/types/db/index.d.ts +0 -2
- package/lib/cjs/types/db/index.d.ts.map +1 -1
- package/lib/cjs/types/index.d.ts +2 -2
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -77,7 +77,6 @@ const getConversation = (req, res, { isClient }) => __awaiter(void 0, void 0, vo
|
|
|
77
77
|
const reacciones = yield (0, index_1.query)('SELECT [ID], [EMOJI], [ID CHAT], [ID SENDER] FROM [CHAT MESSAGE REACCION] WHERE [ID CHAT] IN (?)', [
|
|
78
78
|
messages.map((m) => m.id),
|
|
79
79
|
]);
|
|
80
|
-
console.log({ reacciones });
|
|
81
80
|
messages = messages.reverse();
|
|
82
81
|
// 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]
|
|
83
82
|
if (header.preferredLanguage !== common_1.LANGUAGES.ES && isClient) {
|
|
@@ -202,12 +201,21 @@ const getConversationFile = (req, res, { bucket, isClient }) => __awaiter(void 0
|
|
|
202
201
|
});
|
|
203
202
|
if (!result)
|
|
204
203
|
return res.status(404).send('Not found');
|
|
205
|
-
|
|
206
|
-
'
|
|
207
|
-
'
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
if (result.message.mimetype.includes('video')) {
|
|
205
|
+
res.setHeader('Cache-Control', 'public, max-age=604800');
|
|
206
|
+
res.setHeader('Expires', new Date(Date.now() + 604800000).toUTCString());
|
|
207
|
+
res.send({
|
|
208
|
+
video: result.file.toString('base64'),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
res.writeHead(200, {
|
|
213
|
+
'Content-Type': result.message.text,
|
|
214
|
+
'Content-disposition': 'inline',
|
|
215
|
+
'Content-Length': result.file.length,
|
|
216
|
+
});
|
|
217
|
+
res.end(result.file);
|
|
218
|
+
}
|
|
211
219
|
});
|
|
212
220
|
const getChatFile = ({ bucket, id, isClient, userid }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
213
221
|
const idBBDD = id.includes('-original') ? id.replace('-original', '') : id;
|
|
@@ -281,7 +289,7 @@ const sendEmoji = (req, res, { sendNotification, firebaseMessaging, isClient })
|
|
|
281
289
|
if (isClientMessage.idCliente !== idCliente)
|
|
282
290
|
return res.send({ idReaction: null });
|
|
283
291
|
yield (0, index_1.query)('DELETE FROM [CHAT MESSAGE REACCION] WHERE [ID CHAT] = ? AND [ID SENDER] = ? AND [EMOJI] = ?', [messageId, userid, emoji]);
|
|
284
|
-
const [reaction] = yield (0, index_1.query)(
|
|
292
|
+
const [reaction] = yield (0, index_1.query)('INSERT INTO [CHAT MESSAGE REACCION] ([EMOJI], [ID CHAT], [ID SENDER]) VALUES (?, ?, ?) RETURNING [ID]', [
|
|
285
293
|
emoji,
|
|
286
294
|
messageId,
|
|
287
295
|
userid,
|
|
@@ -456,21 +464,22 @@ Actúa como un sistema automático de corrección y estandarización de texto pa
|
|
|
456
464
|
|
|
457
465
|
Sigue estas reglas estrictamente:
|
|
458
466
|
1. Corrige todos los errores ortográficos y gramaticales.
|
|
459
|
-
2. Ajusta el tono para que sea
|
|
467
|
+
2. Ajusta el tono para que sea amigable y profesional a la vez. La idea es que suene natural, no como una máquina ni excesivamente casual.
|
|
460
468
|
3. NO añadas información, ideas o frases que no estuvieran implícitas en el mensaje original. Tu trabajo es reformular, no añadir contenido.
|
|
461
|
-
4. NO
|
|
462
|
-
5. NO
|
|
463
|
-
6. NO
|
|
464
|
-
7.
|
|
469
|
+
4. NO elimines los emojis del mensaje original.
|
|
470
|
+
5. NO ofrezcas múltiples opciones.
|
|
471
|
+
6. NO incluyas explicaciones, comentarios ni viñetas.
|
|
472
|
+
7. NO uses caracteres especiales para dar estilo al texto (como * para negrita/cursiva o _). El resultado debe ser siempre texto plano.
|
|
473
|
+
8. Tu respuesta DEBE ser únicamente el texto final corregido.
|
|
465
474
|
|
|
466
475
|
---
|
|
467
476
|
**EJEMPLO 1**
|
|
468
|
-
**Texto Original:** "hey, mñn no te olvides d entrenar el hombro, no agas el vago q te veo. Y bebe awua"
|
|
469
|
-
**Texto Corregido:** "¡Hola! Para mañana, recuerda entrenar hombro. Mantén la intensidad y no olvides hidratarte."
|
|
477
|
+
**Texto Original:** "hey, mñn no te olvides d entrenar el hombro, no agas el vago q te veo. Y bebe awua 💪"
|
|
478
|
+
**Texto Corregido:** "¡Hola! Para mañana, recuerda entrenar hombro. Mantén la intensidad y no olvides hidratarte. 💪"
|
|
470
479
|
---
|
|
471
480
|
**EJEMPLO 2**
|
|
472
481
|
**Texto Original:** "Llegas tarde ala sesion de oy"
|
|
473
|
-
**Texto Corregido:** "
|
|
482
|
+
**Texto Corregido:** "Llego tarde a la sesión de hoy."
|
|
474
483
|
---
|
|
475
484
|
|
|
476
485
|
**TAREA ACTUAL**
|
package/lib/cjs/db/index.js
CHANGED
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.pool = exports.toPgArray = exports.batchQuery = exports.longRunningQuery = exports.
|
|
15
|
+
exports.pool = exports.toPgArray = exports.batchQuery = exports.longRunningQuery = exports.queryWithClient = exports.query = void 0;
|
|
16
16
|
const pg_1 = __importDefault(require("pg"));
|
|
17
17
|
const { Pool } = pg_1.default;
|
|
18
18
|
const pool = new Pool({
|
|
@@ -30,7 +30,8 @@ const pool = new Pool({
|
|
|
30
30
|
query_timeout: 30000,
|
|
31
31
|
});
|
|
32
32
|
exports.pool = pool;
|
|
33
|
-
pool.on('error', (err
|
|
33
|
+
pool.on('error', (err) => {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
34
35
|
console.error('PG pool error', err);
|
|
35
36
|
// El pool se encarga automáticamente del manejo
|
|
36
37
|
});
|
|
@@ -53,6 +54,7 @@ const query = (queryText, values = []) => __awaiter(void 0, void 0, void 0, func
|
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
catch (error) {
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
56
58
|
console.error('PG query error', error);
|
|
57
59
|
return [];
|
|
58
60
|
}
|
|
@@ -79,6 +81,7 @@ const queryWithClient = (queryText, values = [], _retry = false) => __awaiter(vo
|
|
|
79
81
|
});
|
|
80
82
|
}
|
|
81
83
|
catch (error) {
|
|
84
|
+
// eslint-disable-next-line no-console
|
|
82
85
|
console.error('PG query error', error);
|
|
83
86
|
// Liberar conexión como rota si es necesario
|
|
84
87
|
if (['EPIPE', 'ECONNRESET', '57P01', 'ECONNREFUSED'].includes(error.code)) {
|
|
@@ -99,30 +102,13 @@ const queryWithClient = (queryText, values = [], _retry = false) => __awaiter(vo
|
|
|
99
102
|
client.release();
|
|
100
103
|
}
|
|
101
104
|
catch (releaseError) {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
102
106
|
console.error('Error releasing client:', releaseError);
|
|
103
107
|
}
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
});
|
|
107
111
|
exports.queryWithClient = queryWithClient;
|
|
108
|
-
// ✅ Para transacciones - función helper
|
|
109
|
-
const transaction = (callback) => __awaiter(void 0, void 0, void 0, function* () {
|
|
110
|
-
const client = yield pool.connect();
|
|
111
|
-
try {
|
|
112
|
-
yield client.query('BEGIN');
|
|
113
|
-
const result = yield callback(client);
|
|
114
|
-
yield client.query('COMMIT');
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
yield client.query('ROLLBACK');
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
client.release();
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
exports.transaction = transaction;
|
|
126
112
|
// ✅ Batch queries optimizado con queryDirect
|
|
127
113
|
const batchQuery = (queries, batchSize = 5) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
114
|
const results = [];
|
|
@@ -135,6 +121,7 @@ const batchQuery = (queries, batchSize = 5) => __awaiter(void 0, void 0, void 0,
|
|
|
135
121
|
results.push(...batchResults);
|
|
136
122
|
}
|
|
137
123
|
catch (error) {
|
|
124
|
+
// eslint-disable-next-line no-console
|
|
138
125
|
console.error('Batch query error:', error);
|
|
139
126
|
// Continuar con el siguiente batch
|
|
140
127
|
}
|
|
@@ -212,21 +199,14 @@ function sleep(ms) {
|
|
|
212
199
|
}
|
|
213
200
|
// ✅ Manejo de cierre mejorado
|
|
214
201
|
const gracefulShutdown = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
215
|
-
console.log('Cerrando pool de conexiones...');
|
|
216
202
|
try {
|
|
217
203
|
yield pool.end();
|
|
218
|
-
console.log('PG pool cerrado correctamente');
|
|
219
204
|
}
|
|
220
205
|
catch (e) {
|
|
206
|
+
// eslint-disable-next-line no-console
|
|
221
207
|
console.error('Error cerrando PG pool', e);
|
|
222
208
|
}
|
|
223
209
|
});
|
|
224
|
-
['SIGTERM', 'SIGINT'].forEach((signal) => {
|
|
225
|
-
process.on(signal, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
226
|
-
yield gracefulShutdown();
|
|
227
|
-
process.exit(0);
|
|
228
|
-
}));
|
|
229
|
-
});
|
|
230
210
|
process.on('beforeExit', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
231
211
|
yield gracefulShutdown();
|
|
232
212
|
}));
|
package/lib/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sendPrompt = exports.saveResponseTime = exports.sendMessageChatToClient = exports.saveWorkoutAplication = exports.getPlanificacionPrueba7dias = exports.sendWorkoutToWatch = exports.getDefaultWorkoutImage = exports.generateShareMap = exports.reduceSizeImage = exports.getLetter = exports.getNumberByLetter = exports.appendSheet = exports.writeSheet = exports.findCellByValue = exports.readSheet = exports.NOTION_DATABASES_ID = exports.notionEditPage = exports.notionAddPage = exports.notionGetDatabase = exports.notionGetUsers = exports.getCountNotificaciones = exports.chatExposed = exports.chatApi = exports.chat = exports.getExerciseTranslatedDescription = exports.useTranslation = exports.LANGUAGES = exports.translate = exports.CHANNEL_SLACK = exports.notifySlack = exports.fetchIA = exports.err = exports.sendMail = exports.pool = exports.toPgArray = exports.batchQuery = exports.longRunningQuery = exports.
|
|
3
|
+
exports.sendPrompt = exports.saveResponseTime = exports.sendMessageChatToClient = exports.saveWorkoutAplication = exports.getPlanificacionPrueba7dias = exports.sendWorkoutToWatch = exports.getDefaultWorkoutImage = exports.generateShareMap = exports.reduceSizeImage = exports.getLetter = exports.getNumberByLetter = exports.appendSheet = exports.writeSheet = exports.findCellByValue = exports.readSheet = exports.NOTION_DATABASES_ID = exports.notionEditPage = exports.notionAddPage = exports.notionGetDatabase = exports.notionGetUsers = exports.getCountNotificaciones = exports.chatExposed = exports.chatApi = exports.chat = exports.getExerciseTranslatedDescription = exports.useTranslation = exports.LANGUAGES = exports.translate = exports.CHANNEL_SLACK = exports.notifySlack = exports.fetchIA = exports.err = exports.sendMail = exports.pool = exports.toPgArray = exports.batchQuery = exports.longRunningQuery = exports.queryWithClient = exports.query = exports.sleep = exports.sendNotification = void 0;
|
|
4
4
|
const sendNotification_1 = require("./sendNotification");
|
|
5
5
|
Object.defineProperty(exports, "sendNotification", { enumerable: true, get: function () { return sendNotification_1.sendNotification; } });
|
|
6
6
|
const sleep_1 = require("./sleep");
|
|
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { r
|
|
|
8
8
|
const db_1 = require("./db");
|
|
9
9
|
Object.defineProperty(exports, "query", { enumerable: true, get: function () { return db_1.query; } });
|
|
10
10
|
Object.defineProperty(exports, "queryWithClient", { enumerable: true, get: function () { return db_1.queryWithClient; } });
|
|
11
|
-
Object.defineProperty(exports, "transaction", { enumerable: true, get: function () { return db_1.transaction; } });
|
|
12
11
|
Object.defineProperty(exports, "longRunningQuery", { enumerable: true, get: function () { return db_1.longRunningQuery; } });
|
|
13
12
|
Object.defineProperty(exports, "batchQuery", { enumerable: true, get: function () { return db_1.batchQuery; } });
|
|
14
13
|
Object.defineProperty(exports, "toPgArray", { enumerable: true, get: function () { return db_1.toPgArray; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;AA4fF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -2,13 +2,11 @@ import postgresql from 'pg';
|
|
|
2
2
|
declare const pool: postgresql.Pool;
|
|
3
3
|
declare const query: (queryText: string, values?: (string | number | boolean)[]) => Promise<any>;
|
|
4
4
|
declare const queryWithClient: (queryText: string, values?: (string | number | boolean)[], _retry?: boolean) => any;
|
|
5
|
-
declare const transaction: (callback: (client: any) => Promise<any>) => Promise<any>;
|
|
6
5
|
declare const batchQuery: (queries: any[], batchSize?: number) => Promise<any[]>;
|
|
7
6
|
declare const longRunningQuery: (queryText: string, values?: (string | number | boolean)[], timeoutMs?: number) => Promise<any>;
|
|
8
7
|
declare const toPgArray: (arr: string[]) => string;
|
|
9
8
|
export { query, // ⭐ Función principal (queryDirect)
|
|
10
9
|
queryWithClient, // Para casos especiales
|
|
11
|
-
transaction, // Para transacciones
|
|
12
10
|
longRunningQuery, // Para queries pesadas
|
|
13
11
|
batchQuery, // Para lotes
|
|
14
12
|
toPgArray, // Utilidad
|
|
@@ -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;
|
|
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,iBAuB5E,CAAC;AAGF,QAAA,MAAM,eAAe,cAAqB,MAAM,WAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,0BAiDtF,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;AAkDF,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/lib/cjs/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { sendNotification } from './sendNotification';
|
|
2
2
|
import { sleep } from './sleep';
|
|
3
|
-
import { query, queryWithClient,
|
|
3
|
+
import { query, queryWithClient, longRunningQuery, batchQuery, toPgArray, pool } from './db';
|
|
4
4
|
import { sendMail } from './sendMail';
|
|
5
5
|
import { err } from './err';
|
|
6
6
|
import { fetchIA } from './fetch/fetchIA';
|
|
@@ -18,5 +18,5 @@ import { saveWorkoutAplication } from './workout/saveWorkoutAplication';
|
|
|
18
18
|
import { sendMessageChatToClient } from './chat/sendMessageChatToClient';
|
|
19
19
|
import { saveResponseTime } from './chat/saveResponseTime';
|
|
20
20
|
import { sendPrompt } from './prompt';
|
|
21
|
-
export { sendNotification, sleep, query, queryWithClient,
|
|
21
|
+
export { sendNotification, sleep, query, queryWithClient, longRunningQuery, batchQuery, toPgArray, pool, sendMail, err, fetchIA, notifySlack, CHANNEL_SLACK, translate, LANGUAGES, useTranslation, getExerciseTranslatedDescription, chat, chatApi, chatExposed, getCountNotificaciones, notionGetUsers, notionGetDatabase, notionAddPage, notionEditPage, NOTION_DATABASES_ID, readSheet, findCellByValue, writeSheet, appendSheet, getNumberByLetter, getLetter, reduceSizeImage, generateShareMap, getDefaultWorkoutImage, sendWorkoutToWatch, getPlanificacionPrueba7dias, saveWorkoutAplication, sendMessageChatToClient, saveResponseTime, sendPrompt, };
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AACvG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACjH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EACL,gBAAgB,EAChB,KAAK,EACL,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,OAAO,EACP,WAAW,EACX,aAAa,EACb,SAAS,EACT,SAAS,EACT,cAAc,EACd,gCAAgC,EAChC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,sBAAsB,EACtB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EAClB,2BAA2B,EAC3B,qBAAqB,EACrB,uBAAuB,EACvB,gBAAgB,EAChB,UAAU,GACX,CAAC"}
|