From d61ad95a3df83b18042a38792e9f19e11a423894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Let=C3=ADcia=20Zalasik?= Date: Fri, 30 Aug 2024 16:56:05 -0300 Subject: [PATCH 1/7] =?UTF-8?q?Cria=C3=A7=C3=A3o=20do=20entidade,=20do=20r?= =?UTF-8?q?eposit=C3=B3rio=20e=20da=20service=20para=20o=20alert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/database/entities/alert.entity.ts | 25 +++++++++++++++++++ .../alert/repository/alerts.repository.ts | 20 +++++++++++++++ src/modules/alert/service/alerts.service.ts | 19 ++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/database/entities/alert.entity.ts create mode 100644 src/modules/alert/repository/alerts.repository.ts create mode 100644 src/modules/alert/service/alerts.service.ts diff --git a/src/database/entities/alert.entity.ts b/src/database/entities/alert.entity.ts new file mode 100644 index 0000000..c31857c --- /dev/null +++ b/src/database/entities/alert.entity.ts @@ -0,0 +1,25 @@ +import { + Column, + Entity, + PrimaryGeneratedColumn, + ManyToOne, + JoinColumn, + } from 'typeorm'; + import { UsersEntity } from './users.entity'; + + @Entity('tb_alerts') + export class AlertEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + keyword: string; + + @Column() + location: string; + + @ManyToOne(() => UsersEntity) + @JoinColumn({ name: 'userId' }) + user: UsersEntity; + } + \ No newline at end of file diff --git a/src/modules/alert/repository/alerts.repository.ts b/src/modules/alert/repository/alerts.repository.ts new file mode 100644 index 0000000..da39347 --- /dev/null +++ b/src/modules/alert/repository/alerts.repository.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@nestjs/common'; +import { Repository } from 'typeorm'; +import { AlertEntity } from '../../../database/entities/alert.entity'; +import { InjectRepository } from '@nestjs/typeorm'; + +@Injectable() +export class AlertsRepository { + constructor( + @InjectRepository(AlertEntity) + private alertsRepository: Repository, + ) {} + + async createAlert(data: Partial): Promise { + return this.alertsRepository.save(data); + } + + async findUserById(userId: string): Promise { + return this.alertsRepository.find({ where: { user: { id: userId } } }); + } +} diff --git a/src/modules/alert/service/alerts.service.ts b/src/modules/alert/service/alerts.service.ts new file mode 100644 index 0000000..7967748 --- /dev/null +++ b/src/modules/alert/service/alerts.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@nestjs/common'; +import { AlertsRepository } from '../repository/alerts.repository'; // Lembre-se de ajustar o caminho correto +import { AlertEntity } from '../../../database/entities/alert.entity'; // Lembre-se de ajustar o caminho correto + +@Injectable() +export class AlertsService { + constructor(private readonly alertsRepository: AlertsRepository) {} + + async findEmailUser(alertId: string): Promise { + const alerts = await this.alertsRepository.findUserById(alertId); + if (alerts && alerts.length > 0) { + const alert = alerts[0]; + if (alert.user) { + return alert.user.email; + } + } + return null; + } +} From 44394c706fd80967b4e8f10660da85a8371e80e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Let=C3=ADcia=20Zalasik?= Date: Fri, 6 Sep 2024 10:13:18 -0300 Subject: [PATCH 2/7] =?UTF-8?q?:bug:=20Fix=20(alert.entity,=20alerts.repos?= =?UTF-8?q?itory,=20alerts.service):=20colocar=20userId=20como=20coluna,?= =?UTF-8?q?=20mudan=C3=A7a=20nio=20nome=20de=20dois=20m=C3=A9todos,=20cria?= =?UTF-8?q?=C3=A7=C3=A3o=20do=20m=C3=A9todo=20createAlert=20.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 20 ------------------- src/database/data-source.ts | 8 ++++---- src/database/entities/alert.entity.ts | 3 +++ .../alert/repository/alerts.repository.ts | 4 +++- src/modules/alert/service/alerts.service.ts | 12 +++++++++-- src/modules/mails/mail.module.ts | 8 ++++---- 6 files changed, 24 insertions(+), 31 deletions(-) delete mode 100644 .env.example diff --git a/.env.example b/.env.example deleted file mode 100644 index 61b7ef1..0000000 --- a/.env.example +++ /dev/null @@ -1,20 +0,0 @@ -PORT= - -# JWT -SECRET_KEY= - -# TYPEORM_CONNECTION -TYPEORM_CONNECTION= -TYPEORM_HOST= -TYPEORM_PORT= -TYPEORM_USERNAME= -TYPEORM_PASSWORD= -TYPEORM_DATABASE= - -#SEND_EMAIL -MAIL_HOST= -MAIL_USER= -MAIL_PASSWORD= -MAIL_FROM= -MAIL_PORT= -NODE_ENV= \ No newline at end of file diff --git a/src/database/data-source.ts b/src/database/data-source.ts index 9e1a48d..e04779b 100644 --- a/src/database/data-source.ts +++ b/src/database/data-source.ts @@ -24,10 +24,10 @@ export const typeormConfig: DataSourceOptions = { 'dist/database/migrations/*.js', 'dist/database/migrations/seeds/*.js', ], - ssl: { - ca: CA_CERT, - rejectUnauthorized: false, - } + // ssl: { + // ca: CA_CERT, + // rejectUnauthorized: false, + //} } export const AppDataSource = new DataSource({ diff --git a/src/database/entities/alert.entity.ts b/src/database/entities/alert.entity.ts index c31857c..cd7d7c4 100644 --- a/src/database/entities/alert.entity.ts +++ b/src/database/entities/alert.entity.ts @@ -11,6 +11,9 @@ import { export class AlertEntity { @PrimaryGeneratedColumn('uuid') id: string; + + @Column('uuid') + userId: string; @Column() keyword: string; diff --git a/src/modules/alert/repository/alerts.repository.ts b/src/modules/alert/repository/alerts.repository.ts index da39347..fca17b5 100644 --- a/src/modules/alert/repository/alerts.repository.ts +++ b/src/modules/alert/repository/alerts.repository.ts @@ -14,7 +14,9 @@ export class AlertsRepository { return this.alertsRepository.save(data); } - async findUserById(userId: string): Promise { + async findAlertsByUserId(userId: string): Promise { return this.alertsRepository.find({ where: { user: { id: userId } } }); } + + } diff --git a/src/modules/alert/service/alerts.service.ts b/src/modules/alert/service/alerts.service.ts index 7967748..666c55f 100644 --- a/src/modules/alert/service/alerts.service.ts +++ b/src/modules/alert/service/alerts.service.ts @@ -6,8 +6,8 @@ import { AlertEntity } from '../../../database/entities/alert.entity'; // Lembre export class AlertsService { constructor(private readonly alertsRepository: AlertsRepository) {} - async findEmailUser(alertId: string): Promise { - const alerts = await this.alertsRepository.findUserById(alertId); + async getUserEmailByAlertId(alertId: string): Promise { + const alerts = await this.alertsRepository.findAlertsByUserId(alertId); if (alerts && alerts.length > 0) { const alert = alerts[0]; if (alert.user) { @@ -16,4 +16,12 @@ export class AlertsService { } return null; } + + async createAlert(data: Partial): Promise { + return this.alertsRepository.createAlert(data); + } } + + + + diff --git a/src/modules/mails/mail.module.ts b/src/modules/mails/mail.module.ts index 656fb3a..aff3245 100644 --- a/src/modules/mails/mail.module.ts +++ b/src/modules/mails/mail.module.ts @@ -15,10 +15,10 @@ import { MailService } from './mail.service'; port: config.get('MAIL_PORT'), // secure: true, // secure: false, - auth: { - user: config.get('MAIL_USER'), - pass: config.get('MAIL_PASSWORD'), - }, + // auth: { + // user: config.get('MAIL_USER'), + // pass: config.get('MAIL_PASSWORD'), + //}, // tls: { // rejectUnauthorized: false, // }, From 8ed8b4bb4ddc467b617fee74e34df6408ccfa111 Mon Sep 17 00:00:00 2001 From: jlazaro Date: Thu, 12 Sep 2024 01:45:58 -0300 Subject: [PATCH 3/7] =?UTF-8?q?Adicionado=20fun=C3=A7=C3=A3o=20alertas=20d?= =?UTF-8?q?e=20vagas.=20Para=20verifica=C3=A7=C3=A3o=20do=20mentor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 20 - package-lock.json | 706 +++++++++++++-------------- package.json | 2 +- src/alertas/alertas.service.spec.ts | 18 + src/alertas/alertas.service.ts | 53 ++ src/alertas/dto/create-alerta.dto.ts | 5 + src/app.module.ts | 3 +- src/database/data-source.ts | 8 +- src/modules/mails/mail.module.ts | 8 +- 9 files changed, 417 insertions(+), 406 deletions(-) delete mode 100644 .env.example create mode 100644 src/alertas/alertas.service.spec.ts create mode 100644 src/alertas/alertas.service.ts create mode 100644 src/alertas/dto/create-alerta.dto.ts diff --git a/.env.example b/.env.example deleted file mode 100644 index 61b7ef1..0000000 --- a/.env.example +++ /dev/null @@ -1,20 +0,0 @@ -PORT= - -# JWT -SECRET_KEY= - -# TYPEORM_CONNECTION -TYPEORM_CONNECTION= -TYPEORM_HOST= -TYPEORM_PORT= -TYPEORM_USERNAME= -TYPEORM_PASSWORD= -TYPEORM_DATABASE= - -#SEND_EMAIL -MAIL_HOST= -MAIL_USER= -MAIL_PASSWORD= -MAIL_FROM= -MAIL_PORT= -NODE_ENV= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a738c05..b598187 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@nestjs/throttler": "^5.0.0", "@nestjs/typeorm": "^10.0.0", "aws-sdk": "2.1469.0", - "axios": "^1.6.7", + "axios": "^1.7.7", "bcrypt": "^5.1.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -149,15 +149,15 @@ } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "17.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.1.2.tgz", - "integrity": "sha512-bvXykYzSST05qFdlgIzUguNOb3z0hCa8HaTwtqdmQo9aFPf+P+/AC56I64t1iTchMjQtf3JrBQhYM25gUdcGbg==", + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.8.tgz", + "integrity": "sha512-TjmiwWJarX7oqvNiRAroQ5/LeKUatxBOCNEuKXO/PV8e7pn/Hr/BqfFm+UcYrQoFdZplmtNAfqmbqgVziKvCpA==", "dev": true, "dependencies": { - "@angular-devkit/core": "17.1.2", - "@angular-devkit/schematics": "17.1.2", + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", "ansi-colors": "4.1.3", - "inquirer": "9.2.12", + "inquirer": "9.2.15", "symbol-observable": "4.0.0", "yargs-parser": "21.1.1" }, @@ -170,6 +170,51 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-devkit/schematics-cli/node_modules/@angular-devkit/core": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", + "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/@angular-devkit/schematics": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", + "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "17.3.8", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, "node_modules/@angular-devkit/schematics-cli/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -191,47 +236,19 @@ "node": ">= 12" } }, - "node_modules/@angular-devkit/schematics-cli/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics-cli/node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { - "version": "9.2.12", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", - "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", + "version": "9.2.15", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", + "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", "dev": true, "dependencies": { - "@ljharb/through": "^2.3.11", + "@ljharb/through": "^2.3.12", "ansi-escapes": "^4.3.2", "chalk": "^5.3.0", "cli-cursor": "^3.1.0", "cli-width": "^4.1.0", "external-editor": "^3.1.0", - "figures": "^5.0.0", + "figures": "^3.2.0", "lodash": "^4.17.21", "mute-stream": "1.0.0", "ora": "^5.4.1", @@ -242,19 +259,25 @@ "wrap-ansi": "^6.2.0" }, "engines": { - "node": ">=14.18.0" + "node": ">=18" } }, - "node_modules/@angular-devkit/schematics-cli/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "node_modules/@angular-devkit/schematics-cli/node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@angular-devkit/schematics-cli/node_modules/mute-stream": { @@ -266,6 +289,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@angular-devkit/schematics-cli/node_modules/picomatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@angular-devkit/schematics-cli/node_modules/run-async": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", @@ -1895,12 +1930,12 @@ } }, "node_modules/@ljharb/through": { - "version": "2.3.12", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", - "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", + "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5" + "call-bind": "^1.0.7" }, "engines": { "node": ">= 0.4" @@ -2000,32 +2035,29 @@ } }, "node_modules/@nestjs/cli": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.3.2.tgz", - "integrity": "sha512-aWmD1GLluWrbuC4a1Iz/XBk5p74Uj6nIVZj6Ov03JbTfgtWqGFLtXuMetvzMiHxfrHehx/myt2iKAPRhKdZvTg==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", + "integrity": "sha512-FP7Rh13u8aJbHe+zZ7hM0CC4785g9Pw4lz4r2TTgRtf0zTxSWMkJaPEwyjX8SK9oWK2GsYxl+fKpwVZNbmnj9A==", "dev": true, "dependencies": { - "@angular-devkit/core": "17.1.2", - "@angular-devkit/schematics": "17.1.2", - "@angular-devkit/schematics-cli": "17.1.2", + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "@angular-devkit/schematics-cli": "17.3.8", "@nestjs/schematics": "^10.0.1", "chalk": "4.1.2", "chokidar": "3.6.0", - "cli-table3": "0.6.3", + "cli-table3": "0.6.5", "commander": "4.1.1", "fork-ts-checker-webpack-plugin": "9.0.2", - "glob": "10.3.10", + "glob": "10.4.2", "inquirer": "8.2.6", "node-emoji": "1.11.0", "ora": "5.4.1", - "rimraf": "4.4.1", - "shelljs": "0.8.5", - "source-map-support": "0.5.21", "tree-kill": "1.2.2", "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.1.0", "typescript": "5.3.3", - "webpack": "5.90.1", + "webpack": "5.94.0", "webpack-node-externals": "3.0.0" }, "bin": { @@ -2035,7 +2067,7 @@ "node": ">= 16.14" }, "peerDependencies": { - "@swc/cli": "^0.1.62 || ^0.3.0", + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0", "@swc/core": "^1.3.62" }, "peerDependenciesMeta": { @@ -2047,6 +2079,51 @@ } } }, + "node_modules/@nestjs/cli/node_modules/@angular-devkit/core": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", + "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@nestjs/cli/node_modules/@angular-devkit/schematics": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", + "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "17.3.8", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, "node_modules/@nestjs/cli/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2072,67 +2149,69 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nestjs/cli/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/@nestjs/cli/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@nestjs/cli/node_modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nestjs/cli/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/@nestjs/cli/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/@nestjs/cli/node_modules/rimraf": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "node_modules/@nestjs/cli/node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/@nestjs/cli/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/@nestjs/cli/node_modules/rimraf/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@nestjs/cli/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -2141,51 +2220,16 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nestjs/cli/node_modules/webpack": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", - "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==", + "node_modules/@nestjs/cli/node_modules/picomatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, "engines": { - "node": ">=10.13.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/@nestjs/common": { @@ -2320,15 +2364,15 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.3.tgz", - "integrity": "sha512-GGKSEU48Os7nYFIsUM0nutuFUGn5AbeP8gzFBiBCAtiuJWrXZXpZ58pMBYxAbMf7IrcOZFInHEukjHGAQU0OZw==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.1.tgz", + "integrity": "sha512-ccfqIDAq/bg1ShLI5KGtaLaYGykuAdvCi57ohewH7eKJSIpWY1DQjbgKlFfXokALYUq1YOMGqjeZ244OWHfDQg==", "dependencies": { "body-parser": "1.20.2", "cors": "2.8.5", - "express": "4.18.2", + "express": "4.19.2", "multer": "1.4.4-lts.1", - "tslib": "2.6.2" + "tslib": "2.6.3" }, "funding": { "type": "opencollective", @@ -2339,6 +2383,11 @@ "@nestjs/core": "^10.0.0" } }, + "node_modules/@nestjs/platform-express/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, "node_modules/@nestjs/schematics": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.1.1.tgz", @@ -2688,20 +2737,14 @@ "version": "8.56.3", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3170,9 +3213,9 @@ "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -3189,9 +3232,9 @@ "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", @@ -3209,14 +3252,14 @@ "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { @@ -3241,26 +3284,26 @@ "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", @@ -3268,22 +3311,22 @@ } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", @@ -3292,11 +3335,11 @@ } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -3338,10 +3381,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "peerDependencies": { "acorn": "^8" } @@ -3582,9 +3625,9 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, "node_modules/assert-never": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", - "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.3.0.tgz", + "integrity": "sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ==" }, "node_modules/async": { "version": "3.2.5", @@ -3640,11 +3683,12 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3951,11 +3995,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4409,9 +4453,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, "dependencies": { "string-width": "^4.2.0" @@ -4641,9 +4685,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -5141,9 +5185,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "optional": true, "dependencies": { "jake": "^10.8.5" @@ -5194,9 +5238,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5646,16 +5690,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -5686,29 +5730,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5874,9 +5895,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6002,9 +6023,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -6811,15 +6832,6 @@ "node": ">= 0.10" } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -8667,12 +8679,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8735,9 +8747,9 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "engines": { "node": ">=16 || 14 >=14.17" } @@ -9595,6 +9607,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -9746,15 +9764,15 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -10151,11 +10169,11 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pug": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", - "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", + "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", "dependencies": { - "pug-code-gen": "^3.0.2", + "pug-code-gen": "^3.0.3", "pug-filters": "^4.0.0", "pug-lexer": "^5.0.1", "pug-linker": "^4.0.0", @@ -10176,24 +10194,24 @@ } }, "node_modules/pug-code-gen": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", - "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", + "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", "dependencies": { "constantinople": "^4.0.1", "doctypes": "^1.1.0", "js-stringify": "^1.0.2", "pug-attrs": "^3.0.0", - "pug-error": "^2.0.0", - "pug-runtime": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", "void-elements": "^3.1.0", "with": "^7.0.0" } }, "node_modules/pug-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", - "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==" }, "node_modules/pug-filters": { "version": "4.0.0", @@ -10345,20 +10363,6 @@ "node": ">= 0.6" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -10417,18 +10421,6 @@ "node": ">=8.10.0" } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", @@ -10970,43 +10962,6 @@ "node": ">=8" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/shelljs/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/side-channel": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", @@ -11385,9 +11340,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -12292,9 +12247,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -12435,25 +12390,24 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.90.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", - "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -12461,7 +12415,7 @@ "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { diff --git a/package.json b/package.json index 9413d1b..cfb7060 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@nestjs/throttler": "^5.0.0", "@nestjs/typeorm": "^10.0.0", "aws-sdk": "2.1469.0", - "axios": "^1.6.7", + "axios": "^1.7.7", "bcrypt": "^5.1.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", diff --git a/src/alertas/alertas.service.spec.ts b/src/alertas/alertas.service.spec.ts new file mode 100644 index 0000000..d8714f9 --- /dev/null +++ b/src/alertas/alertas.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AlertasService } from './alertas.service'; + +describe('AlertasService', () => { + let service: AlertasService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AlertasService], + }).compile(); + + service = module.get(AlertasService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/alertas/alertas.service.ts b/src/alertas/alertas.service.ts new file mode 100644 index 0000000..7ceb640 --- /dev/null +++ b/src/alertas/alertas.service.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@nestjs/common'; +import { CreateAlertaDto } from './dto/create-alerta.dto'; +import { HttpService } from '@nestjs/axios'; +import { MailerService } from '@nestjs-modules/mailer'; +import { lastValueFrom } from 'rxjs'; + +@Injectable() +export class AlertasService { + constructor( + private readonly httpService: HttpService, + private readonly mailerService: MailerService, + ) {} + + private alertas = []; + + create(createAlertaDto: CreateAlertaDto) { + const novoAlerta = { id: Date.now(), ...createAlertaDto }; + this.alertas.push(novoAlerta); + return novoAlerta; + } + + async enviarEmailsDiarios() { + for (const alerta of this.alertas) { + const vagas = await this.buscarVagas(alerta.palavraChave, alerta.localizacao); + const email = this.buscarEmailUsuario(alerta.usuarioId); + await this.enviarEmail(email, vagas); + } + } + + private async buscarVagas(palavraChave: string, localizacao: string) { + const response = await lastValueFrom( + this.httpService.get(`/jobs`, { + params: { palavraChave, localizacao }, + }), + ); + return response.data; + } + + private buscarEmailUsuario(usuarioId: number) { + // Simulação de busca de e-mail do usuário + return 'usuario@example.com'; + } + + private async enviarEmail(email: string, vagas: any[]) { + await this.mailerService.sendMail({ + to: email, + subject: 'Vagas Relevantes para Você', + template: './vagas', // O template deve estar configurado + context: { vagas }, + }); + } + +} \ No newline at end of file diff --git a/src/alertas/dto/create-alerta.dto.ts b/src/alertas/dto/create-alerta.dto.ts new file mode 100644 index 0000000..707e268 --- /dev/null +++ b/src/alertas/dto/create-alerta.dto.ts @@ -0,0 +1,5 @@ +export class CreateAlertaDto { + palavraChave: string; + localizacao: string; + usuarioId: number; + } \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index bc80037..50cdab5 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -15,6 +15,7 @@ import { UploadModule } from './modules/upload/upload.module'; import { UserModule } from './modules/user/user.module'; import { ApplicationsModule } from './modules/applications/applications.module'; import { typeormConfig } from './database/data-source';import { PassportModule } from '@nestjs/passport'; +import { AlertasService } from './alertas/alertas.service'; @Module({ imports: [ @@ -39,6 +40,6 @@ import { typeormConfig } from './database/data-source';import { PassportModule } ApplicationsModule, ], controllers: [AppController], - providers: [AppService], + providers: [AppService, AlertasService], }) export class AppModule {} diff --git a/src/database/data-source.ts b/src/database/data-source.ts index 9e1a48d..6b5586a 100644 --- a/src/database/data-source.ts +++ b/src/database/data-source.ts @@ -24,10 +24,10 @@ export const typeormConfig: DataSourceOptions = { 'dist/database/migrations/*.js', 'dist/database/migrations/seeds/*.js', ], - ssl: { - ca: CA_CERT, - rejectUnauthorized: false, - } + // ssl: { + // ca: CA_CERT, + // rejectUnauthorized: false, + // } } export const AppDataSource = new DataSource({ diff --git a/src/modules/mails/mail.module.ts b/src/modules/mails/mail.module.ts index 656fb3a..d861ebd 100644 --- a/src/modules/mails/mail.module.ts +++ b/src/modules/mails/mail.module.ts @@ -15,10 +15,10 @@ import { MailService } from './mail.service'; port: config.get('MAIL_PORT'), // secure: true, // secure: false, - auth: { - user: config.get('MAIL_USER'), - pass: config.get('MAIL_PASSWORD'), - }, + // auth: { + // user: config.get('MAIL_USER'), + // pass: config.get('MAIL_PASSWORD'), + // }, // tls: { // rejectUnauthorized: false, // }, From 98868ddf80e9e6cb4d7150d795725e5d0d433c3b Mon Sep 17 00:00:00 2001 From: jlazaro Date: Wed, 18 Sep 2024 04:35:21 -0300 Subject: [PATCH 4/7] =?UTF-8?q?Palavras=20traduzidas=20para=20o=20ingl?= =?UTF-8?q?=C3=AAs=20e=20refatora=C3=A7=C3=A3o=20e=20corre=C3=A7=C3=A3o=20?= =?UTF-8?q?de=20c=C3=B3digo=20para=20verifica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++ src/alertas/alertas.service.ts | 53 ------------------- src/alertas/dto/create-alerta.dto.ts | 5 -- .../alerts.service.spec.ts} | 10 ++-- src/alerts/alerts.service.ts | 47 ++++++++++++++++ src/alerts/dto/create-alert.dto.ts | 5 ++ src/app.module.ts | 4 +- src/database/entities/alert.entity.ts | 24 +++++++++ .../alert/repository/alerts.repository.ts | 21 ++++++++ 9 files changed, 109 insertions(+), 65 deletions(-) delete mode 100644 src/alertas/alertas.service.ts delete mode 100644 src/alertas/dto/create-alerta.dto.ts rename src/{alertas/alertas.service.spec.ts => alerts/alerts.service.spec.ts} (54%) create mode 100644 src/alerts/alerts.service.ts create mode 100644 src/alerts/dto/create-alert.dto.ts create mode 100644 src/database/entities/alert.entity.ts create mode 100644 src/modules/alert/repository/alerts.repository.ts diff --git a/.gitignore b/.gitignore index 6b31da4..4618cd8 100644 --- a/.gitignore +++ b/.gitignore @@ -138,4 +138,9 @@ dist # SvelteKit build / generate output .svelte-kit +data-source.ts +.env +.env.example +mail.module.ts + # End of https://www.toptal.com/developers/gitignore/api/node \ No newline at end of file diff --git a/src/alertas/alertas.service.ts b/src/alertas/alertas.service.ts deleted file mode 100644 index 7ceb640..0000000 --- a/src/alertas/alertas.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { CreateAlertaDto } from './dto/create-alerta.dto'; -import { HttpService } from '@nestjs/axios'; -import { MailerService } from '@nestjs-modules/mailer'; -import { lastValueFrom } from 'rxjs'; - -@Injectable() -export class AlertasService { - constructor( - private readonly httpService: HttpService, - private readonly mailerService: MailerService, - ) {} - - private alertas = []; - - create(createAlertaDto: CreateAlertaDto) { - const novoAlerta = { id: Date.now(), ...createAlertaDto }; - this.alertas.push(novoAlerta); - return novoAlerta; - } - - async enviarEmailsDiarios() { - for (const alerta of this.alertas) { - const vagas = await this.buscarVagas(alerta.palavraChave, alerta.localizacao); - const email = this.buscarEmailUsuario(alerta.usuarioId); - await this.enviarEmail(email, vagas); - } - } - - private async buscarVagas(palavraChave: string, localizacao: string) { - const response = await lastValueFrom( - this.httpService.get(`/jobs`, { - params: { palavraChave, localizacao }, - }), - ); - return response.data; - } - - private buscarEmailUsuario(usuarioId: number) { - // Simulação de busca de e-mail do usuário - return 'usuario@example.com'; - } - - private async enviarEmail(email: string, vagas: any[]) { - await this.mailerService.sendMail({ - to: email, - subject: 'Vagas Relevantes para Você', - template: './vagas', // O template deve estar configurado - context: { vagas }, - }); - } - -} \ No newline at end of file diff --git a/src/alertas/dto/create-alerta.dto.ts b/src/alertas/dto/create-alerta.dto.ts deleted file mode 100644 index 707e268..0000000 --- a/src/alertas/dto/create-alerta.dto.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class CreateAlertaDto { - palavraChave: string; - localizacao: string; - usuarioId: number; - } \ No newline at end of file diff --git a/src/alertas/alertas.service.spec.ts b/src/alerts/alerts.service.spec.ts similarity index 54% rename from src/alertas/alertas.service.spec.ts rename to src/alerts/alerts.service.spec.ts index d8714f9..0294813 100644 --- a/src/alertas/alertas.service.spec.ts +++ b/src/alerts/alerts.service.spec.ts @@ -1,15 +1,15 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { AlertasService } from './alertas.service'; +import { AlertsService } from './alerts.service'; -describe('AlertasService', () => { - let service: AlertasService; +describe('AlertsService', () => { + let service: AlertsService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [AlertasService], + providers: [AlertsService], }).compile(); - service = module.get(AlertasService); + service = module.get(AlertsService); }); it('should be defined', () => { diff --git a/src/alerts/alerts.service.ts b/src/alerts/alerts.service.ts new file mode 100644 index 0000000..aad7f56 --- /dev/null +++ b/src/alerts/alerts.service.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@nestjs/common'; +import { AlertsRepository } from '../modules/alert/repository/alerts.repository' +import { JobsEntity } from '../database/entities/jobs.entity' +import { MailerService } from '@nestjs-modules/mailer'; +import axios from 'axios'; + +@Injectable() +export class AlertsService { + constructor( + private readonly mailerService: MailerService, + private readonly alertsRepository: AlertsRepository, + + ) {} + + + async sendEmailsDaily() { + const alerts = await this.alertsRepository.findAll(); + for (const alert of alerts) { + const jobs = await this.findJobs(alert.keyword, alert.location); + const userEmail = alert.user.email; + await this.sendEmail(userEmail, jobs); + } + } + + private findEmailUser(userId: number) { + // Simulação de busca de e-mail do usuário + return 'usuario@example.com'; + } + + private async findJobs(keyword: string, location: string): Promise { + // Exemplo de busca simples + const response = await axios.get(`/jobs?keyword=${keyword}&location=${location}`); + return response.data; + } + + private async sendEmail(email: string, jobs: JobsEntity[]): Promise { + await this.mailerService.sendMail({ + to: email, + subject: 'Vagas Relevantes para Você', + template: './vagas', + context: { + jobs, + }, + }); + } + +} \ No newline at end of file diff --git a/src/alerts/dto/create-alert.dto.ts b/src/alerts/dto/create-alert.dto.ts new file mode 100644 index 0000000..4005b55 --- /dev/null +++ b/src/alerts/dto/create-alert.dto.ts @@ -0,0 +1,5 @@ +export class CreateAlertDto { + keyword: string; + location: string; + userId: number; + } \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index 50cdab5..a72d171 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -15,7 +15,7 @@ import { UploadModule } from './modules/upload/upload.module'; import { UserModule } from './modules/user/user.module'; import { ApplicationsModule } from './modules/applications/applications.module'; import { typeormConfig } from './database/data-source';import { PassportModule } from '@nestjs/passport'; -import { AlertasService } from './alertas/alertas.service'; +import { AlertsService } from './alerts/alerts.service'; @Module({ imports: [ @@ -40,6 +40,6 @@ import { AlertasService } from './alertas/alertas.service'; ApplicationsModule, ], controllers: [AppController], - providers: [AppService, AlertasService], + providers: [AppService, AlertsService], }) export class AppModule {} diff --git a/src/database/entities/alert.entity.ts b/src/database/entities/alert.entity.ts new file mode 100644 index 0000000..9ea5d5b --- /dev/null +++ b/src/database/entities/alert.entity.ts @@ -0,0 +1,24 @@ +import { + Column, + Entity, + PrimaryGeneratedColumn, + ManyToOne, + JoinColumn, + } from 'typeorm'; + import { UsersEntity } from './users.entity'; + + @Entity('tb_alerts') + export class AlertEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + keyword: string; + + @Column() + location: string; + + @ManyToOne(() => UsersEntity) + @JoinColumn({ name: 'userId' }) + user: UsersEntity; + } \ No newline at end of file diff --git a/src/modules/alert/repository/alerts.repository.ts b/src/modules/alert/repository/alerts.repository.ts new file mode 100644 index 0000000..7c5f2f9 --- /dev/null +++ b/src/modules/alert/repository/alerts.repository.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@nestjs/common'; +import { AlertEntity } from '../../../database/entities/alert.entity'; + +@Injectable() +export class AlertsRepository { + private alerts: AlertEntity[] = []; + + async create(alert: AlertEntity): Promise { + const existingAlert = this.alerts.find(a => a.id === alert.id); + if (existingAlert) { + + return existingAlert; + } + this.alerts.push(alert); + return alert; + } + + async findAll(): Promise { + return this.alerts; + } +} \ No newline at end of file From 69c2bd9371d28e039e4e4c2e505ea0f15ae412e8 Mon Sep 17 00:00:00 2001 From: Guilherme Sanches Date: Tue, 24 Sep 2024 16:40:41 -0300 Subject: [PATCH 5/7] :sparkles: feat(alerts): alert controller & migration --- package-lock.json | 32 ++++++++++++ package.json | 3 ++ src/alerts/alerts.service.spec.ts | 18 ------- src/alerts/alerts.service.ts | 47 ----------------- src/alerts/dto/create-alert.dto.ts | 5 -- src/app.module.ts | 14 ++--- src/database/entities/alert.entity.ts | 4 +- .../migrations/1727205337042-migrations.ts | 52 +++++++++++++++++++ src/modules/alert/alerts.module.ts | 15 ++++++ .../alert/controller/alerts.controller.ts | 15 ++++++ src/modules/alert/dtos/create-alert.dto.ts | 15 ++++++ .../alert/repository/alerts.repository.ts | 7 ++- src/modules/alert/service/alerts.service.ts | 51 ++++++++++-------- src/modules/mails/mail.service.ts | 13 ++++- src/modules/mails/templates/jobsAlert.hbs | 41 +++++++++++++++ 15 files changed, 227 insertions(+), 105 deletions(-) delete mode 100644 src/alerts/alerts.service.spec.ts delete mode 100644 src/alerts/alerts.service.ts delete mode 100644 src/alerts/dto/create-alert.dto.ts create mode 100644 src/database/migrations/1727205337042-migrations.ts create mode 100644 src/modules/alert/alerts.module.ts create mode 100644 src/modules/alert/controller/alerts.controller.ts create mode 100644 src/modules/alert/dtos/create-alert.dto.ts create mode 100644 src/modules/mails/templates/jobsAlert.hbs diff --git a/package-lock.json b/package-lock.json index b598187..f18d68a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,8 @@ "dotenv": "^16.4.5", "handlebars": "^4.7.8", "install": "^0.13.0", + "linkedin-backend": "file:", + "node-cron": "^3.0.3", "nodemailer": "^6.9.5", "passport": "^0.6.0", "passport-jwt": "^4.0.1", @@ -49,6 +51,7 @@ "@types/express": "^4.17.18", "@types/jest": "29.5.5", "@types/node": "^20.8.2", + "@types/node-cron": "^3.0.11", "@types/nodemailer": "^6.4.11", "@types/passport-jwt": "^3.0.10", "@types/supertest": "^2.0.14", @@ -2856,6 +2859,12 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/node-cron": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", + "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", + "dev": true + }, "node_modules/@types/nodemailer": { "version": "6.4.14", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.14.tgz", @@ -8381,6 +8390,10 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkedin-backend": { + "resolved": "", + "link": true + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -9288,6 +9301,25 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-cron/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", diff --git a/package.json b/package.json index cfb7060..26deb56 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,8 @@ "dotenv": "^16.4.5", "handlebars": "^4.7.8", "install": "^0.13.0", + "linkedin-backend": "file:", + "node-cron": "^3.0.3", "nodemailer": "^6.9.5", "passport": "^0.6.0", "passport-jwt": "^4.0.1", @@ -67,6 +69,7 @@ "@types/express": "^4.17.18", "@types/jest": "29.5.5", "@types/node": "^20.8.2", + "@types/node-cron": "^3.0.11", "@types/nodemailer": "^6.4.11", "@types/passport-jwt": "^3.0.10", "@types/supertest": "^2.0.14", diff --git a/src/alerts/alerts.service.spec.ts b/src/alerts/alerts.service.spec.ts deleted file mode 100644 index 0294813..0000000 --- a/src/alerts/alerts.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AlertsService } from './alerts.service'; - -describe('AlertsService', () => { - let service: AlertsService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [AlertsService], - }).compile(); - - service = module.get(AlertsService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/src/alerts/alerts.service.ts b/src/alerts/alerts.service.ts deleted file mode 100644 index aad7f56..0000000 --- a/src/alerts/alerts.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AlertsRepository } from '../modules/alert/repository/alerts.repository' -import { JobsEntity } from '../database/entities/jobs.entity' -import { MailerService } from '@nestjs-modules/mailer'; -import axios from 'axios'; - -@Injectable() -export class AlertsService { - constructor( - private readonly mailerService: MailerService, - private readonly alertsRepository: AlertsRepository, - - ) {} - - - async sendEmailsDaily() { - const alerts = await this.alertsRepository.findAll(); - for (const alert of alerts) { - const jobs = await this.findJobs(alert.keyword, alert.location); - const userEmail = alert.user.email; - await this.sendEmail(userEmail, jobs); - } - } - - private findEmailUser(userId: number) { - // Simulação de busca de e-mail do usuário - return 'usuario@example.com'; - } - - private async findJobs(keyword: string, location: string): Promise { - // Exemplo de busca simples - const response = await axios.get(`/jobs?keyword=${keyword}&location=${location}`); - return response.data; - } - - private async sendEmail(email: string, jobs: JobsEntity[]): Promise { - await this.mailerService.sendMail({ - to: email, - subject: 'Vagas Relevantes para Você', - template: './vagas', - context: { - jobs, - }, - }); - } - -} \ No newline at end of file diff --git a/src/alerts/dto/create-alert.dto.ts b/src/alerts/dto/create-alert.dto.ts deleted file mode 100644 index 4005b55..0000000 --- a/src/alerts/dto/create-alert.dto.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class CreateAlertDto { - keyword: string; - location: string; - userId: number; - } \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index a72d171..8758e41 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -14,8 +14,9 @@ import { ReportsModule } from './modules/reports/reports.module'; import { UploadModule } from './modules/upload/upload.module'; import { UserModule } from './modules/user/user.module'; import { ApplicationsModule } from './modules/applications/applications.module'; -import { typeormConfig } from './database/data-source';import { PassportModule } from '@nestjs/passport'; -import { AlertsService } from './alerts/alerts.service'; +import { typeormConfig } from './database/data-source'; +import { PassportModule } from '@nestjs/passport'; +import { AlertsModule } from './modules/alert/alerts.module'; @Module({ imports: [ @@ -24,10 +25,10 @@ import { AlertsService } from './alerts/alerts.service'; TypeOrmModule.forRootAsync({ useFactory: () => ({ ...typeormConfig, - autoLoadEntities: true - }) + autoLoadEntities: true, + }), }), - PassportModule.register({defaultStrategy: "jwt"}), + PassportModule.register({ defaultStrategy: 'jwt' }), JobsModule, UserModule, AuthModule, @@ -38,8 +39,9 @@ import { AlertsService } from './alerts/alerts.service'; UploadModule, CurriculumModule, ApplicationsModule, + AlertsModule, ], controllers: [AppController], - providers: [AppService, AlertsService], + providers: [AppService], }) export class AppModule {} diff --git a/src/database/entities/alert.entity.ts b/src/database/entities/alert.entity.ts index 0c6e946..04869ca 100644 --- a/src/database/entities/alert.entity.ts +++ b/src/database/entities/alert.entity.ts @@ -12,7 +12,7 @@ export class AlertEntity { @PrimaryGeneratedColumn('uuid') id: string; - @Column('uuid') + @Column({ name: 'user_id' }) userId: string; @Column() @@ -22,6 +22,6 @@ export class AlertEntity { location: string; @ManyToOne(() => UsersEntity) - @JoinColumn({ name: 'userId' }) + @JoinColumn({ name: 'user_id' }) user: UsersEntity; } diff --git a/src/database/migrations/1727205337042-migrations.ts b/src/database/migrations/1727205337042-migrations.ts new file mode 100644 index 0000000..98a7458 --- /dev/null +++ b/src/database/migrations/1727205337042-migrations.ts @@ -0,0 +1,52 @@ +import { + MigrationInterface, + QueryRunner, + Table, + TableForeignKey, +} from 'typeorm'; + +export class Migrations1727205337042 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: 'tb_alerts', + columns: [ + { + name: 'id', + type: 'uuid', + isPrimary: true, + generationStrategy: 'uuid', + default: 'uuid_generate_v4()', + }, + { + name: 'user_id', + type: 'uuid', + }, + { + name: 'keyword', + type: 'varchar', + }, + { + name: 'location', + type: 'varchar', + }, + ], + }), + true, + ); + + await queryRunner.createForeignKey( + 'tb_alerts', + new TableForeignKey({ + columnNames: ['user_id'], + referencedColumnNames: ['id'], + referencedTableName: 'tb_users', + onDelete: 'CASCADE', + }), + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable('tb_alerts'); + } +} diff --git a/src/modules/alert/alerts.module.ts b/src/modules/alert/alerts.module.ts new file mode 100644 index 0000000..b703039 --- /dev/null +++ b/src/modules/alert/alerts.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AlertsController } from './controller/alerts.controller'; +import { AlertEntity } from 'src/database/entities/alert.entity'; +import { MailModule } from '../mails/mail.module'; +import { AlertsRepository } from './repository/alerts.repository'; +import { AlertsService } from './service/alerts.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([AlertEntity]), MailModule], + controllers: [AlertsController], + providers: [AlertsService, AlertsRepository], + exports: [AlertsService], +}) +export class AlertsModule {} diff --git a/src/modules/alert/controller/alerts.controller.ts b/src/modules/alert/controller/alerts.controller.ts new file mode 100644 index 0000000..7737d65 --- /dev/null +++ b/src/modules/alert/controller/alerts.controller.ts @@ -0,0 +1,15 @@ +import { Body, Controller, Post, UseGuards } from '@nestjs/common'; +import { AlertsService } from '../service/alerts.service'; +import { CreateAlertDto } from '../dtos/create-alert.dto'; +import { AuthGuard } from '@nestjs/passport'; + +@Controller('alerts') +@UseGuards(AuthGuard('jwt')) +export class AlertsController { + constructor(private readonly alertsService: AlertsService) {} + + @Post() + async createAlert(@Body() createAlertDto: CreateAlertDto) { + return await this.alertsService.createAlert(createAlertDto); + } +} diff --git a/src/modules/alert/dtos/create-alert.dto.ts b/src/modules/alert/dtos/create-alert.dto.ts new file mode 100644 index 0000000..82ed417 --- /dev/null +++ b/src/modules/alert/dtos/create-alert.dto.ts @@ -0,0 +1,15 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class CreateAlertDto { + @IsString({ message: 'O campo userId deve ser uma string' }) + @IsNotEmpty({ message: 'O campo userId não pode estar vazio' }) + userId: string; + + @IsString({ message: 'O campo keyword deve ser uma string' }) + @IsNotEmpty({ message: 'O campo keyword não pode estar vazio' }) + keyword: string; + + @IsString({ message: 'O campo location deve ser uma string' }) + @IsNotEmpty({ message: 'O campo location não pode estar vazio' }) + location: string; +} diff --git a/src/modules/alert/repository/alerts.repository.ts b/src/modules/alert/repository/alerts.repository.ts index 1578342..023ddd8 100644 --- a/src/modules/alert/repository/alerts.repository.ts +++ b/src/modules/alert/repository/alerts.repository.ts @@ -14,8 +14,11 @@ export class AlertsRepository { return this.alertsRepository.save(data); } - async findAlertsByUserId(userId: string): Promise { - return this.alertsRepository.find({ where: { user: { id: userId } } }); + async findAlertById(alertId: string): Promise { + return this.alertsRepository.findOne({ + where: { id: alertId }, + relations: ['user'], + }); } async findAll(): Promise { diff --git a/src/modules/alert/service/alerts.service.ts b/src/modules/alert/service/alerts.service.ts index 9e3a920..ba13665 100644 --- a/src/modules/alert/service/alerts.service.ts +++ b/src/modules/alert/service/alerts.service.ts @@ -1,25 +1,37 @@ import { Injectable } from '@nestjs/common'; -import { AlertsRepository } from '../repository/alerts.repository'; // Lembre-se de ajustar o caminho correto -import { AlertEntity } from '../../../database/entities/alert.entity'; // Lembre-se de ajustar o caminho correto +import { AlertsRepository } from '../repository/alerts.repository'; +import { AlertEntity } from '../../../database/entities/alert.entity'; import { JobsEntity } from 'src/database/entities/jobs.entity'; import axios from 'axios'; -import { MailerService } from '@nestjs-modules/mailer'; +import { MailService } from '../../mails/mail.service'; +import * as Cron from 'node-cron'; @Injectable() export class AlertsService { constructor( private readonly alertsRepository: AlertsRepository, - private readonly mailerService: MailerService, - ) {} + private readonly mailerService: MailService, + ) { + Cron.schedule( + '0 12 * * *', + () => { + this.sendEmailsDaily(); + }, + { + scheduled: true, + timezone: 'America/Sao_Paulo', + }, + ); + } - async getUserEmailByAlertId(alertId: string): Promise { - const alerts = await this.alertsRepository.findAlertsByUserId(alertId); - if (alerts && alerts.length > 0) { - const alert = alerts[0]; - if (alert.user) { - return alert.user.email; - } + async getUserEmailByAlertId( + alertId: string, + ): Promise<{ email: string } | null> { + const alert = await this.alertsRepository.findAlertById(alertId); + if (alert) { + return { email: alert.user.email }; } + return null; } @@ -31,8 +43,8 @@ export class AlertsService { const alerts = await this.alertsRepository.findAll(); for (const alert of alerts) { const jobs = await this.findJobs(alert.keyword, alert.location); - const userEmail = alert.user.email; - await this.sendEmail(userEmail, jobs); + const user = await this.getUserEmailByAlertId(alert.id); + await this.sendEmail(user.email, jobs); } } @@ -41,19 +53,12 @@ export class AlertsService { location: string, ): Promise { const response = await axios.get( - `/jobs?keyword=${keyword}&location=${location}`, + `${process.env.VACANCIES_URL}/job?keyword=${keyword}&location=${location}`, ); return response.data; } private async sendEmail(email: string, jobs: JobsEntity[]): Promise { - await this.mailerService.sendMail({ - to: email, - subject: 'Vagas Relevantes para Você', - template: './vagas', - context: { - jobs, - }, - }); + await this.mailerService.sendJobAlerts(email, jobs); } } diff --git a/src/modules/mails/mail.service.ts b/src/modules/mails/mail.service.ts index ba725b1..790e90e 100644 --- a/src/modules/mails/mail.service.ts +++ b/src/modules/mails/mail.service.ts @@ -12,8 +12,6 @@ export class MailService { // const url = `https://vagas-front-end.netlify.app/recovery-password?token=${recoverPasswordToken}&type=USER`; const url = `${process.env.FRONTEND_URL}/recovery-password?token=${recoverPasswordToken}&type=USER`; - - if (recoverPasswordToken) { await this.mailerService.sendMail({ to: email, @@ -97,6 +95,17 @@ export class MailService { }); } + async sendJobAlerts(email: string, jobs: any[]): Promise { + await this.mailerService.sendMail({ + to: email, + subject: 'Vagas Relevantes para Você', + template: './jobsAlert', + context: { + jobs, + }, + }); + } + async sendMail({ subject, template, context, email }) { await this.mailerService.sendMail({ to: email, diff --git a/src/modules/mails/templates/jobsAlert.hbs b/src/modules/mails/templates/jobsAlert.hbs new file mode 100644 index 0000000..88288b7 --- /dev/null +++ b/src/modules/mails/templates/jobsAlert.hbs @@ -0,0 +1,41 @@ + + + + + + Vagas Encontradas + + +

