@runnerpro/backend 1.30.0 → 1.31.1
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/image/generateShareMap.js +29 -1
- package/lib/cjs/prompt/ai.js +38 -4
- package/lib/cjs/prompt/azureModel.js +27 -1
- package/lib/cjs/types/image/generateShareMap.d.ts +16 -0
- package/lib/cjs/types/image/generateShareMap.d.ts.map +1 -1
- package/lib/cjs/types/prompt/ai.d.ts.map +1 -1
- package/lib/cjs/types/prompt/azureModel.d.ts +2 -1
- package/lib/cjs/types/prompt/azureModel.d.ts.map +1 -1
- package/lib/cjs/types/workout/saveWorkoutAplication.d.ts.map +1 -1
- package/lib/cjs/workout/saveWorkoutAplication.js +11 -1
- package/package.json +2 -1
|
@@ -25,12 +25,40 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
25
25
|
// install fonts
|
|
26
26
|
canvas_1.GlobalFonts.registerFromPath(path_1.default.join(__dirname, '../../..', 'static/fonts', 'SofiaSans-Bold.ttf'), 'SofiaSansBold');
|
|
27
27
|
canvas_1.GlobalFonts.registerFromPath(path_1.default.join(__dirname, '../../..', 'static/fonts', 'SofiaSans-Regular.ttf'), 'SofiaSans');
|
|
28
|
+
/**
|
|
29
|
+
* Genera la imagen cuadrada (1080x1080) para compartir un entreno: la foto/mapa
|
|
30
|
+
* de fondo con los datos del entreno (distancia, tiempo, ritmo o desnivel) superpuestos.
|
|
31
|
+
*
|
|
32
|
+
* @param image - Buffer de la imagen de fondo (mapa del entreno o foto por defecto).
|
|
33
|
+
* @param idWorkout - ID del entreno del que se leen los datos y el idioma de su cliente.
|
|
34
|
+
* @param options - `useDefaultPhoto: true` cuando el fondo es la foto genérica (invierte el degradado superior).
|
|
35
|
+
* @returns Buffer JPEG con la imagen, o `null` si no se pudieron leer el entreno o su cliente.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const shareMap = await generateShareMap(image, idWorkout, { useDefaultPhoto: true });
|
|
40
|
+
* if (!shareMap) return; // ⚠️ SIEMPRE comprobar el null antes de subirla
|
|
41
|
+
* await bucket.file(`Workout/${idWorkout}-share`).save(shareMap);
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
28
44
|
const generateShareMap = (image, idWorkout, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
45
|
const useDefaultPhoto = (options === null || options === void 0 ? void 0 : options.useDefaultPhoto) || false;
|
|
30
46
|
const [workout] = yield (0, index_1.query)('SELECT [ID], [ID CLIENTE], [TYPE], [DISTANCE], [DURATION], [DESNIVEL] FROM [WORKOUT] WHERE [ID] = ?', [idWorkout]);
|
|
47
|
+
// ⚠️ El guard va ANTES de usar `workout`: `query` devuelve [] tanto si el entreno
|
|
48
|
+
// no existe como si la consulta falló (se traga el error y loguea 'PG query error',
|
|
49
|
+
// p.ej. client_login_timeout del pool). Leer `workout.idCliente` sin comprobarlo
|
|
50
|
+
// rompía el webhook con TypeError.
|
|
51
|
+
if (!workout) {
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
console.error(`generateShareMap: sin fila de WORKOUT para idWorkout=${idWorkout}; el entreno no existe o la consulta falló (ver 'PG query error' justo antes). No se genera la imagen de compartir.`);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
31
56
|
const [cliente] = yield (0, index_1.query)('SELECT [PREFERRED LANGUAGE] FROM [CLIENTE] WHERE [ID] = ?', [workout.idCliente]);
|
|
32
|
-
if (!
|
|
57
|
+
if (!cliente) {
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.error(`generateShareMap: sin fila de CLIENTE idCliente=${workout.idCliente} del idWorkout=${idWorkout}; el cliente no existe o la consulta falló. No se genera la imagen de compartir.`);
|
|
33
60
|
return null;
|
|
61
|
+
}
|
|
34
62
|
const width = 1080;
|
|
35
63
|
const height = 1080;
|
|
36
64
|
const canvas = (0, canvas_1.createCanvas)(width, height);
|
package/lib/cjs/prompt/ai.js
CHANGED
|
@@ -214,6 +214,38 @@ function withLaxSchemaDefaults(options) {
|
|
|
214
214
|
const po = options.providerOptions;
|
|
215
215
|
return Object.assign(Object.assign({}, options), { providerOptions: Object.assign(Object.assign({}, po), { openai: Object.assign({ strictJsonSchema: false }, po === null || po === void 0 ? void 0 : po.openai), azure: Object.assign({ strictJsonSchema: false }, po === null || po === void 0 ? void 0 : po.azure) }) });
|
|
216
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Quita `temperature` cuando el modelo que va a atender ESTA llamada la descarta.
|
|
219
|
+
*
|
|
220
|
+
* Los GPT-5.x de Azure son "reasoning models": el SDK borra `temperature` y emite un warning
|
|
221
|
+
* ("temperature is not supported for reasoning models") en CADA llamada. No rompe nada —la
|
|
222
|
+
* llamada sigue y no salta al fallback—, pero ensucia los logs del pipeline (~80 call sites
|
|
223
|
+
* pasan temperature) y hace creer que el valor se está aplicando cuando no es así.
|
|
224
|
+
*
|
|
225
|
+
* ⚠️ Se aplica POR INTENTO, no una vez al entrar: la cola de la cascada es Gemini, y ahí
|
|
226
|
+
* `temperature` SÍ se respeta. Los modelos de Google/Bedrock no llevan la etiqueta
|
|
227
|
+
* `_ignoresTemperature`, así que conservan el valor que pase el caller.
|
|
228
|
+
*
|
|
229
|
+
* @param options - Opciones tal y como se van a mandar al SDK en este intento
|
|
230
|
+
* @returns Las mismas opciones, sin `temperature` si el modelo la fuese a descartar
|
|
231
|
+
*/
|
|
232
|
+
function withoutUnsupportedTemperature(options) {
|
|
233
|
+
var _a, _b, _c;
|
|
234
|
+
const model = options.model;
|
|
235
|
+
if (!(model === null || model === void 0 ? void 0 : model._ignoresTemperature))
|
|
236
|
+
return options;
|
|
237
|
+
if (typeof options.temperature !== 'number')
|
|
238
|
+
return options;
|
|
239
|
+
// Única vía de escape del SDK: reasoningEffort 'none' en las familias que aún admiten
|
|
240
|
+
// parámetros de muestreo (5.1–5.5). Si el caller la pide, respetamos su temperature.
|
|
241
|
+
const po = options.providerOptions;
|
|
242
|
+
const reasoningEffort = (_b = (_a = po === null || po === void 0 ? void 0 : po.openai) === null || _a === void 0 ? void 0 : _a.reasoningEffort) !== null && _b !== void 0 ? _b : (_c = po === null || po === void 0 ? void 0 : po.azure) === null || _c === void 0 ? void 0 : _c.reasoningEffort;
|
|
243
|
+
if (reasoningEffort === 'none' && model._supportsNonReasoningParameters)
|
|
244
|
+
return options;
|
|
245
|
+
const rest = Object.assign({}, options);
|
|
246
|
+
delete rest.temperature;
|
|
247
|
+
return rest;
|
|
248
|
+
}
|
|
217
249
|
function generateObject(options) {
|
|
218
250
|
var _a;
|
|
219
251
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -236,7 +268,7 @@ function generateObject(options) {
|
|
|
236
268
|
let fallbackIdx = 0;
|
|
237
269
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
238
270
|
try {
|
|
239
|
-
const { object, usage } = yield (0, ai_1.generateObject)(currentOptions);
|
|
271
|
+
const { object, usage } = yield (0, ai_1.generateObject)(withoutUnsupportedTemperature(currentOptions));
|
|
240
272
|
const modelName = extractModelName(currentOptions.model);
|
|
241
273
|
const cost = (0, modelPricing_1.calculateCost)(modelName, usage === null || usage === void 0 ? void 0 : usage.inputTokens, usage === null || usage === void 0 ? void 0 : usage.outputTokens);
|
|
242
274
|
const tracker = costTrackingStorage.getStore();
|
|
@@ -397,7 +429,7 @@ function generateText(options) {
|
|
|
397
429
|
let fallbackIdx = 0;
|
|
398
430
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
399
431
|
try {
|
|
400
|
-
const { text, usage } = yield (0, ai_1.generateText)(currentOptions);
|
|
432
|
+
const { text, usage } = yield (0, ai_1.generateText)(withoutUnsupportedTemperature(currentOptions));
|
|
401
433
|
const modelName = extractModelName(currentOptions.model);
|
|
402
434
|
const cost = (0, modelPricing_1.calculateCost)(modelName, usage === null || usage === void 0 ? void 0 : usage.inputTokens, usage === null || usage === void 0 ? void 0 : usage.outputTokens);
|
|
403
435
|
const cleanResult = yield ensureNoChainOfThought({ rawText: text, baseCost: cost, originalOptions: options, modelLabel: modelName });
|
|
@@ -459,9 +491,11 @@ function ensureNoChainOfThought(params) {
|
|
|
459
491
|
const accumulatedCost = Object.assign({}, baseCost);
|
|
460
492
|
const baseTemperature = typeof originalOptions.temperature === 'number' ? originalOptions.temperature : 0.7;
|
|
461
493
|
const retryTemperature = Math.min(1, baseTemperature + 0.1);
|
|
462
|
-
// Paso 2: retry con system anti-CoT y temperatura ligeramente superior
|
|
494
|
+
// Paso 2: retry con system anti-CoT y temperatura ligeramente superior.
|
|
495
|
+
// En los reasoning models de Azure el empujón de temperatura no llega a aplicarse (el SDK la
|
|
496
|
+
// descarta), así que allí lo que desatasca el retry es únicamente el `system` reforzado.
|
|
463
497
|
try {
|
|
464
|
-
const { text: retryText, usage: retryUsage } = yield (0, ai_1.generateText)(Object.assign(Object.assign({}, originalOptions), { system: buildAntiCotSystem(originalOptions.system), temperature: retryTemperature }));
|
|
498
|
+
const { text: retryText, usage: retryUsage } = yield (0, ai_1.generateText)(withoutUnsupportedTemperature(Object.assign(Object.assign({}, originalOptions), { system: buildAntiCotSystem(originalOptions.system), temperature: retryTemperature })));
|
|
465
499
|
const retryModelLabel = extractModelName(originalOptions.model);
|
|
466
500
|
const retryCost = (0, modelPricing_1.calculateCost)(retryModelLabel, retryUsage === null || retryUsage === void 0 ? void 0 : retryUsage.inputTokens, retryUsage === null || retryUsage === void 0 ? void 0 : retryUsage.outputTokens);
|
|
467
501
|
accumulatedCost.inputTokens = (accumulatedCost.inputTokens || 0) + (retryCost.inputTokens || 0);
|
|
@@ -20,10 +20,34 @@ function getAzureProvider() {
|
|
|
20
20
|
const baseURL = process.env.AZURE_BASE_URL;
|
|
21
21
|
return (0, azure_1.createAzure)(Object.assign(Object.assign({ apiKey: process.env.AZURE_API_KEY }, (baseURL ? { baseURL } : { resourceName: process.env.AZURE_RESOURCE_NAME })), (apiVersion ? { apiVersion } : {})));
|
|
22
22
|
}
|
|
23
|
+
// Prefijos de razonamiento que NO son de la familia gpt-5 (esa se trata aparte por la
|
|
24
|
+
// excepción de gpt-5-chat, que es el único gpt-5* conversacional).
|
|
25
|
+
const OPENAI_REASONING_PREFIXES = ['o1', 'o3', 'o4-mini'];
|
|
26
|
+
// Familias que recuperan los parámetros de muestreo si se pide `reasoningEffort: 'none'`.
|
|
27
|
+
// ⚠️ La 5.6 NO está en la lista: en terra/luna `temperature` se descarta siempre, pase lo
|
|
28
|
+
// que pase. Réplica de `supportsNonReasoningParameters` en @ai-sdk/openai.
|
|
29
|
+
const NON_REASONING_PARAM_PREFIXES = ['gpt-5.1', 'gpt-5.2', 'gpt-5.3', 'gpt-5.4', 'gpt-5.5'];
|
|
30
|
+
/**
|
|
31
|
+
* Indica si el SDK va a tratar el deployment como "reasoning model" y, por tanto, va a
|
|
32
|
+
* DESCARTAR `temperature` y `topP` antes de llamar (avisando con un warning por llamada).
|
|
33
|
+
*
|
|
34
|
+
* Réplica de `getOpenAILanguageModelCapabilities` de @ai-sdk/openai: los modelos `.responses()`
|
|
35
|
+
* de @ai-sdk/azure comparten ese parser, así que la regla aplica igual a los deployments de Azure.
|
|
36
|
+
* Los DeepSeek quedan fuera a propósito (no empiezan por gpt-5/o*), que es justo lo que hace el SDK.
|
|
37
|
+
*
|
|
38
|
+
* @param deploymentName - Nombre del deployment (ej: 'gpt-5.6-terra')
|
|
39
|
+
* @returns true si el SDK descartará los parámetros de muestreo
|
|
40
|
+
*/
|
|
41
|
+
function isReasoningDeployment(deploymentName) {
|
|
42
|
+
if (deploymentName.startsWith('gpt-5'))
|
|
43
|
+
return !deploymentName.startsWith('gpt-5-chat');
|
|
44
|
+
return OPENAI_REASONING_PREFIXES.some((prefix) => deploymentName.startsWith(prefix));
|
|
45
|
+
}
|
|
23
46
|
/**
|
|
24
47
|
* Crea una instancia del modelo de Azure OpenAI a partir del nombre del deployment.
|
|
25
48
|
* Etiqueta el objeto con _productionModelName (nombre limpio, sin el prefijo "azure:")
|
|
26
|
-
* para el cálculo de costes
|
|
49
|
+
* para el cálculo de costes, y con _ignoresTemperature / _supportsNonReasoningParameters
|
|
50
|
+
* para que `generateObject`/`generateText` no manden `temperature` a un modelo que la descarta.
|
|
27
51
|
*
|
|
28
52
|
* @param deploymentName - Nombre del deployment en Azure (ej: 'gpt-5')
|
|
29
53
|
* @returns Instancia del modelo de Azure compatible con AI SDK
|
|
@@ -42,6 +66,8 @@ function createAzureModelFromString(deploymentName) {
|
|
|
42
66
|
const model = azure.responses(deploymentName);
|
|
43
67
|
model._productionModelName = deploymentName;
|
|
44
68
|
model._fallbackModelNames = [];
|
|
69
|
+
model._ignoresTemperature = isReasoningDeployment(deploymentName);
|
|
70
|
+
model._supportsNonReasoningParameters = NON_REASONING_PARAM_PREFIXES.some((prefix) => deploymentName.startsWith(prefix));
|
|
45
71
|
return model;
|
|
46
72
|
}
|
|
47
73
|
exports.createAzureModelFromString = createAzureModelFromString;
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* Genera la imagen cuadrada (1080x1080) para compartir un entreno: la foto/mapa
|
|
4
|
+
* de fondo con los datos del entreno (distancia, tiempo, ritmo o desnivel) superpuestos.
|
|
5
|
+
*
|
|
6
|
+
* @param image - Buffer de la imagen de fondo (mapa del entreno o foto por defecto).
|
|
7
|
+
* @param idWorkout - ID del entreno del que se leen los datos y el idioma de su cliente.
|
|
8
|
+
* @param options - `useDefaultPhoto: true` cuando el fondo es la foto genérica (invierte el degradado superior).
|
|
9
|
+
* @returns Buffer JPEG con la imagen, o `null` si no se pudieron leer el entreno o su cliente.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const shareMap = await generateShareMap(image, idWorkout, { useDefaultPhoto: true });
|
|
14
|
+
* if (!shareMap) return; // ⚠️ SIEMPRE comprobar el null antes de subirla
|
|
15
|
+
* await bucket.file(`Workout/${idWorkout}-share`).save(shareMap);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
2
18
|
declare const generateShareMap: (image: any, idWorkout: any, options?: {}) => Promise<Buffer>;
|
|
3
19
|
export { generateShareMap };
|
|
4
20
|
//# sourceMappingURL=generateShareMap.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateShareMap.d.ts","sourceRoot":"","sources":["../../../../src/image/generateShareMap.ts"],"names":[],"mappings":";AAcA,QAAA,MAAM,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"generateShareMap.d.ts","sourceRoot":"","sources":["../../../../src/image/generateShareMap.ts"],"names":[],"mappings":";AAcA;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,gBAAgB,+DA+BrB,CAAC;AA0HF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAmPhE,iBAAe,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAoD/H;AAkFD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,iBAAe,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CA4C5H;AAmFD;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAe,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB5H;AAED,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Crea una instancia del modelo de Azure OpenAI a partir del nombre del deployment.
|
|
3
3
|
* Etiqueta el objeto con _productionModelName (nombre limpio, sin el prefijo "azure:")
|
|
4
|
-
* para el cálculo de costes
|
|
4
|
+
* para el cálculo de costes, y con _ignoresTemperature / _supportsNonReasoningParameters
|
|
5
|
+
* para que `generateObject`/`generateText` no manden `temperature` a un modelo que la descarta.
|
|
5
6
|
*
|
|
6
7
|
* @param deploymentName - Nombre del deployment en Azure (ej: 'gpt-5')
|
|
7
8
|
* @returns Instancia del modelo de Azure compatible con AI SDK
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azureModel.d.ts","sourceRoot":"","sources":["../../../../src/prompt/azureModel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"azureModel.d.ts","sourceRoot":"","sources":["../../../../src/prompt/azureModel.ts"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;GAcG;AACH,iBAAS,0BAA0B,CAAC,cAAc,EAAE,MAAM,GAAG,GAAG,CAW/D;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saveWorkoutAplication.d.ts","sourceRoot":"","sources":["../../../../src/workout/saveWorkoutAplication.ts"],"names":[],"mappings":"AAuTA;;;;;;;;;;GAUG;AACH,QAAA,MAAM,qBAAqB,SACnB,GAAG,UAED,GAAG,KACV,QAAQ,MAAM,GAAG,IAAI,CA6EvB,CAAC;
|
|
1
|
+
{"version":3,"file":"saveWorkoutAplication.d.ts","sourceRoot":"","sources":["../../../../src/workout/saveWorkoutAplication.ts"],"names":[],"mappings":"AAuTA;;;;;;;;;;GAUG;AACH,QAAA,MAAM,qBAAqB,SACnB,GAAG,UAED,GAAG,KACV,QAAQ,MAAM,GAAG,IAAI,CA6EvB,CAAC;AA+EF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -384,7 +384,13 @@ const postHooks = (idWorkout, opts) => __awaiter(void 0, void 0, void 0, functio
|
|
|
384
384
|
catch (_) {
|
|
385
385
|
// Un fallo de Mapbox no debe romper la ingesta (estado ya persistido).
|
|
386
386
|
}
|
|
387
|
-
|
|
387
|
+
try {
|
|
388
|
+
yield saveShareWorkoutImage(idWorkout, opts.type);
|
|
389
|
+
}
|
|
390
|
+
catch (_) {
|
|
391
|
+
// La imagen de compartir es accesoria: si falla (Storage, canvas, BD) no debe
|
|
392
|
+
// romper la ingesta ni escapar como unhandled rejection (así llegaba a Sentry).
|
|
393
|
+
}
|
|
388
394
|
yield (0, estructuraWorkout_1.saveDoneStructuraWorkout)(idWorkout);
|
|
389
395
|
// Logros: evaluar al completar el entreno (este es el embudo de los entrenos
|
|
390
396
|
// sincronizados). Se pasa el idWorkout para calcular el PR solo de ESTE entreno
|
|
@@ -438,6 +444,10 @@ const saveShareWorkoutImage = (id, type) => __awaiter(void 0, void 0, void 0, fu
|
|
|
438
444
|
else
|
|
439
445
|
[image] = yield storage.bucket(process.env.CLOUD_STORAGE_BUCKET_PUBLIC).file(`Workout/${id}`).download();
|
|
440
446
|
const shareMap = yield (0, generateShareMap_1.generateShareMap)(image, id);
|
|
447
|
+
// generateShareMap devuelve null si no pudo leer el entreno o su cliente (ya deja
|
|
448
|
+
// traza del motivo): sin imagen no hay nada que subir ni URL que guardar.
|
|
449
|
+
if (!shareMap)
|
|
450
|
+
return;
|
|
441
451
|
// @ts-ignore
|
|
442
452
|
yield storage.bucket(process.env.CLOUD_STORAGE_BUCKET_PUBLIC).file(`Workout/${id}-share`).save(shareMap);
|
|
443
453
|
const urlShare = `https://storage.googleapis.com/${process.env.CLOUD_STORAGE_BUCKET_PUBLIC}/Workout/${id}-share`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runnerpro/backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.1",
|
|
4
4
|
"description": "A collection of common backend functions",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/cjs/index.js"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"semantic-release": "semantic-release",
|
|
18
18
|
"lint": "eslint --ext .ts --ignore-path .gitignore .",
|
|
19
19
|
"test:translate-workout-garmin": "ts-node --transpile-only scripts/translateWorkoutGarmin.ts",
|
|
20
|
+
"test:generate-share-map-guard": "ts-node --transpile-only -P configs/tsconfig.cjs.json scripts/testGenerateShareMapGuard.ts",
|
|
20
21
|
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
21
22
|
"prepare": "husky"
|
|
22
23
|
},
|