From 713a9638b5b0b91484b6cc0286e3fa0202313b39 Mon Sep 17 00:00:00 2001 From: shahjahan-arif Date: Sat, 21 Mar 2026 01:05:47 +0500 Subject: [PATCH 1/2] fix(engine): resolve lint-staged and json path typing --- package.json | 6 +- project.json | 38 ++++++++ .../channel/meta/whatsapp.business.service.ts | 2 +- .../whatsapp/whatsapp.baileys.service.ts | 88 +++++++++++++------ .../chatwoot/services/chatwoot.service.ts | 8 +- src/api/services/channel.service.ts | 16 ++-- src/utils/onWhatsappCache.ts | 13 +-- 7 files changed, 119 insertions(+), 52 deletions(-) create mode 100644 project.json diff --git a/package.json b/package.json index 56e32fcc8..a7aa0e829 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "start:prod": "node dist/main", "dev:server": "tsx watch ./src/main.ts", "test": "tsx watch ./test/all.test.ts", - "lint": "eslint --fix --ext .ts src", - "lint:check": "eslint --ext .ts src", + "lint": "ESLINT_USE_FLAT_CONFIG=false eslint --fix --ext .ts src", + "lint:check": "ESLINT_USE_FLAT_CONFIG=false eslint --ext .ts src", "commit": "cz", "commitlint": "commitlint --edit", "db:generate": "node runWithProvider.js \"npx prisma generate --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", @@ -53,7 +53,7 @@ "homepage": "https://github.com/EvolutionAPI/evolution-api#readme", "lint-staged": { "src/**/*.{ts,js}": [ - "eslint --fix" + "sh -c 'ESLINT_USE_FLAT_CONFIG=false eslint --fix'" ], "src/**/*.ts": [ "sh -c 'tsc --noEmit'" diff --git a/project.json b/project.json new file mode 100644 index 000000000..591349ffe --- /dev/null +++ b/project.json @@ -0,0 +1,38 @@ +{ + "name": "engine", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/engine/src", + "projectType": "application", + "prefix": "engine", + "targets": { + "serve": { + "executor": "nx:run-commands", + "options": { + "command": "npm run dev:server", + "cwd": "apps/engine" + } + }, + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npm run build", + "cwd": "apps/engine" + } + }, + "db:migrate": { + "executor": "nx:run-commands", + "options": { + "command": "npm run db:deploy", + "cwd": "apps/engine" + } + }, + "db:seed": { + "executor": "nx:run-commands", + "options": { + "command": "npm run db:seed", + "cwd": "apps/engine" + } + } + }, + "tags": ["type:app", "scope:engine"] +} diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index 1e4808c15..42e54d6bc 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -758,7 +758,7 @@ export class BusinessStartupService extends ChannelStartupService { where: { instanceId: this.instanceId, key: { - path: ['id'], + path: '$.id', equals: key.id, }, }, diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 60e857fcc..021abea9a 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -1819,7 +1819,7 @@ export class BaileysStartupService extends ChannelStartupService { const savedLabel = labelsRepository.find((l) => l.labelId === label.id); if (label.deleted && savedLabel) { await this.prismaRepository.label.delete({ - where: { labelId_instanceId: { instanceId: this.instanceId, labelId: label.id } }, + where: { id: savedLabel.id }, }); this.sendDataWebhook(Events.LABELS_EDIT, { ...label, instance: this.instance.name }); return; @@ -1835,11 +1835,16 @@ export class BaileysStartupService extends ChannelStartupService { predefinedId: label.predefinedId, instanceId: this.instanceId, }; - await this.prismaRepository.label.upsert({ - where: { labelId_instanceId: { instanceId: labelData.instanceId, labelId: labelData.labelId } }, - update: labelData, - create: labelData, - }); + if (savedLabel) { + await this.prismaRepository.label.update({ + where: { id: savedLabel.id }, + data: labelData, + }); + } else { + await this.prismaRepository.label.create({ + data: labelData, + }); + } } } }, @@ -3776,7 +3781,7 @@ export class BaileysStartupService extends ChannelStartupService { if (messageId) { const isLogicalDeleted = configService.get('DATABASE').DELETE_DATA.LOGICAL_MESSAGE_DELETE; let message = await this.prismaRepository.message.findFirst({ - where: { key: { path: ['id'], equals: messageId } }, + where: { key: { path: '$.id', equals: messageId } }, }); if (isLogicalDeleted) { if (!message) return response; @@ -4196,7 +4201,7 @@ export class BaileysStartupService extends ChannelStartupService { const messageId = messageSent.message?.protocolMessage?.key?.id; if (messageId && this.configService.get('DATABASE').SAVE_DATA.NEW_MESSAGE) { let message = await this.prismaRepository.message.findFirst({ - where: { key: { path: ['id'], equals: messageId } }, + where: { key: { path: '$.id', equals: messageId } }, }); if (!message) throw new NotFoundException('Message not found'); @@ -4734,6 +4739,26 @@ export class BaileysStartupService extends ChannelStartupService { private async updateMessagesReadedByTimestamp(remoteJid: string, timestamp?: number): Promise { if (timestamp === undefined || timestamp === null) return 0; + const dbProvider = String(this.configService.get('DATABASE')?.PROVIDER || '').toLowerCase(); + + if (dbProvider === 'mysql') { + const result = await this.prismaRepository.$executeRaw` + UPDATE \`Message\` + SET \`status\` = ${status[4]} + WHERE \`instanceId\` = ${this.instanceId} + AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.remoteJid')) = ${remoteJid} + AND JSON_EXTRACT(\`key\`, '$.fromMe') = false + AND \`messageTimestamp\` <= ${timestamp} + AND (\`status\` IS NULL OR \`status\` = ${status[3]}) + `; + + if (result && result > 0) { + this.updateChatUnreadMessages(remoteJid); + } + + return result || 0; + } + // Use raw SQL to avoid JSON path issues const result = await this.prismaRepository.$executeRaw` UPDATE "Message" @@ -4757,16 +4782,25 @@ export class BaileysStartupService extends ChannelStartupService { } private async updateChatUnreadMessages(remoteJid: string): Promise { + const dbProvider = String(this.configService.get('DATABASE')?.PROVIDER || '').toLowerCase(); + const [chat, unreadMessages] = await Promise.all([ this.prismaRepository.chat.findFirst({ where: { remoteJid } }), - // Use raw SQL to avoid JSON path issues - this.prismaRepository.$queryRaw` - SELECT COUNT(*)::int as count FROM "Message" - WHERE "instanceId" = ${this.instanceId} - AND "key"->>'remoteJid' = ${remoteJid} - AND ("key"->>'fromMe')::boolean = false - AND "status" = ${status[3]} - `.then((result: any[]) => result[0]?.count || 0), + dbProvider === 'mysql' + ? this.prismaRepository.$queryRaw` + SELECT COUNT(*) as count FROM \`Message\` + WHERE \`instanceId\` = ${this.instanceId} + AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.remoteJid')) = ${remoteJid} + AND JSON_EXTRACT(\`key\`, '$.fromMe') = false + AND \`status\` = ${status[3]} + `.then((result: any[]) => Number(result?.[0]?.count || 0)) + : this.prismaRepository.$queryRaw` + SELECT COUNT(*)::int as count FROM "Message" + WHERE "instanceId" = ${this.instanceId} + AND "key"->>'remoteJid' = ${remoteJid} + AND ("key"->>'fromMe')::boolean = false + AND "status" = ${status[3]} + `.then((result: any[]) => result[0]?.count || 0), ]); if (chat && chat.unreadMessages !== unreadMessages) { @@ -5013,7 +5047,7 @@ export class BaileysStartupService extends ChannelStartupService { } } - public async fetchMessages(query: Query) { + public async fetchMessages(query: Query): Promise { const keyFilters = query?.where?.key as ExtendedIMessageKey; const timestampFilter = {}; @@ -5034,13 +5068,13 @@ export class BaileysStartupService extends ChannelStartupService { messageType: query?.where?.messageType, ...timestampFilter, AND: [ - keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {}, - keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {}, - keyFilters?.participant ? { key: { path: ['participant'], equals: keyFilters?.participant } } : {}, + keyFilters?.id ? { key: { path: '$.id', equals: keyFilters?.id } } : {}, + keyFilters?.fromMe ? { key: { path: '$.fromMe', equals: keyFilters?.fromMe } } : {}, + keyFilters?.participant ? { key: { path: '$.participant', equals: keyFilters?.participant } } : {}, { OR: [ - keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {}, - keyFilters?.remoteJidAlt ? { key: { path: ['remoteJidAlt'], equals: keyFilters?.remoteJidAlt } } : {}, + keyFilters?.remoteJid ? { key: { path: '$.remoteJid', equals: keyFilters?.remoteJid } } : {}, + keyFilters?.remoteJidAlt ? { key: { path: '$.remoteJidAlt', equals: keyFilters?.remoteJidAlt } } : {}, ], }, ], @@ -5063,13 +5097,13 @@ export class BaileysStartupService extends ChannelStartupService { messageType: query?.where?.messageType, ...timestampFilter, AND: [ - keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {}, - keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {}, - keyFilters?.participant ? { key: { path: ['participant'], equals: keyFilters?.participant } } : {}, + keyFilters?.id ? { key: { path: '$.id', equals: keyFilters?.id } } : {}, + keyFilters?.fromMe ? { key: { path: '$.fromMe', equals: keyFilters?.fromMe } } : {}, + keyFilters?.participant ? { key: { path: '$.participant', equals: keyFilters?.participant } } : {}, { OR: [ - keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {}, - keyFilters?.remoteJidAlt ? { key: { path: ['remoteJidAlt'], equals: keyFilters?.remoteJidAlt } } : {}, + keyFilters?.remoteJid ? { key: { path: '$.remoteJid', equals: keyFilters?.remoteJid } } : {}, + keyFilters?.remoteJidAlt ? { key: { path: '$.remoteJidAlt', equals: keyFilters?.remoteJidAlt } } : {}, ], }, ], diff --git a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts index 906fff188..af18da4cd 100644 --- a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts @@ -1546,7 +1546,7 @@ export class ChatwootService { const lastMessage = await this.prismaRepository.message.findFirst({ where: { key: { - path: ['fromMe'], + path: '$.fromMe', equals: false, }, instanceId: instance.instanceId, @@ -1576,7 +1576,7 @@ export class ChatwootService { where: { instanceId: instance.instanceId, key: { - path: ['id'], + path: '$.id', equals: key.id, }, }, @@ -2025,7 +2025,7 @@ export class ChatwootService { quotedMsg = await this.prismaRepository.message.findFirst({ where: { key: { - path: ['id'], + path: '$.id', equals: quotedId, }, chatwootMessageId: { @@ -2337,7 +2337,7 @@ export class ChatwootService { await this.prismaRepository.message.deleteMany({ where: { key: { - path: ['id'], + path: '$.id', equals: body.key.id, }, instanceId: instance.instanceId, diff --git a/src/api/services/channel.service.ts b/src/api/services/channel.service.ts index 56bec0802..27891c133 100644 --- a/src/api/services/channel.service.ts +++ b/src/api/services/channel.service.ts @@ -623,10 +623,10 @@ export class ChannelStartupService { messageType: query?.where?.messageType, ...timestampFilter, AND: [ - keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {}, - keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {}, - keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {}, - keyFilters?.participants ? { key: { path: ['participants'], equals: keyFilters?.participants } } : {}, + keyFilters?.id ? { key: { path: '$.id', equals: keyFilters?.id } } : {}, + keyFilters?.fromMe ? { key: { path: '$.fromMe', equals: keyFilters?.fromMe } } : {}, + keyFilters?.remoteJid ? { key: { path: '$.remoteJid', equals: keyFilters?.remoteJid } } : {}, + keyFilters?.participants ? { key: { path: '$.participants', equals: keyFilters?.participants } } : {}, ], }, }); @@ -647,10 +647,10 @@ export class ChannelStartupService { messageType: query?.where?.messageType, ...timestampFilter, AND: [ - keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {}, - keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {}, - keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {}, - keyFilters?.participants ? { key: { path: ['participants'], equals: keyFilters?.participants } } : {}, + keyFilters?.id ? { key: { path: '$.id', equals: keyFilters?.id } } : {}, + keyFilters?.fromMe ? { key: { path: '$.fromMe', equals: keyFilters?.fromMe } } : {}, + keyFilters?.remoteJid ? { key: { path: '$.remoteJid', equals: keyFilters?.remoteJid } } : {}, + keyFilters?.participants ? { key: { path: '$.participants', equals: keyFilters?.participants } } : {}, ], }, orderBy: { diff --git a/src/utils/onWhatsappCache.ts b/src/utils/onWhatsappCache.ts index 08de0714e..be3c8a777 100644 --- a/src/utils/onWhatsappCache.ts +++ b/src/utils/onWhatsappCache.ts @@ -126,12 +126,9 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) { // Ordena os JIDs para garantir consistência na string final const sortedJidOptions = [...finalJidOptions].sort(); const newJidOptionsString = sortedJidOptions.join(','); - const newLid = item.lid === 'lid' || item.remoteJid?.includes('@lid') ? 'lid' : null; - const dataPayload = { remoteJid: remoteJid, jidOptions: newJidOptionsString, - lid: newLid, }; // 4. Decide entre Criar ou Atualizar @@ -142,9 +139,7 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) { : ''; const isDataSame = - existingRecord.remoteJid === dataPayload.remoteJid && - existingJidOptionsString === dataPayload.jidOptions && - existingRecord.lid === dataPayload.lid; + existingRecord.remoteJid === dataPayload.remoteJid && existingJidOptionsString === dataPayload.jidOptions; if (isDataSame) { logger.verbose(`[saveOnWhatsappCache] Data for ${remoteJid} is already up-to-date. Skipping update.`); @@ -153,7 +148,7 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) { // Os dados são diferentes, então atualiza logger.verbose( - `[saveOnWhatsappCache] Register exists, updating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}, lid=${dataPayload.lid}`, + `[saveOnWhatsappCache] Register exists, updating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}`, ); await prismaRepository.isOnWhatsapp.update({ where: { id: existingRecord.id }, @@ -162,7 +157,7 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) { } else { // Cria nova entrada logger.verbose( - `[saveOnWhatsappCache] Register does not exist, creating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}, lid=${dataPayload.lid}`, + `[saveOnWhatsappCache] Register does not exist, creating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}`, ); await prismaRepository.isOnWhatsapp.create({ data: dataPayload, @@ -203,7 +198,7 @@ export async function getOnWhatsappCache(remoteJids: string[]) { remoteJid: item.remoteJid, number: item.remoteJid.split('@')[0], jidOptions: item.jidOptions.split(','), - lid: item.lid, + lid: (item as any).lid || (item.remoteJid.includes('@lid') ? 'lid' : undefined), })); } From b99625e97a4ccde576d866d0a207c28e11709690 Mon Sep 17 00:00:00 2001 From: shahjahan-arif Date: Sun, 5 Apr 2026 03:13:47 +0500 Subject: [PATCH 2/2] chore: update env config and examples --- .env.example | 6 + env.example | 4 + grafana-dashboard.json.example | 238 --------------------------------- package.json | 22 +-- src/config/env.config.ts | 24 +++- 5 files changed, 43 insertions(+), 251 deletions(-) delete mode 100644 grafana-dashboard.json.example diff --git a/.env.example b/.env.example index 73a3b40d3..8e13b6440 100644 --- a/.env.example +++ b/.env.example @@ -348,6 +348,12 @@ EVOAI_ENABLED=false # Redis Cache enabled CACHE_REDIS_ENABLED=true CACHE_REDIS_URI=redis://localhost:6379/6 +# Local machine Redis settings (used when NODE_ENV is not PROD) +CACHE_REDIS_LOCAL_ENABLED=true +CACHE_REDIS_LOCAL_URI=redis://localhost:6379/6 +# Production Redis settings (used when NODE_ENV=PROD) +CACHE_REDIS_PRODUCTION_ENABLED=true +CACHE_REDIS_PRODUCTION_URI=redis://your-production-redis:6379/6 CACHE_REDIS_TTL=604800 # Prefix serves to differentiate data from one installation to another that are using the same redis CACHE_REDIS_PREFIX_KEY=evolution diff --git a/env.example b/env.example index 5fe448b82..387123abd 100644 --- a/env.example +++ b/env.example @@ -49,6 +49,10 @@ DATABASE_DELETE_MESSAGE=false # =========================================== CACHE_REDIS_ENABLED=true CACHE_REDIS_URI=redis://localhost:6379 +CACHE_REDIS_LOCAL_ENABLED=true +CACHE_REDIS_LOCAL_URI=redis://localhost:6379 +CACHE_REDIS_PRODUCTION_ENABLED=true +CACHE_REDIS_PRODUCTION_URI=redis://your-production-redis:6379 CACHE_REDIS_PREFIX_KEY=evolution-cache CACHE_REDIS_TTL=604800 CACHE_REDIS_SAVE_INSTANCES=true diff --git a/grafana-dashboard.json.example b/grafana-dashboard.json.example deleted file mode 100644 index f85eb9d6c..000000000 --- a/grafana-dashboard.json.example +++ /dev/null @@ -1,238 +0,0 @@ -{ - "dashboard": { - "id": null, - "title": "Evolution API Monitoring", - "tags": ["evolution-api", "whatsapp", "monitoring"], - "style": "dark", - "timezone": "browser", - "panels": [ - { - "id": 1, - "title": "API Status", - "type": "stat", - "targets": [ - { - "expr": "up{job=\"evolution-api\"}", - "legendFormat": "API Status" - } - ], - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "0": { - "text": "DOWN", - "color": "red" - }, - "1": { - "text": "UP", - "color": "green" - } - }, - "type": "value" - } - ] - } - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - } - }, - { - "id": 2, - "title": "Total Instances", - "type": "stat", - "targets": [ - { - "expr": "evolution_instances_total", - "legendFormat": "Total Instances" - } - ], - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - } - }, - { - "id": 3, - "title": "Instance Status Overview", - "type": "piechart", - "targets": [ - { - "expr": "sum by (state) (evolution_instance_state)", - "legendFormat": "{{ state }}" - } - ], - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 8 - } - }, - { - "id": 4, - "title": "Instances by Integration Type", - "type": "piechart", - "targets": [ - { - "expr": "sum by (integration) (evolution_instance_up)", - "legendFormat": "{{ integration }}" - } - ], - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 8 - } - }, - { - "id": 5, - "title": "Instance Uptime", - "type": "table", - "targets": [ - { - "expr": "evolution_instance_up", - "format": "table", - "instant": true - } - ], - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "__name__": true - }, - "renameByName": { - "instance": "Instance Name", - "integration": "Integration Type", - "Value": "Status" - } - } - } - ], - "fieldConfig": { - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Status" - }, - "properties": [ - { - "id": "mappings", - "value": [ - { - "options": { - "0": { - "text": "DOWN", - "color": "red" - }, - "1": { - "text": "UP", - "color": "green" - } - }, - "type": "value" - } - ] - } - ] - } - ] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 17 - } - }, - { - "id": 6, - "title": "Instance Status Timeline", - "type": "timeseries", - "targets": [ - { - "expr": "evolution_instance_up", - "legendFormat": "{{ instance }} ({{ integration }})" - } - ], - "fieldConfig": { - "defaults": { - "custom": { - "drawStyle": "line", - "lineInterpolation": "stepAfter", - "lineWidth": 2, - "fillOpacity": 10, - "gradientMode": "none", - "spanNulls": false, - "insertNulls": false, - "showPoints": "never", - "pointSize": 5, - "stacking": { - "mode": "none", - "group": "A" - }, - "axisPlacement": "auto", - "axisLabel": "", - "scaleDistribution": { - "type": "linear" - }, - "hideFrom": { - "legend": false, - "tooltip": false, - "vis": false - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "min": 0, - "max": 1 - } - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 26 - } - } - ], - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "templating": { - "list": [] - }, - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "refresh": "30s", - "schemaVersion": 27, - "version": 0, - "links": [] - } -} diff --git a/package.json b/package.json index a7aa0e829..dc3207954 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "test": "tsx watch ./test/all.test.ts", "lint": "ESLINT_USE_FLAT_CONFIG=false eslint --fix --ext .ts src", "lint:check": "ESLINT_USE_FLAT_CONFIG=false eslint --ext .ts src", - "commit": "cz", "commitlint": "commitlint --edit", "db:generate": "node runWithProvider.js \"npx prisma generate --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", "db:deploy": "node runWithProvider.js \"rm -rf ./prisma/migrations && cp -r ./prisma/DATABASE_PROVIDER-migrations ./prisma/migrations && npx prisma migrate deploy --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", @@ -59,17 +58,20 @@ "sh -c 'tsc --noEmit'" ] }, - "config": { - "commitizen": { - "path": "cz-conventional-changelog" - } - }, "dependencies": { "@adiwajshing/keyed-db": "^0.2.4", "@aws-sdk/client-sqs": "^3.891.0", "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@figuro/chatwoot-sdk": "^1.1.16", + "@figuro/chatwoot-sdk": "^1.1.17", "@hapi/boom": "^10.0.1", + "@nestjs/swagger": "^11.2.6", + "@nx/eslint": "^22.6.3", + "@nx/eslint-plugin": "^22.6.3", + "@nx/jest": "^22.6.3", + "@nx/playwright": "^22.6.3", + "@nx/vite": "^22.6.3", + "@nx/web": "^22.6.3", + "@nx/webpack": "^22.6.3", "@paralleldrive/cuid2": "^2.2.2", "@prisma/client": "^6.16.2", "@sentry/node": "^10.12.0", @@ -77,7 +79,7 @@ "amqplib": "^0.10.5", "audio-decode": "^2.2.3", "axios": "^1.7.9", - "baileys": "7.0.0-rc.9", + "baileys": "^6.7.21", "class-validator": "^0.14.1", "compression": "^1.7.5", "cors": "^2.8.5", @@ -87,10 +89,10 @@ "eventemitter2": "^6.4.9", "express": "^4.21.2", "express-async-errors": "^3.1.1", + "fetch-socks": "^1.3.2", "fluent-ffmpeg": "^2.1.3", "form-data": "^4.0.1", "https-proxy-agent": "^7.0.6", - "fetch-socks": "^1.3.2", "i18next": "^23.7.19", "jimp": "^1.6.0", "json-schema": "^0.4.0", @@ -141,8 +143,6 @@ "@types/qrcode-terminal": "^0.12.2", "@typescript-eslint/eslint-plugin": "^8.44.0", "@typescript-eslint/parser": "^8.44.0", - "commitizen": "^4.3.1", - "cz-conventional-changelog": "^3.3.0", "eslint": "^8.45.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "^2.31.0", diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 7c4e382e7..2eaa469bd 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -454,6 +454,26 @@ export class ConfigService { } private envProcess(): Env { + const isProductionMode = process.env?.NODE_ENV === 'PROD'; + + const redisEnabledFallback = process.env?.CACHE_REDIS_ENABLED === 'true'; + const redisLocalEnabled = process.env?.CACHE_REDIS_LOCAL_ENABLED === 'true'; + const redisProductionEnabled = process.env?.CACHE_REDIS_PRODUCTION_ENABLED === 'true'; + + const redisUriFallback = process.env?.CACHE_REDIS_URI || ''; + const redisLocalUri = process.env?.CACHE_REDIS_LOCAL_URI || redisUriFallback; + const redisProductionUri = process.env?.CACHE_REDIS_PRODUCTION_URI || redisUriFallback; + + const selectedRedisEnabled = isProductionMode + ? process.env?.CACHE_REDIS_PRODUCTION_ENABLED + ? redisProductionEnabled + : redisEnabledFallback + : process.env?.CACHE_REDIS_LOCAL_ENABLED + ? redisLocalEnabled + : redisEnabledFallback; + + const selectedRedisUri = isProductionMode ? redisProductionUri : redisLocalUri; + return { SERVER: { NAME: process.env?.SERVER_NAME || 'evolution', @@ -841,8 +861,8 @@ export class ConfigService { }, CACHE: { REDIS: { - ENABLED: process.env?.CACHE_REDIS_ENABLED === 'true', - URI: process.env?.CACHE_REDIS_URI || '', + ENABLED: selectedRedisEnabled, + URI: selectedRedisUri, PREFIX_KEY: process.env?.CACHE_REDIS_PREFIX_KEY || 'evolution-cache', TTL: Number.parseInt(process.env?.CACHE_REDIS_TTL) || 604800, SAVE_INSTANCES: process.env?.CACHE_REDIS_SAVE_INSTANCES === 'true',