Vagas Encontradas!

+

Olá, aqui estão as vagas encontradas para a posição que você criou o alerta:

+
    + {{#each jobs}} +
  • + {{#if this.title}} +

    {{this.title}}

    + {{else}} +

    Título não disponível

    + {{/if}} + + {{#if this.description}} +

    {{this.description}}

    + {{else}} +

    Descrição não disponível

    + {{/if}} + + {{#if this.location}} +

    Local: {{this.location}}

    + {{else}} +

    Localização não disponível

    + {{/if}} + + {{#if this.link}} +

    Ver mais detalhes

    + {{else}} +

    Link não disponível

    + {{/if}} +
  • + {{/each}} +
+ + \ No newline at end of file From 9bfd20ccfb14f0d45645542e496b1e13a329e0c6 Mon Sep 17 00:00:00 2001 From: Guilherme Sanches Date: Fri, 4 Oct 2024 16:15:03 -0300 Subject: [PATCH 6/7] :wrench: fix(alerts): add error handling & fix alert email template --- .gitignore | 2 +- src/database/data-source.ts | 35 ++ src/database/entities/alert.entity.ts | 2 +- .../alert/controller/alerts.controller.ts | 3 + .../alert/repository/alerts.repository.ts | 15 +- src/modules/alert/service/alerts.service.ts | 48 ++- src/modules/mails/mail.service.ts | 3 +- src/modules/mails/templates/jobsAlert.hbs | 400 ++++++++++++++++-- 8 files changed, 445 insertions(+), 63 deletions(-) create mode 100644 src/database/data-source.ts diff --git a/.gitignore b/.gitignore index 2bb6891..50c11b5 100644 --- a/.gitignore +++ b/.gitignore @@ -139,7 +139,7 @@ dist .svelte-kit # Config files -src/database/data-source.ts +# src/database/data-source.ts .env .env.example mail.module.ts diff --git a/src/database/data-source.ts b/src/database/data-source.ts new file mode 100644 index 0000000..069ba46 --- /dev/null +++ b/src/database/data-source.ts @@ -0,0 +1,35 @@ +import { config } from 'dotenv'; +config(); +import { DataSource, DataSourceOptions } from 'typeorm'; +import 'reflect-metadata'; + +const { + TYPEORM_HOST, + TYPEORM_PORT, + TYPEORM_PASSWORD, + TYPEORM_USERNAME, + TYPEORM_DATABASE, + CA_CERT, +} = process.env; + +export const typeormConfig: DataSourceOptions = { + type: 'postgres', + host: TYPEORM_HOST, + port: +TYPEORM_PORT, + username: TYPEORM_USERNAME, + password: TYPEORM_PASSWORD, + database: TYPEORM_DATABASE, + entities: ['dist/database/entities/*.entity.js'], + migrations: [ + 'dist/database/migrations/*.js', + 'dist/database/migrations/seeds/*.js', + ], + /* ssl: { + ca: CA_CERT, + rejectUnauthorized: false, + }, */ +}; + +export const AppDataSource = new DataSource({ + ...typeormConfig, +}); diff --git a/src/database/entities/alert.entity.ts b/src/database/entities/alert.entity.ts index 04869ca..dc87996 100644 --- a/src/database/entities/alert.entity.ts +++ b/src/database/entities/alert.entity.ts @@ -12,7 +12,7 @@ export class AlertEntity { @PrimaryGeneratedColumn('uuid') id: string; - @Column({ name: 'user_id' }) + @Column({ name: 'user_id', nullable: false }) userId: string; @Column() diff --git a/src/modules/alert/controller/alerts.controller.ts b/src/modules/alert/controller/alerts.controller.ts index 7737d65..b63aed1 100644 --- a/src/modules/alert/controller/alerts.controller.ts +++ b/src/modules/alert/controller/alerts.controller.ts @@ -2,13 +2,16 @@ import { Body, Controller, Post, UseGuards } from '@nestjs/common'; import { AlertsService } from '../service/alerts.service'; import { CreateAlertDto } from '../dtos/create-alert.dto'; import { AuthGuard } from '@nestjs/passport'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +@ApiTags('Alerts') @Controller('alerts') @UseGuards(AuthGuard('jwt')) export class AlertsController { constructor(private readonly alertsService: AlertsService) {} @Post() + @ApiBearerAuth() async createAlert(@Body() createAlertDto: CreateAlertDto) { return await this.alertsService.createAlert(createAlertDto); } diff --git a/src/modules/alert/repository/alerts.repository.ts b/src/modules/alert/repository/alerts.repository.ts index 023ddd8..dd42790 100644 --- a/src/modules/alert/repository/alerts.repository.ts +++ b/src/modules/alert/repository/alerts.repository.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; import { AlertEntity } from '../../../database/entities/alert.entity'; import { InjectRepository } from '@nestjs/typeorm'; +import { handleError } from '../../../shared/utils/handle-error.util'; @Injectable() export class AlertsRepository { @@ -11,17 +12,19 @@ export class AlertsRepository { ) {} async createAlert(data: Partial): Promise { - return this.alertsRepository.save(data); + return this.alertsRepository.save(data).catch(handleError); } async findAlertById(alertId: string): Promise { - return this.alertsRepository.findOne({ - where: { id: alertId }, - relations: ['user'], - }); + return this.alertsRepository + .findOne({ + where: { id: alertId }, + relations: ['user'], + }) + .catch(handleError); } async findAll(): Promise { - return this.alertsRepository.find(); + return this.alertsRepository.find().catch(handleError); } } diff --git a/src/modules/alert/service/alerts.service.ts b/src/modules/alert/service/alerts.service.ts index ba13665..4965cb3 100644 --- a/src/modules/alert/service/alerts.service.ts +++ b/src/modules/alert/service/alerts.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { AlertsRepository } from '../repository/alerts.repository'; import { AlertEntity } from '../../../database/entities/alert.entity'; import { JobsEntity } from 'src/database/entities/jobs.entity'; @@ -12,8 +12,12 @@ export class AlertsService { private readonly alertsRepository: AlertsRepository, private readonly mailerService: MailService, ) { + this.configureCronJob(); + } + + private configureCronJob() { Cron.schedule( - '0 12 * * *', + '49 15 * * *', () => { this.sendEmailsDaily(); }, @@ -24,15 +28,11 @@ export class AlertsService { ); } - async getUserEmailByAlertId( - alertId: string, - ): Promise<{ email: string } | null> { + async getUserEmailByAlertId(alertId: string): Promise { const alert = await this.alertsRepository.findAlertById(alertId); - if (alert) { - return { email: alert.user.email }; - } + if (!alert) throw new NotFoundException('Alert not found'); - return null; + return alert.user.email; } async createAlert(data: Partial): Promise { @@ -41,21 +41,33 @@ export class AlertsService { async sendEmailsDaily() { const alerts = await this.alertsRepository.findAll(); - for (const alert of alerts) { - const jobs = await this.findJobs(alert.keyword, alert.location); - const user = await this.getUserEmailByAlertId(alert.id); - await this.sendEmail(user.email, jobs); - } + + await Promise.all( + alerts.map(async (alert) => { + const jobs = await this.findJobs(alert.keyword, alert.location); + const userEmail = await this.getUserEmailByAlertId(alert.id); + + await this.sendEmail(userEmail, jobs); + }), + ); } private async findJobs( keyword: string, location: string, ): Promise { - const response = await axios.get( - `${process.env.VACANCIES_URL}/job?keyword=${keyword}&location=${location}`, - ); - return response.data; + try { + const response = await axios.get( + `${process.env.VACANCIES_URL}/job?keyword=${keyword}&location=${location}`, + ); + return response.data; + } catch (error) { + console.error( + `Error fetching jobs for keyword: ${keyword}, location: ${location}`, + error, + ); + return []; + } } private async sendEmail(email: string, jobs: JobsEntity[]): Promise { diff --git a/src/modules/mails/mail.service.ts b/src/modules/mails/mail.service.ts index 790e90e..d6abb58 100644 --- a/src/modules/mails/mail.service.ts +++ b/src/modules/mails/mail.service.ts @@ -1,6 +1,7 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Injectable } from '@nestjs/common'; import { CompaniesEntity } from 'src/database/entities/companies.entity'; +import { JobsEntity } from 'src/database/entities/jobs.entity'; import { UsersEntity } from 'src/database/entities/users.entity'; @Injectable() @@ -95,7 +96,7 @@ export class MailService { }); } - async sendJobAlerts(email: string, jobs: any[]): Promise { + async sendJobAlerts(email: string, jobs: JobsEntity[]): Promise { await this.mailerService.sendMail({ to: email, subject: 'Vagas Relevantes para Você', diff --git a/src/modules/mails/templates/jobsAlert.hbs b/src/modules/mails/templates/jobsAlert.hbs index 88288b7..752eb6b 100644 --- a/src/modules/mails/templates/jobsAlert.hbs +++ b/src/modules/mails/templates/jobsAlert.hbs @@ -1,41 +1,369 @@ - + + - - - Vagas Encontradas + + + + + - -

Vagas Encontradas!

-

Olá, aqui estão as vagas encontradas para a posição que você criou o alerta:

-
    - {{#each jobs}} -
  • - {{#if this.title}} -

    {{this.title}}

    - {{else}} -

    Título não disponível

    - {{/if}} - - {{#if this.description}} -

    {{this.description}}

    - {{else}} -

    Descrição não disponível

    - {{/if}} - - {{#if this.location}} -

    Local: {{this.location}}

    - {{else}} -

    Localização não disponível

    - {{/if}} - - {{#if this.link}} -

    Ver mais detalhes

    - {{else}} -

    Link não disponível

    - {{/if}} -
  • - {{/each}} -
+ + + + + + + + + + \ No newline at end of file From 694f7fc7548c27d1a5e65734aa86bb8cfd91989a Mon Sep 17 00:00:00 2001 From: Guilherme Sanches Date: Fri, 4 Oct 2024 16:32:00 -0300 Subject: [PATCH 7/7] :sparkles: feat(alerts): add swagger annotations --- src/modules/alert/controller/alerts.controller.ts | 2 ++ src/modules/alert/dtos/create-alert.dto.ts | 13 +++++++++++++ .../decorators/alerts/create-alert.swagger.ts | 10 ++++++++++ 3 files changed, 25 insertions(+) create mode 100644 src/shared/Swagger/decorators/alerts/create-alert.swagger.ts diff --git a/src/modules/alert/controller/alerts.controller.ts b/src/modules/alert/controller/alerts.controller.ts index b63aed1..68aa24d 100644 --- a/src/modules/alert/controller/alerts.controller.ts +++ b/src/modules/alert/controller/alerts.controller.ts @@ -3,6 +3,7 @@ import { AlertsService } from '../service/alerts.service'; import { CreateAlertDto } from '../dtos/create-alert.dto'; import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { CreateAlertSwagger } from '../../../shared/Swagger/decorators/alerts/create-alert.swagger'; @ApiTags('Alerts') @Controller('alerts') @@ -12,6 +13,7 @@ export class AlertsController { @Post() @ApiBearerAuth() + @CreateAlertSwagger() async createAlert(@Body() createAlertDto: CreateAlertDto) { return await this.alertsService.createAlert(createAlertDto); } diff --git a/src/modules/alert/dtos/create-alert.dto.ts b/src/modules/alert/dtos/create-alert.dto.ts index 82ed417..aa009cd 100644 --- a/src/modules/alert/dtos/create-alert.dto.ts +++ b/src/modules/alert/dtos/create-alert.dto.ts @@ -1,14 +1,27 @@ +import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString } from 'class-validator'; export class CreateAlertDto { + @ApiProperty({ + name: 'userId', + type: String, + }) @IsString({ message: 'O campo userId deve ser uma string' }) @IsNotEmpty({ message: 'O campo userId não pode estar vazio' }) userId: string; + @ApiProperty({ + name: 'keyword', + type: String, + }) @IsString({ message: 'O campo keyword deve ser uma string' }) @IsNotEmpty({ message: 'O campo keyword não pode estar vazio' }) keyword: string; + @ApiProperty({ + name: 'location', + type: String, + }) @IsString({ message: 'O campo location deve ser uma string' }) @IsNotEmpty({ message: 'O campo location não pode estar vazio' }) location: string; diff --git a/src/shared/Swagger/decorators/alerts/create-alert.swagger.ts b/src/shared/Swagger/decorators/alerts/create-alert.swagger.ts new file mode 100644 index 0000000..38ffeaa --- /dev/null +++ b/src/shared/Swagger/decorators/alerts/create-alert.swagger.ts @@ -0,0 +1,10 @@ +import { applyDecorators } from '@nestjs/common'; +import { ApiOperation } from '@nestjs/swagger'; + +export function CreateAlertSwagger() { + return applyDecorators( + ApiOperation({ + summary: 'Criar alerta de vaga', + }), + ); +}