diff --git a/.eslintrc b/.eslintrc index f22dca830..24c75871f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -20,6 +20,7 @@ "rules": { "@typescript-eslint/no-explicit-any": "off", "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "warn" + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/await-thenable": "error" } } diff --git a/cspell.json b/cspell.json index 6fe536f68..834d20c7d 100644 --- a/cspell.json +++ b/cspell.json @@ -14,7 +14,9 @@ "apikey", "requestid", "dtos", - "blabla" + "blabla", + "randexp", + "mediumpassword" ], "ignorePaths": [ "node_modules/**", diff --git a/package.json b/package.json index c2222f523..cf1ff3365 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ack-nestjs-boilerplate", - "version": "5.6.6", + "version": "5.7.0", "description": "Ack NestJs Boilerplate", "repository": { "type": "git", @@ -47,25 +47,25 @@ "rollback": "yarn rollback:email && yarn rollback:apikey && yarn rollback:user && yarn rollback:role" }, "dependencies": { - "@aws-sdk/client-s3": "^3.507.0", - "@aws-sdk/client-ses": "^3.507.0", + "@aws-sdk/client-s3": "^3.513.0", + "@aws-sdk/client-ses": "^3.513.0", "@casl/ability": "^6.5.0", - "@faker-js/faker": "^8.4.0", + "@faker-js/faker": "^8.4.1", "@joi/date": "^2.1.0", - "@nestjs/axios": "^3.0.1", - "@nestjs/common": "^10.3.1", - "@nestjs/config": "^3.1.1", - "@nestjs/core": "^10.3.1", + "@nestjs/axios": "^3.0.2", + "@nestjs/common": "^10.3.3", + "@nestjs/config": "^3.2.0", + "@nestjs/core": "^10.3.3", "@nestjs/jwt": "^10.2.0", - "@nestjs/mongoose": "^10.0.2", + "@nestjs/mongoose": "^10.0.4", "@nestjs/passport": "^10.0.3", - "@nestjs/platform-express": "^10.3.1", - "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.2.0", - "@nestjs/terminus": "^10.2.1", - "@nestjs/throttler": "^5.1.1", + "@nestjs/platform-express": "^10.3.3", + "@nestjs/schedule": "^4.0.1", + "@nestjs/swagger": "^7.3.0", + "@nestjs/terminus": "^10.2.2", + "@nestjs/throttler": "^5.1.2", "@ntegral/nestjs-sentry": "^4.0.1", - "@sentry/node": "^7.99.0", + "@sentry/node": "^7.101.0", "@types/response-time": "^2.3.8", "axios": "^1.6.7", "bcryptjs": "^2.4.3", @@ -73,33 +73,34 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "crypto-js": "^4.2.0", - "google-auth-library": "^9.6.2", + "google-auth-library": "^9.6.3", "helmet": "^7.1.0", "joi": "^17.12.1", "moment": "^2.30.1", "moment-timezone": "^0.5.45", - "mongoose": "^8.1.1", + "mongoose": "^8.1.2", "nest-winston": "^1.9.4", "nestjs-command": "^3.1.4", "nestjs-i18n": "^10.4.0", "passport": "^0.7.0", "passport-headerapikey": "^1.2.2", "passport-jwt": "^4.0.1", + "randexp": "^0.5.3", "reflect-metadata": "^0.2.1", "response-time": "^2.3.2", "rotating-file-stream": "^3.2.1", "rxjs": "^7.8.1", "ua-parser-js": "^1.0.37", "winston": "^3.11.0", - "winston-daily-rotate-file": "^4.7.1", + "winston-daily-rotate-file": "^5.0.0", "xlsx": "^0.18.5", "yargs": "^17.7.2", "yarn": "^1.22.21" }, "devDependencies": { - "@nestjs/cli": "^10.3.1", - "@nestjs/schematics": "^10.1.0", - "@nestjs/testing": "^10.3.1", + "@nestjs/cli": "^10.3.2", + "@nestjs/schematics": "^10.1.1", + "@nestjs/testing": "^10.3.3", "@types/bcryptjs": "^2.4.6", "@types/bytes": "^3.1.4", "@types/cors": "^2.8.17", @@ -110,18 +111,18 @@ "@types/lodash": "^4.14.202", "@types/ms": "^0.7.34", "@types/multer": "^1.4.11", - "@types/node": "^20.11.16", + "@types/node": "^20.11.17", "@types/passport-jwt": "^4.0.1", "@types/supertest": "^6.0.2", "@types/ua-parser-js": "^0.7.39", "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", "cspell": "^8.3.2", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "husky": "^9.0.10", + "husky": "^9.0.11", "jest": "^29.7.0", "prettier": "^3.2.5", "supertest": "^6.3.4", diff --git a/src/app/controllers/app.controller.ts b/src/app/controllers/app.controller.ts index eaaca1124..684535694 100644 --- a/src/app/controllers/app.controller.ts +++ b/src/app/controllers/app.controller.ts @@ -42,7 +42,7 @@ export class AppController { userAgent, date: newDate, format: this.helperDateService.format(newDate), - timestamp: this.helperDateService.timestamp(newDate), + timestamp: this.helperDateService.createTimestamp(newDate), }, }; } diff --git a/src/common/api-key/guards/x-api-key/api-key.x-api-key.guard.ts b/src/common/api-key/guards/x-api-key/api-key.x-api-key.guard.ts index 6cc690d6d..88497e1bb 100644 --- a/src/common/api-key/guards/x-api-key/api-key.x-api-key.guard.ts +++ b/src/common/api-key/guards/x-api-key/api-key.x-api-key.guard.ts @@ -5,16 +5,11 @@ import { Injectable, UnauthorizedException, } from '@nestjs/common'; -import { HelperNumberService } from 'src/common/helper/services/helper.number.service'; import { ENUM_API_KEY_STATUS_CODE_ERROR } from 'src/common/api-key/constants/api-key.status-code.constant'; import { BadRequestError } from 'passport-headerapikey'; @Injectable() export class ApiKeyXApiKeyGuard extends AuthGuard('x-api-key') { - constructor(private readonly helperNumberService: HelperNumberService) { - super(); - } - canActivate(context: ExecutionContext) { return super.canActivate(context); } @@ -35,7 +30,7 @@ export class ApiKeyXApiKeyGuard extends AuthGuard('x-api-key') { message: 'apiKey.error.keyNeeded', }); } else if (err) { - const statusCode: number = this.helperNumberService.create( + const statusCode: number = Number.parseInt( err.message as string ); diff --git a/src/common/api-key/services/api-key.service.ts b/src/common/api-key/services/api-key.service.ts index d25c61f28..1cced4a63 100644 --- a/src/common/api-key/services/api-key.service.ts +++ b/src/common/api-key/services/api-key.service.ts @@ -208,11 +208,11 @@ export class ApiKeyService implements IApiKeyService { } async createKey(): Promise { - return this.helperStringService.random(25, { + const random: string = this.helperStringService.random(25, { safe: false, upperCase: true, - prefix: `${this.env}_`, }); + return `${this.env}_${random}`; } async createSecret(): Promise { diff --git a/src/common/common.module.ts b/src/common/common.module.ts index 70deed5e2..a19150917 100644 --- a/src/common/common.module.ts +++ b/src/common/common.module.ts @@ -18,6 +18,7 @@ import { DATABASE_CONNECTION_NAME } from 'src/common/database/constants/database import { ENUM_APP_ENVIRONMENT } from 'src/app/constants/app.enum.constant'; import { APP_LANGUAGE } from 'src/app/constants/app.constant'; import { PolicyModule } from 'src/common/policy/policy.module'; +import { DebuggerLoggerModule } from 'src/common/debugger/debugger.logger.module'; @Module({ controllers: [], @@ -149,6 +150,7 @@ import { PolicyModule } from 'src/common/policy/policy.module'; ResponseModule, RequestModule, PolicyModule, + DebuggerLoggerModule, ApiKeyModule, AuthModule.forRoot(), ], diff --git a/src/common/debugger/debugger.logger.module.ts b/src/common/debugger/debugger.logger.module.ts new file mode 100644 index 000000000..03675180a --- /dev/null +++ b/src/common/debugger/debugger.logger.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { APP_INTERCEPTOR } from '@nestjs/core'; +import { DebuggerModule } from 'src/common/debugger/debugger.module'; +import { DebuggerInterceptor } from 'src/common/debugger/interceptors/debugger.logger.interceptor'; + +@Module({ + providers: [ + { + provide: APP_INTERCEPTOR, + useClass: DebuggerInterceptor, + }, + ], + exports: [], + controllers: [], + imports: [DebuggerModule], +}) +export class DebuggerLoggerModule {} diff --git a/src/common/debugger/interceptors/debugger.logger.interceptor.ts b/src/common/debugger/interceptors/debugger.logger.interceptor.ts new file mode 100644 index 000000000..f3701ef81 --- /dev/null +++ b/src/common/debugger/interceptors/debugger.logger.interceptor.ts @@ -0,0 +1,76 @@ +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler, +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { ConfigService } from '@nestjs/config'; +import { DebuggerService } from 'src/common/debugger/services/debugger.service'; +import { IRequestApp } from 'src/common/request/interfaces/request.interface'; +import { Response } from 'express'; + +@Injectable() +export class DebuggerInterceptor implements NestInterceptor> { + private readonly writeIntoFile: boolean; + + constructor( + private readonly configService: ConfigService, + private readonly debuggerService: DebuggerService + ) { + this.writeIntoFile = this.configService.get( + 'debugger.writeIntoFile' + ); + } + + async intercept( + context: ExecutionContext, + next: CallHandler + ): Promise | string>> { + if (context.getType() === 'http') { + const request: IRequestApp = context + .switchToHttp() + .getRequest(); + + console.log('aaa'); + + if (this.writeIntoFile) { + console.log('bbb'); + this.debuggerService.info({ + type: 'request', + method: request.method, + path: request.path, + originalUrl: request.originalUrl, + params: request.params, + body: request.body, + baseUrl: request.baseUrl, + query: request.query, + ip: request.ip, + hostname: request.hostname, + protocol: request.protocol, + }); + } + + return next.handle().pipe( + tap(() => { + console.log('ccc'); + const response: Response = context + .switchToHttp() + .getResponse(); + + if (this.writeIntoFile) { + console.log('ddd'); + this.debuggerService.info({ + type: 'response', + statusCode: response.statusCode, + message: response.statusMessage, + }); + } + }) + ); + } + + return next.handle(); + } +} diff --git a/src/common/debugger/services/debugger.options.service.ts b/src/common/debugger/services/debugger.options.service.ts index dc97e3e58..3c20146bf 100644 --- a/src/common/debugger/services/debugger.options.service.ts +++ b/src/common/debugger/services/debugger.options.service.ts @@ -17,9 +17,7 @@ export class DebuggerOptionService implements IDebuggerOptionService { const maxSize = this.configService.get('debugger.maxSize'); const maxFiles = this.configService.get('debugger.maxFiles'); - const transports: Transport[] | Transport = [ - new winston.transports.Console(), - ]; + const transports: Transport[] | Transport = []; if (writeIntoFile) { transports.push( @@ -44,17 +42,6 @@ export class DebuggerOptionService implements IDebuggerOptionService { level: 'info', }) ); - transports.push( - new DailyRotateFile({ - filename: `%DATE%.log`, - dirname: `logs/${DEBUGGER_NAME}/debug`, - datePattern: 'YYYY-MM-DD', - zippedArchive: true, - maxSize: maxSize, - maxFiles: maxFiles, - level: 'debug', - }) - ); } const loggerOptions: LoggerOptions = { diff --git a/src/common/doc/decorators/doc.decorator.ts b/src/common/doc/decorators/doc.decorator.ts index 2e9f49a1b..e48e226b7 100644 --- a/src/common/doc/decorators/doc.decorator.ts +++ b/src/common/doc/decorators/doc.decorator.ts @@ -37,14 +37,14 @@ import { ENUM_FILE_MIME } from 'src/common/file/constants/file.enum.constant'; import { ENUM_PAGINATION_ORDER_DIRECTION_TYPE } from 'src/common/pagination/constants/pagination.enum.constant'; import { ENUM_POLICY_STATUS_CODE_ERROR } from 'src/common/policy/constants/policy.status-code.constant'; import { ENUM_REQUEST_STATUS_CODE_ERROR } from 'src/common/request/constants/request.status-code.constant'; -import { ResponseDefaultSerialization } from 'src/common/response/serializations/response.default.serialization'; +import { ResponseSerialization } from 'src/common/response/serializations/response.serialization'; import { ResponsePagingSerialization } from 'src/common/response/serializations/response.paging.serialization'; import { ENUM_ROLE_STATUS_CODE_ERROR } from 'src/modules/role/constants/role.status-code.constant'; export function DocDefault(options: IDocDefaultOptions): MethodDecorator { const docs = []; const schema: Record = { - allOf: [{ $ref: getSchemaPath(ResponseDefaultSerialization) }], + allOf: [{ $ref: getSchemaPath(ResponseSerialization) }], properties: { message: { example: options.messagePath, @@ -67,7 +67,7 @@ export function DocDefault(options: IDocDefaultOptions): MethodDecorator { } return applyDecorators( - ApiExtraModels(ResponseDefaultSerialization), + ApiExtraModels(ResponseSerialization), ApiResponse({ status: options.httpStatus, schema, @@ -85,7 +85,7 @@ export function DocOneOf( for (const doc of documents) { const oneOfSchema: Record = { - allOf: [{ $ref: getSchemaPath(ResponseDefaultSerialization) }], + allOf: [{ $ref: getSchemaPath(ResponseSerialization) }], properties: { message: { example: doc.messagePath, @@ -111,7 +111,7 @@ export function DocOneOf( } return applyDecorators( - ApiExtraModels(ResponseDefaultSerialization), + ApiExtraModels(ResponseSerialization), ApiResponse({ status: httpStatus, schema: { @@ -131,7 +131,7 @@ export function DocAnyOf( for (const doc of documents) { const anyOfSchema: Record = { - allOf: [{ $ref: getSchemaPath(ResponseDefaultSerialization) }], + allOf: [{ $ref: getSchemaPath(ResponseSerialization) }], properties: { message: { example: doc.messagePath, @@ -157,7 +157,7 @@ export function DocAnyOf( } return applyDecorators( - ApiExtraModels(ResponseDefaultSerialization), + ApiExtraModels(ResponseSerialization), ApiResponse({ status: httpStatus, schema: { @@ -177,7 +177,7 @@ export function DocAllOf( for (const doc of documents) { const allOfSchema: Record = { - allOf: [{ $ref: getSchemaPath(ResponseDefaultSerialization) }], + allOf: [{ $ref: getSchemaPath(ResponseSerialization) }], properties: { message: { example: doc.messagePath, @@ -203,7 +203,7 @@ export function DocAllOf( } return applyDecorators( - ApiExtraModels(ResponseDefaultSerialization), + ApiExtraModels(ResponseSerialization), ApiResponse({ status: httpStatus, schema: { diff --git a/src/common/error/filters/error.http.filter.ts b/src/common/error/filters/error.http.filter.ts index d1d18f7a3..2ee9fc537 100644 --- a/src/common/error/filters/error.http.filter.ts +++ b/src/common/error/filters/error.http.filter.ts @@ -16,9 +16,9 @@ import { DatabaseDefaultUUID } from 'src/common/database/constants/database.func import { ERROR_TYPE } from 'src/common/error/constants/error.enum.constant'; import { IErrorException, + IErrorValidationImport, IErrors, IErrorsImport, - IValidationErrorImport, } from 'src/common/error/interfaces/error.interface'; import { ErrorMetadataSerialization } from 'src/common/error/serializations/error.serialization'; import { HelperDateService } from 'src/common/helper/services/helper.date.service'; @@ -58,7 +58,7 @@ export class ErrorHttpFilter implements ExceptionFilter { const __timestamp = request.__xTimestamp ?? request.__timestamp ?? - this.helperDateService.timestamp(); + this.helperDateService.createTimestamp(); const __timezone = request.__timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -112,7 +112,7 @@ export class ErrorHttpFilter implements ExceptionFilter { errors = responseException._errorType === ERROR_TYPE.IMPORT ? this.messageService.getImportErrorsMessage( - responseException.errors as IValidationErrorImport[], + responseException.errors as IErrorValidationImport[], { customLanguages: __customLang } ) : this.messageService.getRequestErrorsMessage( diff --git a/src/common/error/interfaces/error.interface.ts b/src/common/error/interfaces/error.interface.ts index b3160efbd..a74bcd48d 100644 --- a/src/common/error/interfaces/error.interface.ts +++ b/src/common/error/interfaces/error.interface.ts @@ -1,5 +1,6 @@ import { ValidationError } from 'class-validator'; import { ERROR_TYPE } from 'src/common/error/constants/error.enum.constant'; +import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; import { IMessage } from 'src/common/message/interfaces/message.interface'; import { IResponseCustomPropertyMetadata } from 'src/common/response/interfaces/response.interface'; @@ -10,14 +11,12 @@ export interface IErrors { } // error import -export interface IErrorsImport { +export interface IErrorsImport extends Pick { row: number; - file?: string; - sheet?: number; errors: IErrors[]; } -export interface IValidationErrorImport extends Omit { +export interface IErrorValidationImport extends Omit { errors: ValidationError[]; } @@ -36,7 +35,7 @@ export interface IErrorMetadata { export interface IErrorException { statusCode: number; message: string; - errors?: ValidationError[] | IValidationErrorImport[]; + errors?: ValidationError[] | IErrorValidationImport[]; data?: Record; _error?: string; _errorType?: ERROR_TYPE; diff --git a/src/common/error/serializations/error.serialization.ts b/src/common/error/serializations/error.serialization.ts index fea3c0348..21eaf3dd8 100644 --- a/src/common/error/serializations/error.serialization.ts +++ b/src/common/error/serializations/error.serialization.ts @@ -1,3 +1,3 @@ -import { ResponseMetadataSerialization } from 'src/common/response/serializations/response.default.serialization'; +import { ResponseMetadataSerialization } from 'src/common/response/serializations/response.serialization'; export class ErrorMetadataSerialization extends ResponseMetadataSerialization {} diff --git a/src/common/file/constants/file.enum.constant.ts b/src/common/file/constants/file.enum.constant.ts index 628692a76..ffce51dfe 100644 --- a/src/common/file/constants/file.enum.constant.ts +++ b/src/common/file/constants/file.enum.constant.ts @@ -2,7 +2,6 @@ export enum ENUM_FILE_MIME { JPG = 'image/jpg', JPEG = 'image/jpeg', PNG = 'image/png', - XLS = 'application/vnd.ms-excel', XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', CSV = 'text/csv', PDF = 'application/pdf', diff --git a/src/common/file/interfaces/file.interface.ts b/src/common/file/interfaces/file.interface.ts index 6effe5ccd..2ee456d56 100644 --- a/src/common/file/interfaces/file.interface.ts +++ b/src/common/file/interfaces/file.interface.ts @@ -1,18 +1,18 @@ import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; -export type IFile = Omit; - -export type IFileExtract = IFile & { - extract: IHelperFileRows[]; - dto?: T[]; -}; +export interface IFile extends Omit { + password?: string; +} -export type IFileExtractAllSheets = IFile & { - extracts: IHelperFileRows[][]; - dto?: T[][]; +export type IFileExtract = IFile & { + extracts: IHelperFileRows[]; }; export interface IFileMultipleField { field: string; maxFiles: number; } + +export interface IFileExtractOptions { + password?: string; +} diff --git a/src/common/file/pipes/file.excel-extract.pipe.ts b/src/common/file/pipes/file.excel-extract.pipe.ts index f1a3cdaf7..157d6da82 100644 --- a/src/common/file/pipes/file.excel-extract.pipe.ts +++ b/src/common/file/pipes/file.excel-extract.pipe.ts @@ -2,53 +2,38 @@ import { Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; import { PipeTransform } from '@nestjs/common/interfaces'; import { ENUM_FILE_MIME } from 'src/common/file/constants/file.enum.constant'; import { ENUM_FILE_STATUS_CODE_ERROR } from 'src/common/file/constants/file.status-code.constant'; -import { - IFile, - IFileExtract, - IFileExtractAllSheets, -} from 'src/common/file/interfaces/file.interface'; +import { IFile, IFileExtract } from 'src/common/file/interfaces/file.interface'; import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; import { HelperFileService } from 'src/common/helper/services/helper.file.service'; -// only for excel +// Support excel and csv @Injectable() export class FileExcelExtractPipe implements PipeTransform { constructor(private readonly helperFileService: HelperFileService) {} - async transform( - value: IFile | IFile[] - ): Promise | IFileExtract[]> { + async transform(value: IFile): Promise> { if (!value) { return; } - if (Array.isArray(value)) { - const extracts: IFileExtract[] = []; + await this.validate(value); - for (const val of value) { - await this.validate(val.mimetype); + const extracts: IHelperFileRows[] = this.extracts(value); - const extract: IFileExtract = await this.extract(val); - extracts.push(extract); - } - - return extracts; - } - - const file: IFile = value as IFile; - await this.validate(file.mimetype); - - const extract: IFileExtract = await this.extract(file); - - return extract; + return { + ...value, + extracts, + }; } - async validate(mimetype: string): Promise { - if ( - ![ENUM_FILE_MIME.CSV, ENUM_FILE_MIME.XLS, ENUM_FILE_MIME.XLSX].find( - (val) => val === mimetype.toLowerCase() - ) - ) { + async validate(value: IFile): Promise { + const mimetype = value.mimetype.toLowerCase(); + const supportedFiles: string[] = [ + ENUM_FILE_MIME.CSV, + ENUM_FILE_MIME.XLSX, + ]; + + if (!supportedFiles.includes(mimetype)) { throw new UnsupportedMediaTypeException({ statusCode: ENUM_FILE_STATUS_CODE_ERROR.FILE_EXTENSION_ERROR, message: 'file.error.mimeInvalid', @@ -56,73 +41,30 @@ export class FileExcelExtractPipe implements PipeTransform { } } - async extract(value: IFile): Promise> { - const extracts: IHelperFileRows[][] = - this.helperFileService.readExcelFromBuffer(value.buffer, { - sheet: 0, - }); - - return { - ...value, - extract: extracts[0], - }; - } -} - -// only for excel -@Injectable() -export class FileExcelExtractAllSheetPipe implements PipeTransform { - constructor(private readonly helperFileService: HelperFileService) {} - - async transform( - value: IFile | IFile[] - ): Promise | IFileExtractAllSheets[]> { - if (!value) { - return; - } - - if (Array.isArray(value)) { - const extracts: IFileExtractAllSheets[] = []; - - for (const val of value) { - await this.validate(val.mimetype); - - const extract: IFileExtractAllSheets = - await this.extract(val); - extracts.push(extract); - } - - return extracts; + extracts(value: IFile): IHelperFileRows[] { + if (value.mimetype === ENUM_FILE_MIME.CSV) { + return this.extractsCsv(value); } - const file: IFile = value as IFile; - await this.validate(file.mimetype); - - const extract: IFileExtractAllSheets = await this.extract(file); - - return extract; + return this.extractsExcel(value); } - async validate(mimetype: string): Promise { - if ( - ![ENUM_FILE_MIME.CSV, ENUM_FILE_MIME.XLS, ENUM_FILE_MIME.XLSX].find( - (val) => val === mimetype.toLowerCase() - ) - ) { - throw new UnsupportedMediaTypeException({ - statusCode: ENUM_FILE_STATUS_CODE_ERROR.FILE_EXTENSION_ERROR, - message: 'file.error.mimeInvalid', - }); - } + extractsCsv(value: IFile): IHelperFileRows[] { + const extracts: IHelperFileRows = this.helperFileService.readCsv( + value.buffer + ); + + return [extracts]; } - async extract(value: IFile): Promise> { - const extracts: IHelperFileRows[][] = - this.helperFileService.readExcelFromBuffer(value.buffer); + extractsExcel(value: IFile): IHelperFileRows[] { + const extracts: IHelperFileRows[] = this.helperFileService.readExcel( + value.buffer, + { + password: value?.password, + } + ); - return { - ...value, - extracts: extracts, - }; + return extracts; } } diff --git a/src/common/file/pipes/file.excel-password.pipe.ts b/src/common/file/pipes/file.excel-password.pipe.ts new file mode 100644 index 000000000..239dacc61 --- /dev/null +++ b/src/common/file/pipes/file.excel-password.pipe.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@nestjs/common'; +import { PipeTransform } from '@nestjs/common/interfaces'; +import { IFile } from 'src/common/file/interfaces/file.interface'; + +// Support excel and csv +@Injectable() +export class FileExcelPasswordPipe implements PipeTransform { + constructor(readonly password: string) {} + + async transform(value: IFile): Promise { + if (!value) { + return; + } + + return { + ...value, + password: this.password, + }; + } +} diff --git a/src/common/file/pipes/file.excel-validation.pipe.ts b/src/common/file/pipes/file.excel-validation.pipe.ts index 951648529..75f29e379 100644 --- a/src/common/file/pipes/file.excel-validation.pipe.ts +++ b/src/common/file/pipes/file.excel-validation.pipe.ts @@ -1,95 +1,37 @@ -import { - BadRequestException, - Injectable, - UnprocessableEntityException, - UnsupportedMediaTypeException, -} from '@nestjs/common'; +import { Injectable, UnprocessableEntityException } from '@nestjs/common'; import { PipeTransform } from '@nestjs/common/interfaces'; import { validate, ValidationError } from 'class-validator'; import { ClassConstructor, plainToInstance } from 'class-transformer'; -import { IValidationErrorImport } from 'src/common/error/interfaces/error.interface'; -import { - IFileExtract, - IFileExtractAllSheets, -} from 'src/common/file/interfaces/file.interface'; +import { IFileExtract } from 'src/common/file/interfaces/file.interface'; import { ENUM_FILE_STATUS_CODE_ERROR } from 'src/common/file/constants/file.status-code.constant'; import { ERROR_TYPE } from 'src/common/error/constants/error.enum.constant'; -import { ENUM_FILE_MIME } from 'src/common/file/constants/file.enum.constant'; +import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; +import { IErrorValidationImport } from 'src/common/error/interfaces/error.interface'; // only for excel // must use after FileExtractPipe @Injectable() -export class FileExcelValidationPipe implements PipeTransform { +export class FileExcelValidationPipe + implements PipeTransform +{ constructor(private readonly dto: ClassConstructor) {} - async transform( - value: IFileExtract | IFileExtract[] - ): Promise | IFileExtract[]> { + async transform(value: IFileExtract): Promise> { if (!value) { return; } - if (Array.isArray(value)) { - const classTransforms: IFileExtract[] = []; - for (const val of value) { - await this.validate(val); - - const classTransform: T[] = await this.transformExtract( - this.dto, - val.extract - ); - - await this.validateExtract(classTransform, val.originalname, 0); - - const classTransformMerge: IFileExtract = - await this.transformMerge(val, classTransform); - classTransforms.push(classTransformMerge); - } - - return classTransforms; - } - - const file: IFileExtract = value as IFileExtract; - - await this.validate(file); - - const classTransform: T[] = await this.transformExtract( - this.dto, - file.extract - ); + await this.validate(value); + const dtos = await this.validateExtract(value, this.dto); - await this.validateExtract(classTransform, file.originalname, 0); - - return this.transformMerge(value, classTransform); - } - - async transformMerge( - value: IFileExtract, - classTransform: T[] - ): Promise> { - value.dto = classTransform; - - return value; - } - - async transformExtract( - classDtos: ClassConstructor, - extract: Record[] - ): Promise { - return plainToInstance(classDtos, extract); + return { + ...value, + extracts: dtos, + }; } - async validate(value: IFileExtract): Promise { - if ( - ![ENUM_FILE_MIME.CSV, ENUM_FILE_MIME.XLS, ENUM_FILE_MIME.XLSX].find( - (val) => val === value.mimetype.toLowerCase() - ) - ) { - throw new UnsupportedMediaTypeException({ - statusCode: ENUM_FILE_STATUS_CODE_ERROR.FILE_EXTENSION_ERROR, - message: 'file.error.mimeInvalid', - }); - } else if (!value.extract) { + async validate(value: IFileExtract): Promise { + if (!value.extracts || value.extracts.length === 0) { throw new UnprocessableEntityException({ statusCode: ENUM_FILE_STATUS_CODE_ERROR.FILE_NEED_EXTRACT_FIRST_ERROR, @@ -101,163 +43,30 @@ export class FileExcelValidationPipe implements PipeTransform { } async validateExtract( - classTransform: T[], - filename: string, - sheet: number - ): Promise { - const errors: IValidationErrorImport[] = []; - for (const [index, clsTransform] of classTransform.entries()) { + value: IFileExtract, + classDtos: ClassConstructor + ): Promise[]> { + const errors: IErrorValidationImport[] = []; + const dtos: IHelperFileRows[] = []; + + for (const [index, extract] of value.extracts.entries()) { + const dto: T[] = plainToInstance(classDtos, extract.data); const validator: ValidationError[] = await validate( - clsTransform as Record + dto as Record ); + if (validator.length > 0) { errors.push({ row: index, - file: filename, - sheet, + sheetName: extract.sheetName, errors: validator, }); } - } - - if (errors.length > 0) { - throw new UnprocessableEntityException({ - statusCode: - ENUM_FILE_STATUS_CODE_ERROR.FILE_VALIDATION_DTO_ERROR, - message: 'file.error.validationDto', - errors, - _errorType: ERROR_TYPE.IMPORT, - }); - } - - return; - } -} - -@Injectable() -export class FileExcelValidationAllSheetPipe - implements PipeTransform -{ - constructor(private readonly dto: T) {} - - async transform( - value: IFileExtractAllSheets | IFileExtractAllSheets[] - ): Promise | IFileExtractAllSheets[]> { - if (!value) { - return; - } - - if (Array.isArray(value)) { - for (let val of value) { - val.dto = Array(val.extracts.length).fill([]); - - const file: IFileExtractAllSheets = - val as IFileExtractAllSheets; - - await this.validate(file); - - for (let i = 0; i < (this.dto as Array).length; i++) { - const classTransform: T[] = await this.transformExtract( - this.dto[i] as ClassConstructor, - val.extracts[i] - ); - - await this.validateExtract( - classTransform, - file.originalname, - i - ); - - val = await this.transformMerge(val, classTransform, i); - } - } - - return value; - } - - value.dto = Array(value.extracts.length).fill([]); - - const file: IFileExtractAllSheets = - value as IFileExtractAllSheets; - - await this.validate(file); - - for (let i = 0; i < (this.dto as Array).length; i++) { - const classTransform: T[] = await this.transformExtract( - this.dto[i] as ClassConstructor, - value.extracts[i] - ); - - await this.validateExtract(classTransform, file.originalname, i); - - value = await this.transformMerge(value, classTransform, i); - } - - return value; - } - - async transformMerge( - value: IFileExtractAllSheets, - classTransform: T[], - sheet: number - ): Promise> { - value.dto[sheet] = classTransform; - - return value; - } - - async transformExtract( - classDtos: ClassConstructor, - extract: Record[] - ): Promise { - return plainToInstance(classDtos, extract); - } - async validate(value: IFileExtractAllSheets): Promise { - if ( - ![ENUM_FILE_MIME.CSV, ENUM_FILE_MIME.XLS, ENUM_FILE_MIME.XLSX].find( - (val) => val === value.mimetype.toLowerCase() - ) - ) { - throw new UnsupportedMediaTypeException({ - statusCode: ENUM_FILE_STATUS_CODE_ERROR.FILE_EXTENSION_ERROR, - message: 'file.error.mimeInvalid', + dtos.push({ + sheetName: extract.sheetName, + data: dto, }); - } else if (!value.extracts) { - throw new UnprocessableEntityException({ - statusCode: - ENUM_FILE_STATUS_CODE_ERROR.FILE_NEED_EXTRACT_FIRST_ERROR, - message: 'file.error.needExtractFirst', - }); - } else if (value.extracts.length !== (this.dto as Array).length) { - throw new BadRequestException({ - statusCode: - ENUM_FILE_STATUS_CODE_ERROR.FILE_VALIDATION_ALL_SHEET_DTO_ERROR, - message: 'file.error.allSheetDto', - }); - } - - return; - } - - async validateExtract( - classTransform: T[], - filename: string, - sheet: number - ): Promise { - const errors: IValidationErrorImport[] = []; - for (const [index, clsTransform] of classTransform.entries()) { - const validator: ValidationError[] = await validate( - clsTransform as Record - ); - if (validator.length > 0) { - errors.push({ - row: index, - file: filename, - sheet, - errors: validator, - }); - } } if (errors.length > 0) { @@ -270,6 +79,6 @@ export class FileExcelValidationAllSheetPipe }); } - return; + return dtos; } } diff --git a/src/common/helper/constants/helper.enum.constant.ts b/src/common/helper/constants/helper.enum.constant.ts index b61842f07..3e3c4224a 100644 --- a/src/common/helper/constants/helper.enum.constant.ts +++ b/src/common/helper/constants/helper.enum.constant.ts @@ -29,8 +29,7 @@ export enum ENUM_HELPER_DATE_DIFF { DAYS = 'days', } -export enum ENUM_HELPER_FILE_TYPE { +export enum ENUM_HELPER_FILE_EXCEL_TYPE { XLSX = 'xlsx', - XLS = 'xls', CSV = 'csv', } diff --git a/src/common/helper/interfaces/helper.array-service.interface.ts b/src/common/helper/interfaces/helper.array-service.interface.ts index dc4a6495a..3757a23d2 100644 --- a/src/common/helper/interfaces/helper.array-service.interface.ts +++ b/src/common/helper/interfaces/helper.array-service.interface.ts @@ -1,34 +1,16 @@ export interface IHelperArrayService { - getCombinations( - list: T[][], - start: number, - result: T[][], - current: T[] - ): T[][]; - getLast(array: T[]): T; - getFirst(array: T[]): T; - getFirstByIndex(array: T[], index: number): T; - getLastByIndex(array: T[], index: number): T; - takeFirst(array: T[], length: number): T[]; - takeLast(array: T[], length: number): T[]; - indexOf(array: T[], value: T): number; - lastIndexOf(array: T[], value: T): number; - remove(array: T[], value: T): T[]; - removeFromLeft(array: T[], length: number): T[]; - removeFromRight(array: Array, length: number): T[]; - join(array: Array, delimiter: string): string; - split(str: string, delimiter: string): string[]; - reverse(array: T[]): T[]; + getCombinations(...list: T[][]): T[]; + getFromLeft(array: T[], length: number): T[]; + getFromRight(array: T[], length: number): T[]; + getDifference(a: T[], b: T[]): T[]; + getIntersection(a: T[], b: T[]): T[]; + concat(a: T[], b: T[]): T[]; + concatUnique(a: T[], b: T[]): T[]; unique(array: T[]): T[]; shuffle(array: T[]): T[]; - merge(a: T[], b: T[]): T[]; - mergeUnique(a: T[], b: T[]): T[]; equals(a: T[], b: T[]): boolean; notEquals(a: T[], b: T[]): boolean; in(a: T[], b: T[]): boolean; notIn(a: T[], b: T[]): boolean; - intersection(a: T[], b: T[]): T[]; - difference(a: T[], b: T[]): T[]; - includes(a: T[], b: T): boolean; chunk(a: T[], size: number): T[][]; } diff --git a/src/common/helper/interfaces/helper.date-service.interface.ts b/src/common/helper/interfaces/helper.date-service.interface.ts index 80c87a814..2f07e5f7d 100644 --- a/src/common/helper/interfaces/helper.date-service.interface.ts +++ b/src/common/helper/interfaces/helper.date-service.interface.ts @@ -1,10 +1,10 @@ import { - IHelperDateExtractDate, - IHelperDateOptionsBackward, - IHelperDateOptionsCreate, - IHelperDateOptionsDiff, - IHelperDateOptionsFormat, - IHelperDateOptionsForward, + IHelperDateBackwardOptions, + IHelperDateCreateOptions, + IHelperDateDiffOptions, + IHelperDateFormatOptions, + IHelperDateForwardOptions, + IHelperDateRoundDownOptions, IHelperDateSetTimeOptions, } from 'src/common/helper/interfaces/helper.interface'; @@ -13,54 +13,50 @@ export interface IHelperDateService { diff( dateOne: Date, dateTwoMoreThanDateOne: Date, - options?: IHelperDateOptionsDiff + options?: IHelperDateDiffOptions ): number; check(date: string | Date | number): boolean; - checkDateTime(date: string | Date | number): boolean; + checkIso(date: string | Date | number): boolean; checkTimestamp(timestamp: number): boolean; create( date?: string | number | Date, - options?: IHelperDateOptionsCreate + options?: IHelperDateCreateOptions ): Date; - timestamp( + createTimestamp( date?: string | number | Date, - options?: IHelperDateOptionsCreate + options?: IHelperDateCreateOptions ): number; - format(date: Date, options?: IHelperDateOptionsFormat): string; - formatIsoDuration(inMinutes: number): string; - forwardInMilliseconds( - milliseconds: number, - options?: IHelperDateOptionsForward - ): Date; - backwardInMilliseconds( - milliseconds: number, - options?: IHelperDateOptionsBackward - ): Date; + format(date: Date, options?: IHelperDateFormatOptions): string; + formatIsoDurationFromMinutes(minutes: number): string; + formatIsoDurationFromHours(hours: number): string; + formatIsoDurationFromDays(days: number): string; forwardInSeconds( seconds: number, - options?: IHelperDateOptionsForward + options?: IHelperDateForwardOptions ): Date; backwardInSeconds( seconds: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date; forwardInMinutes( minutes: number, - options?: IHelperDateOptionsForward + options?: IHelperDateForwardOptions ): Date; backwardInMinutes( minutes: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date; - forwardInHours(hours: number, options?: IHelperDateOptionsForward): Date; - backwardInHours(hours: number, options?: IHelperDateOptionsBackward): Date; - forwardInDays(days: number, options?: IHelperDateOptionsForward): Date; - backwardInDays(days: number, options?: IHelperDateOptionsBackward): Date; - forwardInMonths(months: number, options?: IHelperDateOptionsForward): Date; + forwardInHours(hours: number, options?: IHelperDateForwardOptions): Date; + backwardInHours(hours: number, options?: IHelperDateBackwardOptions): Date; + forwardInDays(days: number, options?: IHelperDateForwardOptions): Date; + backwardInDays(days: number, options?: IHelperDateBackwardOptions): Date; + forwardInMonths(months: number, options?: IHelperDateForwardOptions): Date; backwardInMonths( months: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date; + forwardInYears(years: number, options?: IHelperDateForwardOptions): Date; + backwardInYears(years: number, options?: IHelperDateBackwardOptions): Date; endOfMonth(date?: Date): Date; startOfMonth(date?: Date): Date; endOfYear(date?: Date): Date; @@ -69,15 +65,15 @@ export interface IHelperDateService { startOfDay(date?: Date): Date; setTime( date: Date, - { hour, minute, second }: IHelperDateSetTimeOptions + { hour, minute, second, millisecond }: IHelperDateSetTimeOptions ): Date; addTime( date: Date, - { hour, minute, second }: IHelperDateSetTimeOptions + { hour, minute, second, millisecond }: IHelperDateSetTimeOptions ): Date; - minusTime( + subtractTime( date: Date, { hour, minute, second }: IHelperDateSetTimeOptions ): Date; - extractDate(date: string | Date | number): IHelperDateExtractDate; + roundDown(date: Date, options?: IHelperDateRoundDownOptions): Date; } diff --git a/src/common/helper/interfaces/helper.encryption-service.interface.ts b/src/common/helper/interfaces/helper.encryption-service.interface.ts index 96ea6b444..ae8ad9f75 100644 --- a/src/common/helper/interfaces/helper.encryption-service.interface.ts +++ b/src/common/helper/interfaces/helper.encryption-service.interface.ts @@ -6,7 +6,7 @@ import { export interface IHelperEncryptionService { base64Encrypt(data: string): string; base64Decrypt(data: string): string; - base64Compare(clientBasicToken: string, ourBasicToken: string): boolean; + base64Compare(basicToken1: string, basicToken2: string): boolean; aes256Encrypt( data: string | Record | Record[], key: string, @@ -17,6 +17,7 @@ export interface IHelperEncryptionService { key: string, iv: string ): string | Record | Record[]; + aes256Compare(aes1: string, aes2: string): boolean; jwtEncrypt( payload: Record, options: IHelperJwtOptions diff --git a/src/common/helper/interfaces/helper.file-service.interface.ts b/src/common/helper/interfaces/helper.file-service.interface.ts index 346326562..4d30346ad 100644 --- a/src/common/helper/interfaces/helper.file-service.interface.ts +++ b/src/common/helper/interfaces/helper.file-service.interface.ts @@ -1,23 +1,17 @@ import { - IHelperFileWriteExcelOptions, - IHelperFileReadExcelOptions, + IHelperFileReadOptions, IHelperFileRows, - IHelperFileCreateExcelWorkbookOptions, } from 'src/common/helper/interfaces/helper.interface'; -import { WorkBook } from 'xlsx'; export interface IHelperFileService { - createExcelWorkbook( - rows: IHelperFileRows[], - options?: IHelperFileCreateExcelWorkbookOptions - ): WorkBook; - writeExcelToBuffer( - workbook: WorkBook, - options?: IHelperFileWriteExcelOptions + writeCsv(rows: IHelperFileRows): Buffer; + writeExcel( + rows: IHelperFileRows[], + options?: IHelperFileReadOptions ): Buffer; - readExcelFromBuffer( + readCsv(file: Buffer): IHelperFileRows; + readExcel( file: Buffer, - options?: IHelperFileReadExcelOptions - ): IHelperFileRows[][]; - convertToBytes(megabytes: string): number; + options?: IHelperFileReadOptions + ): IHelperFileRows[]; } diff --git a/src/common/helper/interfaces/helper.interface.ts b/src/common/helper/interfaces/helper.interface.ts index dc7029709..5000a91db 100644 --- a/src/common/helper/interfaces/helper.interface.ts +++ b/src/common/helper/interfaces/helper.interface.ts @@ -1,7 +1,6 @@ import { ENUM_HELPER_DATE_DIFF, ENUM_HELPER_DATE_FORMAT, - ENUM_HELPER_FILE_TYPE, } from 'src/common/helper/constants/helper.enum.constant'; // Helper Encryption @@ -23,7 +22,14 @@ export interface IHelperJwtOptions export interface IHelperStringRandomOptions { upperCase?: boolean; safe?: boolean; - prefix?: string; +} + +export interface IHelperStringCurrencyOptions { + locale?: string; +} + +export interface IHelperStringPasswordOptions { + length: number; } // Helper Date @@ -31,58 +37,46 @@ export interface IHelperDateSetTimeOptions { hour?: number; minute?: number; second?: number; + millisecond?: number; } -export interface IHelperDateExtractDate { - date: Date; - day: string; - month: string; - year: string; -} - -export interface IHelperDateOptionsDiff { +export interface IHelperDateDiffOptions { format?: ENUM_HELPER_DATE_DIFF; } -export interface IHelperDateOptionsCreate { +export interface IHelperDateCreateOptions { startOfDay?: boolean; } -export interface IHelperDateOptionsFormat { +export interface IHelperDateFormatOptions { format?: ENUM_HELPER_DATE_FORMAT | string; } -export interface IHelperDateOptionsForward { +export interface IHelperDateForwardOptions { fromDate?: Date; } -export type IHelperDateOptionsBackward = IHelperDateOptionsForward; +export type IHelperDateBackwardOptions = IHelperDateForwardOptions; -export interface IHelperDateOptionsRoundDown { +export interface IHelperDateRoundDownOptions { hour: boolean; minute: boolean; second: boolean; + millisecond: boolean; } // Helper File -export type IHelperFileRows = Record; - -export interface IHelperFileWriteExcelOptions { - password?: string; - type?: ENUM_HELPER_FILE_TYPE; -} - -export interface IHelperFileCreateExcelWorkbookOptions { +export interface IHelperFileRows { + data: T[]; sheetName?: string; } -export interface IHelperFileReadExcelOptions { - sheet?: string | number; +export interface IHelperFileReadOptions { password?: string; } -// helper google +// Helper google export interface IHelperGooglePayload { email: string; diff --git a/src/common/helper/interfaces/helper.number-service.interface.ts b/src/common/helper/interfaces/helper.number-service.interface.ts index b5fab0347..4b8596ce1 100644 --- a/src/common/helper/interfaces/helper.number-service.interface.ts +++ b/src/common/helper/interfaces/helper.number-service.interface.ts @@ -1,6 +1,5 @@ export interface IHelperNumberService { check(number: string): boolean; - create(number: string): number; random(length: number): number; randomInRange(min: number, max: number): number; percent(value: number, total: number): number; diff --git a/src/common/helper/interfaces/helper.string-service.interface.ts b/src/common/helper/interfaces/helper.string-service.interface.ts index c0e8fa009..a78e8edea 100644 --- a/src/common/helper/interfaces/helper.string-service.interface.ts +++ b/src/common/helper/interfaces/helper.string-service.interface.ts @@ -1,13 +1,26 @@ -import { IHelperStringRandomOptions } from 'src/common/helper/interfaces/helper.interface'; +import { + IHelperStringCurrencyOptions, + IHelperStringPasswordOptions, + IHelperStringRandomOptions, +} from 'src/common/helper/interfaces/helper.interface'; export interface IHelperStringService { - checkEmail(email: string): boolean; - randomReference(length: number, prefix?: string): string; + randomReference(length: number): string; random(length: number, options?: IHelperStringRandomOptions): string; - censor(value: string): string; - checkPasswordWeak(password: string, length?: number): boolean; - checkPasswordMedium(password: string, length?: number): boolean; - checkPasswordStrong(password: string, length?: number): boolean; + censor(text: string): string; + checkEmail(email: string): boolean; + checkPasswordWeak( + password: string, + options?: IHelperStringPasswordOptions + ): boolean; + checkPasswordMedium( + password: string, + options?: IHelperStringPasswordOptions + ): boolean; + checkPasswordStrong( + password: string, + options?: IHelperStringPasswordOptions + ): boolean; checkSafeString(text: string): boolean; - formatCurrency(num: number): string; + formatCurrency(num: number, options?: IHelperStringCurrencyOptions): string; } diff --git a/src/common/helper/services/helper.array.service.ts b/src/common/helper/services/helper.array.service.ts index 7b588963e..f00aad218 100644 --- a/src/common/helper/services/helper.array.service.ts +++ b/src/common/helper/services/helper.array.service.ts @@ -4,80 +4,33 @@ import { IHelperArrayService } from 'src/common/helper/interfaces/helper.array-s @Injectable() export class HelperArrayService implements IHelperArrayService { - getCombinations( - list: T[][], - start = 0, - result: T[][] = [], - current: T[] = [] - ): T[][] { - if (start === list.length) result.push(current); - else - list[start].forEach((item) => - this.getCombinations(list, start + 1, result, [ - ...current, - item, - ]) - ); - - return result; - } - - getLast(array: T[]): T { - return _.last(array); - } - - getFirst(array: T[]): T { - return _.first(array); - } - - getFirstByIndex(array: T[], index: number): T { - return _.nth(array, index); - } - - getLastByIndex(array: T[], index: number): T { - return _.nth(array, -Math.abs(index)); + getCombinations(...list: T[][]): T[] { + // TODO: + return []; } - takeFirst(array: T[], length: number): T[] { + getFromLeft(array: T[], length: number): T[] { return _.take(array, length); } - takeLast(array: T[], length: number): T[] { + getFromRight(array: T[], length: number): T[] { return _.takeRight(array, length); } - indexOf(array: T[], value: T): number { - return _.indexOf(array, value); - } - - lastIndexOf(array: T[], value: T): number { - return _.lastIndexOf(array, value); - } - - remove(array: T[], value: T): T[] { - return _.remove(array, function (n) { - return n === value; - }); - } - - removeFromLeft(array: T[], length: number): T[] { - return _.drop(array, length); - } - - removeFromRight(array: Array, length: number): T[] { - return _.dropRight(array, length); + getDifference(a: T[], b: T[]): T[] { + return _.difference(a, b); } - join(array: Array, delimiter: string): string { - return _.join(array, delimiter); + getIntersection(a: T[], b: T[]): T[] { + return _.intersection(a, b); } - split(str: string, delimiter: string): string[] { - return _.split(str, delimiter); + concat(a: T[], b: T[]): T[] { + return _.concat(a, b); } - reverse(array: T[]): T[] { - return _.reverse(array); + concatUnique(a: T[], b: T[]): T[] { + return _.union(a, b); } unique(array: T[]): T[] { @@ -88,14 +41,6 @@ export class HelperArrayService implements IHelperArrayService { return _.shuffle(array); } - merge(a: T[], b: T[]): T[] { - return _.concat(a, b); - } - - mergeUnique(a: T[], b: T[]): T[] { - return _.union(a, b); - } - equals(a: T[], b: T[]): boolean { return _.isEqual(a, b); } @@ -112,18 +57,6 @@ export class HelperArrayService implements IHelperArrayService { return _.intersection(a, b).length === 0; } - intersection(a: T[], b: T[]): T[] { - return _.intersection(a, b); - } - - difference(a: T[], b: T[]): T[] { - return _.difference(a, b); - } - - includes(a: T[], b: T): boolean { - return _.includes(a, b); - } - chunk(a: T[], size: number): T[][] { return _.chunk(a, size); } diff --git a/src/common/helper/services/helper.date.service.ts b/src/common/helper/services/helper.date.service.ts index 0368309fc..2717a17ac 100644 --- a/src/common/helper/services/helper.date.service.ts +++ b/src/common/helper/services/helper.date.service.ts @@ -7,14 +7,13 @@ import { } from 'src/common/helper/constants/helper.enum.constant'; import { IHelperDateService } from 'src/common/helper/interfaces/helper.date-service.interface'; import { - IHelperDateExtractDate, - IHelperDateOptionsBackward, - IHelperDateOptionsCreate, - IHelperDateOptionsDiff, - IHelperDateOptionsFormat, - IHelperDateOptionsForward, - IHelperDateOptionsRoundDown, IHelperDateSetTimeOptions, + IHelperDateFormatOptions, + IHelperDateDiffOptions, + IHelperDateCreateOptions, + IHelperDateForwardOptions, + IHelperDateBackwardOptions, + IHelperDateRoundDownOptions, } from 'src/common/helper/interfaces/helper.interface'; @Injectable() @@ -38,7 +37,7 @@ export class HelperDateService implements IHelperDateService { diff( dateOne: Date, dateTwoMoreThanDateOne: Date, - options?: IHelperDateOptionsDiff + options?: IHelperDateDiffOptions ): number { const mDateOne = moment(dateOne).tz(this.defTz); const mDateTwo = moment(dateTwoMoreThanDateOne).tz(this.defTz); @@ -61,7 +60,7 @@ export class HelperDateService implements IHelperDateService { return moment(date, 'YYYY-MM-DD', true).tz(this.defTz).isValid(); } - checkDateTime(date: string | Date | number): boolean { + checkIso(date: string | Date | number): boolean { return moment(date, ISO_8601, true).tz(this.defTz).isValid(); } @@ -71,7 +70,7 @@ export class HelperDateService implements IHelperDateService { create( date?: string | number | Date, - options?: IHelperDateOptionsCreate + options?: IHelperDateCreateOptions ): Date { const mDate = moment(date ?? undefined).tz(this.defTz); @@ -82,9 +81,9 @@ export class HelperDateService implements IHelperDateService { return mDate.toDate(); } - timestamp( + createTimestamp( date?: string | number | Date, - options?: IHelperDateOptionsCreate + options?: IHelperDateCreateOptions ): number { const mDate = moment(date ?? undefined).tz(this.defTz); @@ -95,115 +94,117 @@ export class HelperDateService implements IHelperDateService { return mDate.valueOf(); } - format(date: Date, options?: IHelperDateOptionsFormat): string { + format(date: Date, options?: IHelperDateFormatOptions): string { return moment(date) .tz(this.defTz) .format(options?.format ?? ENUM_HELPER_DATE_FORMAT.DATE); } - formatIsoDuration(inMinutes: number): string { - return moment.duration(inMinutes, 'minutes').toISOString(); + formatIsoDurationFromMinutes(minutes: number): string { + return moment.duration(minutes, 'minutes').toISOString(); } - forwardInMilliseconds( - milliseconds: number, - options?: IHelperDateOptionsForward - ): Date { - return moment(options?.fromDate) - .tz(this.defTz) - .add(milliseconds, 'ms') - .toDate(); + formatIsoDurationFromHours(hours: number): string { + return moment.duration(hours, 'hours').toISOString(); } - backwardInMilliseconds( - milliseconds: number, - options?: IHelperDateOptionsBackward - ): Date { - return moment(options?.fromDate) - .tz(this.defTz) - .subtract(milliseconds, 'ms') - .toDate(); + formatIsoDurationFromDays(days: number): string { + return moment.duration(days, 'days').toISOString(); } forwardInSeconds( seconds: number, - options?: IHelperDateOptionsForward + options?: IHelperDateForwardOptions ): Date { return moment(options?.fromDate) .tz(this.defTz) - .add(seconds, 's') + .add(seconds, 'seconds') .toDate(); } backwardInSeconds( seconds: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date { return moment(options?.fromDate) .tz(this.defTz) - .subtract(seconds, 's') + .subtract(seconds, 'seconds') .toDate(); } forwardInMinutes( minutes: number, - options?: IHelperDateOptionsForward + options?: IHelperDateForwardOptions ): Date { return moment(options?.fromDate) .tz(this.defTz) - .add(minutes, 'm') + .add(minutes, 'minutes') .toDate(); } backwardInMinutes( minutes: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date { return moment(options?.fromDate) .tz(this.defTz) - .subtract(minutes, 'm') + .subtract(minutes, 'minutes') .toDate(); } - forwardInHours(hours: number, options?: IHelperDateOptionsForward): Date { + forwardInHours(hours: number, options?: IHelperDateForwardOptions): Date { return moment(options?.fromDate) .tz(this.defTz) - .add(hours, 'h') + .add(hours, 'hours') .toDate(); } - backwardInHours(hours: number, options?: IHelperDateOptionsBackward): Date { + backwardInHours(hours: number, options?: IHelperDateBackwardOptions): Date { return moment(options?.fromDate) .tz(this.defTz) - .subtract(hours, 'h') + .subtract(hours, 'hours') .toDate(); } - forwardInDays(days: number, options?: IHelperDateOptionsForward): Date { + forwardInDays(days: number, options?: IHelperDateForwardOptions): Date { return moment(options?.fromDate).tz(this.defTz).add(days, 'd').toDate(); } - backwardInDays(days: number, options?: IHelperDateOptionsBackward): Date { + backwardInDays(days: number, options?: IHelperDateBackwardOptions): Date { return moment(options?.fromDate) .tz(this.defTz) - .subtract(days, 'd') + .subtract(days, 'days') .toDate(); } - forwardInMonths(months: number, options?: IHelperDateOptionsForward): Date { + forwardInMonths(months: number, options?: IHelperDateForwardOptions): Date { return moment(options?.fromDate) .tz(this.defTz) - .add(months, 'M') + .add(months, 'months') .toDate(); } backwardInMonths( months: number, - options?: IHelperDateOptionsBackward + options?: IHelperDateBackwardOptions ): Date { return moment(options?.fromDate) .tz(this.defTz) - .subtract(months, 'M') + .subtract(months, 'months') + .toDate(); + } + + forwardInYears(years: number, options?: IHelperDateForwardOptions): Date { + return moment(options?.fromDate) + .tz(this.defTz) + .add(years, 'years') + .toDate(); + } + + backwardInYears(years: number, options?: IHelperDateBackwardOptions): Date { + return moment(options?.fromDate) + .tz(this.defTz) + .subtract(years, 'years') .toDate(); } @@ -233,7 +234,7 @@ export class HelperDateService implements IHelperDateService { setTime( date: Date, - { hour, minute, second }: IHelperDateSetTimeOptions + { hour, minute, second, millisecond }: IHelperDateSetTimeOptions ): Date { return moment(date) .tz(this.defTz) @@ -241,14 +242,14 @@ export class HelperDateService implements IHelperDateService { hour: hour, minute: minute, second: second, - ms: 0, + millisecond: millisecond, }) .toDate(); } addTime( date: Date, - { hour, minute, second }: IHelperDateSetTimeOptions + { hour, minute, second, millisecond }: IHelperDateSetTimeOptions ): Date { return moment(date) .tz(this.defTz) @@ -256,11 +257,12 @@ export class HelperDateService implements IHelperDateService { hour: hour, minute: minute, second: second, + millisecond: millisecond, }) .toDate(); } - minusTime( + subtractTime( date: Date, { hour, minute, second }: IHelperDateSetTimeOptions ): Date { @@ -274,28 +276,8 @@ export class HelperDateService implements IHelperDateService { .toDate(); } - extractDate(date: string | Date | number): IHelperDateExtractDate { - const newDate = this.create(date); - const day: string = this.format(newDate, { - format: ENUM_HELPER_DATE_FORMAT.ONLY_DATE, - }); - const month: string = this.format(newDate, { - format: ENUM_HELPER_DATE_FORMAT.ONLY_MONTH, - }); - const year: string = this.format(newDate, { - format: ENUM_HELPER_DATE_FORMAT.ONLY_YEAR, - }); - - return { - date: newDate, - day, - month, - year, - }; - } - - roundDown(date: Date, options?: IHelperDateOptionsRoundDown): Date { - const mDate = moment(date).tz(this.defTz).set({ millisecond: 0 }); + roundDown(date: Date, options?: IHelperDateRoundDownOptions): Date { + const mDate = moment(date).tz(this.defTz); if (options?.hour) { mDate.set({ hour: 0 }); @@ -309,6 +291,10 @@ export class HelperDateService implements IHelperDateService { mDate.set({ second: 0 }); } + if (options?.millisecond) { + mDate.set({ millisecond: 0 }); + } + return mDate.toDate(); } } diff --git a/src/common/helper/services/helper.encryption.service.ts b/src/common/helper/services/helper.encryption.service.ts index 11a19037a..197cefcbd 100644 --- a/src/common/helper/services/helper.encryption.service.ts +++ b/src/common/helper/services/helper.encryption.service.ts @@ -21,8 +21,8 @@ export class HelperEncryptionService implements IHelperEncryptionService { return buff.toString('utf8'); } - base64Compare(clientBasicToken: string, ourBasicToken: string): boolean { - return ourBasicToken === clientBasicToken; + base64Compare(basicToken1: string, basicToken2: string): boolean { + return basicToken1 === basicToken2; } aes256Encrypt( @@ -55,6 +55,10 @@ export class HelperEncryptionService implements IHelperEncryptionService { return JSON.parse(cipher.toString(enc.Utf8)); } + aes256Compare(aes1: string, aes2: string): boolean { + return aes1 === aes2; + } + jwtEncrypt( payload: Record, options: IHelperJwtOptions diff --git a/src/common/helper/services/helper.file.service.ts b/src/common/helper/services/helper.file.service.ts index eacd2a98e..f722c5830 100644 --- a/src/common/helper/services/helper.file.service.ts +++ b/src/common/helper/services/helper.file.service.ts @@ -1,80 +1,96 @@ import { Injectable } from '@nestjs/common'; -import bytes from 'bytes'; -import { ENUM_HELPER_FILE_TYPE } from 'src/common/helper/constants/helper.enum.constant'; +import { ENUM_HELPER_FILE_EXCEL_TYPE } from 'src/common/helper/constants/helper.enum.constant'; import { IHelperFileService } from 'src/common/helper/interfaces/helper.file-service.interface'; import { - IHelperFileWriteExcelOptions, - IHelperFileReadExcelOptions, IHelperFileRows, - IHelperFileCreateExcelWorkbookOptions, + IHelperFileReadOptions, } from 'src/common/helper/interfaces/helper.interface'; -import { utils, write, read, WorkBook } from 'xlsx'; +import { utils, write, read } from 'xlsx'; @Injectable() export class HelperFileService implements IHelperFileService { - createExcelWorkbook( - rows: IHelperFileRows[], - options?: IHelperFileCreateExcelWorkbookOptions - ): WorkBook { - // headers - const headers = Object.keys(rows[0]); + writeCsv(rows: IHelperFileRows): Buffer { + const worksheet = utils.json_to_sheet(rows.data); + const csv = utils.sheet_to_csv(worksheet, { FS: ';' }); - // worksheet - const worksheet = utils.json_to_sheet(rows); + // create buffer + const buff: Buffer = Buffer.from(csv, 'utf8'); + + return buff; + } + writeExcel( + rows: IHelperFileRows[], + options?: IHelperFileReadOptions + ): Buffer { // workbook const workbook = utils.book_new(); - utils.sheet_add_aoa(worksheet, [headers], { origin: 'A1' }); - utils.book_append_sheet( - workbook, - worksheet, - options?.sheetName ?? 'Sheet 1' - ); - - return workbook; - } + for (const [index, row] of rows.entries()) { + // worksheet + const worksheet = utils.json_to_sheet(row.data); + utils.book_append_sheet( + workbook, + worksheet, + row.sheetName ?? `Sheet${index + 1}` + ); + } - writeExcelToBuffer( - workbook: WorkBook, - options?: IHelperFileWriteExcelOptions - ): Buffer { // create buffer const buff: Buffer = write(workbook, { type: 'buffer', - bookType: options?.type ?? ENUM_HELPER_FILE_TYPE.CSV, + bookType: ENUM_HELPER_FILE_EXCEL_TYPE.XLSX, password: options?.password, }); return buff; } - readExcelFromBuffer( + readCsv(file: Buffer): IHelperFileRows { + // workbook + const workbook = read(file, { + type: 'buffer', + }); + + // worksheet + const worksheetsName: string = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[worksheetsName]; + const rows: Record[] = + utils.sheet_to_json(worksheet); + + return { + data: rows, + sheetName: worksheetsName, + }; + } + + readExcel( file: Buffer, - options?: IHelperFileReadExcelOptions - ): IHelperFileRows[][] { + options?: IHelperFileReadOptions + ): IHelperFileRows[] { // workbook const workbook = read(file, { type: 'buffer', password: options?.password, - sheets: options?.sheet, }); // worksheet const worksheetsName: string[] = workbook.SheetNames; - const sheets: IHelperFileRows[][] = []; - for (const worksheetName of worksheetsName) { - const worksheet = workbook.Sheets[worksheetName]; + const sheets: IHelperFileRows[] = []; + + for (let i = 0; i < worksheetsName.length; i++) { + const worksheet = workbook.Sheets[worksheetsName[i]]; // rows - const rows: IHelperFileRows[] = utils.sheet_to_json(worksheet); - sheets.push(rows); + const rows: Record[] = + utils.sheet_to_json(worksheet); + + sheets.push({ + data: rows, + sheetName: worksheetsName[i], + }); } return sheets; } - - convertToBytes(megabytes: string): number { - return bytes(megabytes); - } } diff --git a/src/common/helper/services/helper.number.service.ts b/src/common/helper/services/helper.number.service.ts index ffa3d7a24..a9a5dfa33 100644 --- a/src/common/helper/services/helper.number.service.ts +++ b/src/common/helper/services/helper.number.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@nestjs/common'; -import { faker } from '@faker-js/faker'; import { IHelperNumberService } from 'src/common/helper/interfaces/helper.number-service.interface'; @Injectable() @@ -9,10 +8,6 @@ export class HelperNumberService implements IHelperNumberService { return regex.test(number); } - create(number: string): number { - return Number(number); - } - random(length: number): number { const min: number = Number.parseInt(`1`.padEnd(length, '0')); const max: number = Number.parseInt(`9`.padEnd(length, '9')); @@ -20,7 +15,9 @@ export class HelperNumberService implements IHelperNumberService { } randomInRange(min: number, max: number): number { - return faker.number.int({ min, max }); + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min) + min); } percent(value: number, total: number): number { diff --git a/src/common/helper/services/helper.string.service.ts b/src/common/helper/services/helper.string.service.ts index 1296401fe..2633a1946 100644 --- a/src/common/helper/services/helper.string.service.ts +++ b/src/common/helper/services/helper.string.service.ts @@ -1,77 +1,85 @@ import { Injectable } from '@nestjs/common'; -import { faker } from '@faker-js/faker'; -import { IHelperStringRandomOptions } from 'src/common/helper/interfaces/helper.interface'; +import RandExp from 'randexp'; +import { + IHelperStringCurrencyOptions, + IHelperStringPasswordOptions, + IHelperStringRandomOptions, +} from 'src/common/helper/interfaces/helper.interface'; import { IHelperStringService } from 'src/common/helper/interfaces/helper.string-service.interface'; @Injectable() export class HelperStringService implements IHelperStringService { - checkEmail(email: string): boolean { - const regex = /\S+@\S+\.\S+/; - return regex.test(email); - } - - randomReference(length: number, prefix?: string): string { + randomReference(length: number): string { const timestamp = `${new Date().getTime()}`; const randomString: string = this.random(length, { safe: true, upperCase: true, }); - return prefix - ? `${prefix}-${timestamp}${randomString}` - : `${timestamp}${randomString}`; + return `${timestamp}${randomString}`; } random(length: number, options?: IHelperStringRandomOptions): string { const rString = options?.safe - ? faker.internet.password({ - length, - memorable: true, - pattern: /[A-Z]/, - prefix: options?.prefix, - }) - : faker.internet.password({ - length, - memorable: false, - pattern: /\w/, - prefix: options?.prefix, - }); + ? new RandExp(`[A-Z]{${length},${length}}`) + : new RandExp(`\\w{${length},${length}}`); - return options?.upperCase ? rString.toUpperCase() : rString; + return options?.upperCase ? rString.gen().toUpperCase() : rString.gen(); } - censor(value: string): string { - const stringCensor = '*'.repeat(8); - if (value.length <= 5) { - return value; - } else if (value.length <= 10) { - return `${stringCensor}${value.slice(-5)}`; + censor(text: string): string { + if (text.length <= 3) { + const stringCensor = '*'.repeat(2); + return `${stringCensor}${text.slice(-1)}`; + } else if (text.length <= 10) { + const stringCensor = '*'.repeat(7); + return `${stringCensor}${text.slice(-3)}`; + } else if (text.length <= 25) { + const lengthExplicit = Math.ceil((text.length / 100) * 30); + const lengthCensor = Math.ceil((text.length / 100) * 50); + const stringCensor = '*'.repeat(lengthCensor); + return `${stringCensor}${text.slice(-lengthExplicit)}`; } - return `${value.slice(0, 3)}${stringCensor}${value.slice(-5)}`; + const stringCensor = '*'.repeat(10); + const lengthExplicit = Math.ceil((text.length / 100) * 30); + return `${text.slice(0, 3)}${stringCensor}${text.slice(-lengthExplicit)}`; } - checkPasswordWeak(password: string, length?: number): boolean { - const regex = new RegExp( - `^(?=.*?[A-Z])(?=.*?[a-z]).{${length ?? 8},}$` - ); + checkEmail(email: string): boolean { + const regex = new RegExp(/\S+@\S+\.\S+/); + return regex.test(email); + } + + checkPasswordWeak( + password: string, + options?: IHelperStringPasswordOptions + ): boolean { + const length = options?.length ?? 6; + const regex = new RegExp(`^(?=.*?[A-Z])(?=.*?[a-z]).{${length},}$`); return regex.test(password); } - checkPasswordMedium(password: string, length?: number): boolean { + checkPasswordMedium( + password: string, + options?: IHelperStringPasswordOptions + ): boolean { + const length = options?.length ?? 6; const regex = new RegExp( - `^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{${length ?? 8},}$` + `^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{${length},}$` ); return regex.test(password); } - checkPasswordStrong(password: string, length?: number): boolean { + checkPasswordStrong( + password: string, + options?: IHelperStringPasswordOptions + ): boolean { + const length = options?.length ?? 6; const regex = new RegExp( - `^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{${ - length ?? 8 - },}$` + `^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{${length},}$` ); return regex.test(password); @@ -82,15 +90,10 @@ export class HelperStringService implements IHelperStringService { return regex.test(text); } - formatCurrency(num: number): string { - return new Intl.NumberFormat('id-ID', { - style: 'currency', - currency: 'IDR', - minimumFractionDigits: 0, - maximumFractionDigits: 0, - }) - .format(num) - .replace('Rp', '') - .trim(); + formatCurrency( + num: number, + options?: IHelperStringCurrencyOptions + ): string { + return num.toLocaleString(options?.locale); } } diff --git a/src/common/message/interfaces/message.service.interface.ts b/src/common/message/interfaces/message.service.interface.ts index bd6c98ae5..7d6d37a6d 100644 --- a/src/common/message/interfaces/message.service.interface.ts +++ b/src/common/message/interfaces/message.service.interface.ts @@ -2,7 +2,7 @@ import { ValidationError } from '@nestjs/common'; import { IErrors, IErrorsImport, - IValidationErrorImport, + IErrorValidationImport, } from 'src/common/error/interfaces/error.interface'; import { IMessageErrorOptions, @@ -20,7 +20,7 @@ export interface IMessageService { options?: IMessageErrorOptions ): IErrors[]; getImportErrorsMessage( - errors: IValidationErrorImport[], + errors: IErrorValidationImport[], options?: IMessageErrorOptions ): IErrorsImport[]; get(key: string, options?: IMessageOptions): T; diff --git a/src/common/message/middleware/custom-language/message.custom-language.middleware.ts b/src/common/message/middleware/custom-language/message.custom-language.middleware.ts index 68ba964c5..73085ff75 100644 --- a/src/common/message/middleware/custom-language/message.custom-language.middleware.ts +++ b/src/common/message/middleware/custom-language/message.custom-language.middleware.ts @@ -26,7 +26,7 @@ export class MessageCustomLanguageMiddleware implements NestMiddleware { const splitLanguage: string[] = reqLanguages .split(',') .map((val) => val.toLowerCase()); - const languages: string[] = this.helperArrayService.intersection( + const languages: string[] = this.helperArrayService.getIntersection( availableLanguages, splitLanguage ); diff --git a/src/common/message/services/message.service.ts b/src/common/message/services/message.service.ts index 4b49d34cc..4a5682d16 100644 --- a/src/common/message/services/message.service.ts +++ b/src/common/message/services/message.service.ts @@ -5,7 +5,7 @@ import { I18nService } from 'nestjs-i18n'; import { IErrors, IErrorsImport, - IValidationErrorImport, + IErrorValidationImport, } from 'src/common/error/interfaces/error.interface'; import { HelperArrayService } from 'src/common/helper/services/helper.array.service'; import { @@ -41,7 +41,7 @@ export class MessageService implements IMessageService { } filterLanguage(customLanguages: string[]): string[] { - return this.helperArrayService.intersection( + return this.helperArrayService.getIntersection( customLanguages, this.appDefaultAvailableLanguage ); @@ -104,13 +104,12 @@ export class MessageService implements IMessageService { } getImportErrorsMessage( - errors: IValidationErrorImport[], + errors: IErrorValidationImport[], options?: IMessageErrorOptions ): IErrorsImport[] { return errors.map((val) => ({ row: val.row, - file: val.file, - sheet: val.sheet, + sheetName: val.sheetName, errors: this.getRequestErrorsMessage(val.errors, options), })); } diff --git a/src/common/pagination/pipes/pagination.filter-equal.pipe.ts b/src/common/pagination/pipes/pagination.filter-equal.pipe.ts index 6c8d2a437..b86d368c5 100644 --- a/src/common/pagination/pipes/pagination.filter-equal.pipe.ts +++ b/src/common/pagination/pipes/pagination.filter-equal.pipe.ts @@ -44,7 +44,7 @@ export function PaginationFilterEqualPipe( let finalValue: string | number = value; if (options?.isNumber) { finalValue = this.helperNumberService.check(value) - ? this.helperNumberService.create(value) + ? Number.parseInt(value) : value; } diff --git a/src/common/pagination/pipes/pagination.paging.pipe.ts b/src/common/pagination/pipes/pagination.paging.pipe.ts index eece33010..0e165ad37 100644 --- a/src/common/pagination/pipes/pagination.paging.pipe.ts +++ b/src/common/pagination/pipes/pagination.paging.pipe.ts @@ -20,12 +20,10 @@ export function PaginationPagingPipe( value: Record ): Promise> { const page: number = this.paginationService.page( - this.helperNumberService.create(value?.page ?? 1) + Number.parseInt(value?.page ?? 1) ); const perPage: number = this.paginationService.perPage( - this.helperNumberService.create( - value?.perPage ?? defaultPerPage - ) + Number.parseInt(value?.perPage ?? defaultPerPage) ); const offset: number = this.paginationService.offset(page, perPage); diff --git a/src/common/policy/factories/policy.ability.factory.ts b/src/common/policy/factories/policy.ability.factory.ts index a8b0a49cd..bbb1f0a13 100644 --- a/src/common/policy/factories/policy.ability.factory.ts +++ b/src/common/policy/factories/policy.ability.factory.ts @@ -44,9 +44,7 @@ export class PolicyAbilityFactory { return action .split(',') .map((val: string) => ({ - action: this.mappingRequestRule( - this.helperNumberService.create(val) - ), + action: this.mappingRequestRule(Number.parseInt(val)), subject, })) .flat(1); diff --git a/src/common/request/middleware/request.middleware.module.ts b/src/common/request/middleware/request.middleware.module.ts index a82f18a52..79df07c4b 100644 --- a/src/common/request/middleware/request.middleware.module.ts +++ b/src/common/request/middleware/request.middleware.module.ts @@ -11,7 +11,6 @@ import { RequestIdMiddleware } from 'src/common/request/middleware/id/request.id import { RequestTimestampMiddleware } from 'src/common/request/middleware/timestamp/request.timestamp.middleware'; import { RequestTimezoneMiddleware } from 'src/common/request/middleware/timezone/request.timezone.middleware'; import { RequestUserAgentMiddleware } from 'src/common/request/middleware/user-agent/request.user-agent.middleware'; - import { RequestVersionMiddleware } from 'src/common/request/middleware/version/request.version.middleware'; @Module({}) diff --git a/src/common/request/middleware/timestamp/request.timestamp.middleware.ts b/src/common/request/middleware/timestamp/request.timestamp.middleware.ts index 7b6be30ae..b90dd959d 100644 --- a/src/common/request/middleware/timestamp/request.timestamp.middleware.ts +++ b/src/common/request/middleware/timestamp/request.timestamp.middleware.ts @@ -17,9 +17,9 @@ export class RequestTimestampMiddleware implements NestMiddleware { next: NextFunction ): Promise { req.__xTimestamp = req['x-timestamp'] - ? this.helperNumberService.create(req['x-timestamp']) + ? Number.parseInt(req['x-timestamp']) : undefined; - req.__timestamp = this.helperDateService.timestamp(); + req.__timestamp = this.helperDateService.createTimestamp(); next(); } } diff --git a/src/common/request/validations/request.is-password-medium.validation.ts b/src/common/request/validations/request.is-password-medium.validation.ts index e6fa7bd07..e3809916c 100644 --- a/src/common/request/validations/request.is-password-medium.validation.ts +++ b/src/common/request/validations/request.is-password-medium.validation.ts @@ -18,7 +18,7 @@ export class IsPasswordMediumConstraint validate(value: string, args: ValidationArguments): boolean { const [length] = args.constraints; return value - ? this.helperStringService.checkPasswordMedium(value, length) + ? this.helperStringService.checkPasswordMedium(value, { length }) : false; } } diff --git a/src/common/request/validations/request.is-password-strong.validation.ts b/src/common/request/validations/request.is-password-strong.validation.ts index aafccfb92..587a6045f 100644 --- a/src/common/request/validations/request.is-password-strong.validation.ts +++ b/src/common/request/validations/request.is-password-strong.validation.ts @@ -18,7 +18,7 @@ export class IsPasswordStrongConstraint validate(value: string, args: ValidationArguments): boolean { const [length] = args.constraints; return value - ? this.helperStringService.checkPasswordStrong(value, length) + ? this.helperStringService.checkPasswordStrong(value, { length }) : false; } } diff --git a/src/common/request/validations/request.is-password-weak.validation.ts b/src/common/request/validations/request.is-password-weak.validation.ts index ea605ee55..3cc747fbb 100644 --- a/src/common/request/validations/request.is-password-weak.validation.ts +++ b/src/common/request/validations/request.is-password-weak.validation.ts @@ -16,7 +16,7 @@ export class IsPasswordWeakConstraint implements ValidatorConstraintInterface { validate(value: string, args: ValidationArguments): boolean { const [length] = args.constraints; return value - ? this.helperStringService.checkPasswordMedium(value, length) + ? this.helperStringService.checkPasswordMedium(value, { length }) : false; } } diff --git a/src/common/response/constants/response.constant.ts b/src/common/response/constants/response.constant.ts index c8752ec2a..dffcb822c 100644 --- a/src/common/response/constants/response.constant.ts +++ b/src/common/response/constants/response.constant.ts @@ -4,4 +4,9 @@ export const RESPONSE_SERIALIZATION_OPTIONS_META_KEY = export const RESPONSE_MESSAGE_PROPERTIES_META_KEY = 'ResponseSerializationPropertiesMetaKey'; export const RESPONSE_MESSAGE_PATH_META_KEY = 'ResponseMessagePathMetaKey'; -export const RESPONSE_FILE_TYPE_META_KEY = 'ResponseFileTypeMetaKey'; + +export const RESPONSE_FILE_EXCEL_SERIALIZATION_META_KEY = + 'ResponseFileExcelSerializationMetaKey'; +export const RESPONSE_FILE_EXCEL_TYPE_META_KEY = 'ResponseFileExcelTypeMetaKey'; +export const RESPONSE_FILE_EXCEL_PASSWORD_META_KEY = + 'ResponseFileExcelPasswordMetaKey'; diff --git a/src/common/response/decorators/response.decorator.ts b/src/common/response/decorators/response.decorator.ts index 5161dff4e..18f99620b 100644 --- a/src/common/response/decorators/response.decorator.ts +++ b/src/common/response/decorators/response.decorator.ts @@ -4,20 +4,22 @@ import { SetMetadata, UseInterceptors, } from '@nestjs/common'; -import { ENUM_HELPER_FILE_TYPE } from 'src/common/helper/constants/helper.enum.constant'; +import { ENUM_HELPER_FILE_EXCEL_TYPE } from 'src/common/helper/constants/helper.enum.constant'; import { - RESPONSE_FILE_TYPE_META_KEY, + RESPONSE_FILE_EXCEL_PASSWORD_META_KEY, + RESPONSE_FILE_EXCEL_SERIALIZATION_META_KEY, + RESPONSE_FILE_EXCEL_TYPE_META_KEY, RESPONSE_MESSAGE_PATH_META_KEY, RESPONSE_MESSAGE_PROPERTIES_META_KEY, RESPONSE_SERIALIZATION_META_KEY, } from 'src/common/response/constants/response.constant'; -import { ResponseDefaultInterceptor } from 'src/common/response/interceptors/response.default.interceptor'; -import { ResponseFileInterceptor } from 'src/common/response/interceptors/response.file.interceptor'; +import { ResponseInterceptor } from 'src/common/response/interceptors/response.interceptor'; +import { ResponseFileExcelInterceptor } from 'src/common/response/interceptors/response.file.interceptor'; import { ResponsePagingInterceptor } from 'src/common/response/interceptors/response.paging.interceptor'; import { IResponseOptions, IResponsePagingOptions, - IResponseFileOptions, + IResponseFileExcelOptions, } from 'src/common/response/interfaces/response.interface'; export function Response( @@ -25,7 +27,7 @@ export function Response( options?: IResponseOptions ): MethodDecorator { return applyDecorators( - UseInterceptors(ResponseDefaultInterceptor), + UseInterceptors(ResponseInterceptor), SetMetadata(RESPONSE_MESSAGE_PATH_META_KEY, messagePath), SetMetadata(RESPONSE_SERIALIZATION_META_KEY, options?.serialization), SetMetadata( @@ -35,16 +37,20 @@ export function Response( ); } -export function ResponseFile( - options?: IResponseFileOptions +export function ResponseFileExcel( + options?: IResponseFileExcelOptions ): MethodDecorator { return applyDecorators( - UseInterceptors(ResponseFileInterceptor), - SetMetadata(RESPONSE_SERIALIZATION_META_KEY, options?.serialization), + UseInterceptors(ResponseFileExcelInterceptor), + SetMetadata( + RESPONSE_FILE_EXCEL_SERIALIZATION_META_KEY, + options?.serialization + ), SetMetadata( - RESPONSE_FILE_TYPE_META_KEY, - options?.fileType ?? ENUM_HELPER_FILE_TYPE.CSV + RESPONSE_FILE_EXCEL_TYPE_META_KEY, + options?.type ?? ENUM_HELPER_FILE_EXCEL_TYPE.CSV ), + SetMetadata(RESPONSE_FILE_EXCEL_PASSWORD_META_KEY, options?.password), SetMetadata( RESPONSE_MESSAGE_PROPERTIES_META_KEY, options?.messageProperties diff --git a/src/common/response/interceptors/response.file.interceptor.ts b/src/common/response/interceptors/response.file.interceptor.ts index 8d024113e..27c2698da 100644 --- a/src/common/response/interceptors/response.file.interceptor.ts +++ b/src/common/response/interceptors/response.file.interceptor.ts @@ -16,18 +16,22 @@ import { plainToInstance, } from 'class-transformer'; import { Reflector } from '@nestjs/core'; -import { IResponseFile } from 'src/common/response/interfaces/response.interface'; import { - RESPONSE_FILE_TYPE_META_KEY, - RESPONSE_SERIALIZATION_META_KEY, + RESPONSE_FILE_EXCEL_PASSWORD_META_KEY, + RESPONSE_FILE_EXCEL_SERIALIZATION_META_KEY, + RESPONSE_FILE_EXCEL_TYPE_META_KEY, RESPONSE_SERIALIZATION_OPTIONS_META_KEY, } from 'src/common/response/constants/response.constant'; -import { WorkBook } from 'xlsx'; -import { ENUM_HELPER_FILE_TYPE } from 'src/common/helper/constants/helper.enum.constant'; import { HelperDateService } from 'src/common/helper/services/helper.date.service'; +import { ENUM_HELPER_FILE_EXCEL_TYPE } from 'src/common/helper/constants/helper.enum.constant'; +import { ENUM_FILE_MIME } from 'src/common/file/constants/file.enum.constant'; +import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; +import { IResponseFileExcel } from 'src/common/response/interfaces/response.interface'; @Injectable() -export class ResponseFileInterceptor implements NestInterceptor> { +export class ResponseFileExcelInterceptor + implements NestInterceptor> +{ constructor( private readonly reflector: Reflector, private readonly helperFileService: HelperFileService, @@ -38,21 +42,26 @@ export class ResponseFileInterceptor implements NestInterceptor> { context: ExecutionContext, next: CallHandler ): Promise>>> { - const fileType: ENUM_HELPER_FILE_TYPE = - this.reflector.get( - RESPONSE_FILE_TYPE_META_KEY, - context.getHandler() - ); - if (context.getType() === 'http') { return next.handle().pipe( - map(async (res: Promise) => { + map(async (res: Promise) => { const ctx: HttpArgumentsHost = context.switchToHttp(); const response: Response = ctx.getResponse(); - const classSerialization: ClassConstructor = - this.reflector.get>( - RESPONSE_SERIALIZATION_META_KEY, + const type: ENUM_HELPER_FILE_EXCEL_TYPE = + this.reflector.get( + RESPONSE_FILE_EXCEL_TYPE_META_KEY, + context.getHandler() + ); + + const password: string = this.reflector.get( + RESPONSE_FILE_EXCEL_PASSWORD_META_KEY, + context.getHandler() + ); + + const classSerialization: ClassConstructor[] = + this.reflector.get[]>( + RESPONSE_FILE_EXCEL_SERIALIZATION_META_KEY, context.getHandler() ); const classSerializationOptions: ClassTransformOptions = @@ -62,31 +71,92 @@ export class ResponseFileInterceptor implements NestInterceptor> { ); // set default response - const responseData = (await res) as IResponseFile; - let data: Record[] = responseData.data; - if (classSerialization) { - data = plainToInstance( - classSerialization, - data, - classSerializationOptions + const responseData = (await res) as IResponseFileExcel; + + if (!responseData) { + throw new Error( + 'ResponseFileExcel must instanceof IResponseFileExcel' + ); + } else if ( + !responseData.data || + !Array.isArray(responseData.data) || + responseData.data.length === 0 + ) { + throw new Error( + 'Field data must in array and can not be empty' ); } + if (type === ENUM_HELPER_FILE_EXCEL_TYPE.XLSX) { + const datas: IHelperFileRows[] = responseData.data; + + if ( + classSerialization && + Array.isArray(classSerialization) && + classSerialization.length > 0 + ) { + for (const [index, data] of datas.entries()) { + if (classSerialization[index]) { + const dataSerialization = plainToInstance( + classSerialization[index], + data, + classSerializationOptions + ); + + datas[index].data = dataSerialization; + } + } + } + + // create file + const file: Buffer = this.helperFileService.writeExcel( + datas, + { password } + ); + + // set headers + const timestamp = + this.helperDateService.createTimestamp(); + response + .setHeader('Content-Type', ENUM_FILE_MIME.XLSX) + .setHeader( + 'Content-Disposition', + `attachment; filename=export-${timestamp}.${type.toLowerCase()}` + ) + .setHeader('Content-Length', file.length); + + return new StreamableFile(file); + } + + // create file + const data: IHelperFileRows = responseData.data[0]; + + if ( + classSerialization && + Array.isArray(classSerialization) && + classSerialization.length > 0 + ) { + if (classSerialization[0]) { + const dataSerialization = plainToInstance( + classSerialization[0], + data.data, + classSerializationOptions + ); + + data.data = dataSerialization; + } + } + // create file - const workbook: WorkBook = - this.helperFileService.createExcelWorkbook(data); - const file: Buffer = - this.helperFileService.writeExcelToBuffer(workbook, { - type: fileType, - }); + const file: Buffer = this.helperFileService.writeCsv(data); // set headers - const timestamp = this.helperDateService.timestamp(); + const timestamp = this.helperDateService.createTimestamp(); response - .setHeader('Content-Type', fileType.toUpperCase()) + .setHeader('Content-Type', ENUM_FILE_MIME.CSV) .setHeader( 'Content-Disposition', - `attachment; filename=export-${timestamp}.${fileType}` + `attachment; filename=export-${timestamp}.${type.toLowerCase()}` ) .setHeader('Content-Length', file.length); diff --git a/src/common/response/interceptors/response.custom-headers.interceptor.ts b/src/common/response/interceptors/response.headers.interceptor.ts similarity index 96% rename from src/common/response/interceptors/response.custom-headers.interceptor.ts rename to src/common/response/interceptors/response.headers.interceptor.ts index 5e6aaeddf..3e338c45a 100644 --- a/src/common/response/interceptors/response.custom-headers.interceptor.ts +++ b/src/common/response/interceptors/response.headers.interceptor.ts @@ -11,7 +11,7 @@ import { IRequestApp } from 'src/common/request/interfaces/request.interface'; // only for response success and error in controller @Injectable() -export class ResponseCustomHeadersInterceptor +export class ResponseHeadersInterceptor implements NestInterceptor> { async intercept( diff --git a/src/common/response/interceptors/response.default.interceptor.ts b/src/common/response/interceptors/response.interceptor.ts similarity index 95% rename from src/common/response/interceptors/response.default.interceptor.ts rename to src/common/response/interceptors/response.interceptor.ts index 39f523f5e..957fd37a2 100644 --- a/src/common/response/interceptors/response.default.interceptor.ts +++ b/src/common/response/interceptors/response.interceptor.ts @@ -22,9 +22,9 @@ import { IMessageOptionsProperties, } from 'src/common/message/interfaces/message.interface'; import { - ResponseDefaultSerialization, + ResponseSerialization, ResponseMetadataSerialization, -} from 'src/common/response/serializations/response.default.serialization'; +} from 'src/common/response/serializations/response.serialization'; import { RESPONSE_MESSAGE_PATH_META_KEY, RESPONSE_MESSAGE_PROPERTIES_META_KEY, @@ -34,9 +34,7 @@ import { import { IResponse } from 'src/common/response/interfaces/response.interface'; @Injectable() -export class ResponseDefaultInterceptor - implements NestInterceptor> -{ +export class ResponseInterceptor implements NestInterceptor> { constructor( private readonly reflector: Reflector, private readonly messageService: MessageService @@ -45,7 +43,7 @@ export class ResponseDefaultInterceptor async intercept( context: ExecutionContext, next: CallHandler - ): Promise>> { + ): Promise>> { if (context.getType() === 'http') { return next.handle().pipe( map(async (res: Promise>) => { diff --git a/src/common/response/interceptors/response.paging.interceptor.ts b/src/common/response/interceptors/response.paging.interceptor.ts index f5adfb71e..ee147057d 100644 --- a/src/common/response/interceptors/response.paging.interceptor.ts +++ b/src/common/response/interceptors/response.paging.interceptor.ts @@ -104,7 +104,16 @@ export class ResponsePagingInterceptor // response const responseData = (await res) as IResponsePaging; if (!responseData) { - throw new Error('Paging must have response'); + throw new Error( + 'ResponsePaging must instanceof IResponsePaging' + ); + } else if ( + !responseData.data || + !Array.isArray(responseData.data) + ) { + throw new Error( + 'Field data must in array and can not be empty' + ); } const { _metadata } = responseData; diff --git a/src/common/response/interfaces/response.interface.ts b/src/common/response/interfaces/response.interface.ts index 5726aab18..4f4791fa2 100644 --- a/src/common/response/interfaces/response.interface.ts +++ b/src/common/response/interfaces/response.interface.ts @@ -1,6 +1,6 @@ import { HttpStatus } from '@nestjs/common'; import { ClassConstructor } from 'class-transformer'; -import { ENUM_HELPER_FILE_TYPE } from 'src/common/helper/constants/helper.enum.constant'; +import { ENUM_HELPER_FILE_EXCEL_TYPE } from 'src/common/helper/constants/helper.enum.constant'; import { IHelperFileRows } from 'src/common/helper/interfaces/helper.interface'; import { IMessageOptionsProperties } from 'src/common/message/interfaces/message.interface'; @@ -29,16 +29,20 @@ export interface IResponsePagingOptions serialization: ClassConstructor; } -export interface IResponseFileOptions extends IResponseOptions { - fileType?: ENUM_HELPER_FILE_TYPE; +export interface IResponseFileExcelOptions + extends Pick, 'messageProperties'> { + serialization?: ClassConstructor[]; + type?: ENUM_HELPER_FILE_EXCEL_TYPE; + password?: string; } -// type +// response export interface IResponse { _metadata?: IResponseMetadata; data?: Record; } +// response pagination export interface IResponsePagingPagination { totalPage: number; total: number; @@ -50,6 +54,6 @@ export interface IResponsePaging { data: Record[]; } -export interface IResponseFile { +export interface IResponseFileExcel { data: IHelperFileRows[]; } diff --git a/src/common/response/response.module.ts b/src/common/response/response.module.ts index 9db6dcd23..5f19da591 100644 --- a/src/common/response/response.module.ts +++ b/src/common/response/response.module.ts @@ -1,14 +1,14 @@ import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { ResponseMiddlewareModule } from 'src/common/response/middleware/response.middleware.module'; -import { ResponseCustomHeadersInterceptor } from './interceptors/response.custom-headers.interceptor'; +import { ResponseHeadersInterceptor } from './interceptors/response.headers.interceptor'; @Module({ controllers: [], providers: [ { provide: APP_INTERCEPTOR, - useClass: ResponseCustomHeadersInterceptor, + useClass: ResponseHeadersInterceptor, }, ], imports: [ResponseMiddlewareModule], diff --git a/src/common/response/serializations/response.paging.serialization.ts b/src/common/response/serializations/response.paging.serialization.ts index 4f09c66f6..607c32879 100644 --- a/src/common/response/serializations/response.paging.serialization.ts +++ b/src/common/response/serializations/response.paging.serialization.ts @@ -4,9 +4,9 @@ import { PAGINATION_AVAILABLE_ORDER_DIRECTION } from 'src/common/pagination/cons import { ENUM_PAGINATION_ORDER_DIRECTION_TYPE } from 'src/common/pagination/constants/pagination.enum.constant'; import { RequestPaginationSerialization } from 'src/common/request/serializations/request.pagination.serialization'; import { - ResponseDefaultSerialization, + ResponseSerialization, ResponseMetadataSerialization, -} from 'src/common/response/serializations/response.default.serialization'; +} from 'src/common/response/serializations/response.serialization'; export class ResponsePaginationCursorSerialization { nextPage: string; @@ -28,10 +28,7 @@ export interface ResponsePagingMetadataSerialization export class ResponsePagingSerialization< T = Record, -> extends PickType(ResponseDefaultSerialization, [ - 'statusCode', - 'message', -] as const) { +> extends PickType(ResponseSerialization, ['statusCode', 'message'] as const) { @ApiProperty({ name: '_metadata', required: true, diff --git a/src/common/response/serializations/response.default.serialization.ts b/src/common/response/serializations/response.serialization.ts similarity index 96% rename from src/common/response/serializations/response.default.serialization.ts rename to src/common/response/serializations/response.serialization.ts index 8e49f2431..911d7e62d 100644 --- a/src/common/response/serializations/response.default.serialization.ts +++ b/src/common/response/serializations/response.serialization.ts @@ -12,7 +12,7 @@ export class ResponseMetadataSerialization { [key: string]: any; } -export class ResponseDefaultSerialization> { +export class ResponseSerialization> { @ApiProperty({ name: 'statusCode', type: Number, diff --git a/src/modules/dashboard/serializations/dashboard.serialization.ts b/src/modules/dashboard/serializations/dashboard.serialization.ts index 3a6c11508..52694614d 100644 --- a/src/modules/dashboard/serializations/dashboard.serialization.ts +++ b/src/modules/dashboard/serializations/dashboard.serialization.ts @@ -2,14 +2,42 @@ import { ApiProperty } from '@nestjs/swagger'; export class DashboardSerialization { @ApiProperty({ - name: 'name', - nullable: true, + name: 'startDate', + required: true, }) startDate: Date; @ApiProperty({ - name: 'month', - nullable: true, + name: 'endDate', + required: true, }) endDate: Date; } + +export class DashboardTotalSerialization { + @ApiProperty({ + name: 'total', + required: true, + }) + total: number; + + @ApiProperty({ + name: 'percent', + required: false, + }) + percent?: number; +} + +export class DashboardTotalByMonthSerialization extends DashboardTotalSerialization { + @ApiProperty({ + name: 'month', + required: true, + }) + month: number; + + @ApiProperty({ + name: 'year', + required: true, + }) + year: number; +} diff --git a/src/modules/role/guards/payload/role.payload.type.guard.ts b/src/modules/role/guards/payload/role.payload.type.guard.ts index b9aec6383..e395f64b2 100644 --- a/src/modules/role/guards/payload/role.payload.type.guard.ts +++ b/src/modules/role/guards/payload/role.payload.type.guard.ts @@ -5,7 +5,6 @@ import { ForbiddenException, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; -import { HelperArrayService } from 'src/common/helper/services/helper.array.service'; import { IRequestApp } from 'src/common/request/interfaces/request.interface'; import { ROLE_TYPE_META_KEY } from 'src/modules/role/constants/role.constant'; import { ENUM_ROLE_TYPE } from 'src/modules/role/constants/role.enum.constant'; @@ -13,10 +12,7 @@ import { ENUM_ROLE_STATUS_CODE_ERROR } from 'src/modules/role/constants/role.sta @Injectable() export class RolePayloadTypeGuard implements CanActivate { - constructor( - private readonly reflector: Reflector, - private readonly helperArrayService: HelperArrayService - ) {} + constructor(private readonly reflector: Reflector) {} async canActivate(context: ExecutionContext): Promise { const requiredFor: ENUM_ROLE_TYPE[] = this.reflector.getAllAndOverride< @@ -30,11 +26,7 @@ export class RolePayloadTypeGuard implements CanActivate { return true; } - const hasFor: boolean = this.helperArrayService.includes( - requiredFor, - type - ); - + const hasFor: boolean = requiredFor.includes(type); if (!hasFor) { throw new ForbiddenException({ statusCode: diff --git a/src/modules/setting/services/setting.service.ts b/src/modules/setting/services/setting.service.ts index 6b4ea7803..92a985592 100644 --- a/src/modules/setting/services/setting.service.ts +++ b/src/modules/setting/services/setting.service.ts @@ -108,7 +108,7 @@ export class SettingService implements ISettingService { setting.type === ENUM_SETTING_DATA_TYPE.NUMBER && this.helperNumberService.check(setting.value) ) { - return this.helperNumberService.create(setting.value) as any; + return Number.parseInt(setting.value) as any; } else if (setting.type === ENUM_SETTING_DATA_TYPE.ARRAY_OF_STRING) { return setting.value.split(',') as any; } diff --git a/src/modules/user/controllers/user.admin.controller.ts b/src/modules/user/controllers/user.admin.controller.ts index ae754e96d..4fb6763aa 100644 --- a/src/modules/user/controllers/user.admin.controller.ts +++ b/src/modules/user/controllers/user.admin.controller.ts @@ -16,16 +16,16 @@ import { ApiTags } from '@nestjs/swagger'; import { AuthService } from 'src/common/auth/services/auth.service'; import { IFileExtract } from 'src/common/file/interfaces/file.interface'; import { FileRequiredPipe } from 'src/common/file/pipes/file.required.pipe'; -import { ENUM_HELPER_FILE_TYPE } from 'src/common/helper/constants/helper.enum.constant'; import { PaginationService } from 'src/common/pagination/services/pagination.service'; import { RequestParamGuard } from 'src/common/request/decorators/request.decorator'; import { Response, - ResponseFile, + ResponseFileExcel, ResponsePaging, } from 'src/common/response/decorators/response.decorator'; import { IResponse, + IResponseFileExcel, IResponsePaging, } from 'src/common/response/interfaces/response.interface'; import { ResponseIdSerialization } from 'src/common/response/serializations/response.id.serialization'; @@ -76,7 +76,6 @@ import { ENUM_POLICY_ACTION, ENUM_POLICY_SUBJECT, } from 'src/common/policy/constants/policy.enum.constant'; -import { RoleDoc } from 'src/modules/role/repository/entities/role.entity'; import { UserAdminActiveDoc, UserAdminBlockedDoc, @@ -97,6 +96,7 @@ import { FileTypePipe } from 'src/common/file/pipes/file.type.pipe'; import { FileExcelExtractPipe } from 'src/common/file/pipes/file.excel-extract.pipe'; import { FileExcelValidationPipe } from 'src/common/file/pipes/file.excel-validation.pipe'; import { ENUM_FILE_MIME } from 'src/common/file/constants/file.enum.constant'; +import { ENUM_HELPER_FILE_EXCEL_TYPE } from 'src/common/helper/constants/helper.enum.constant'; @ApiTags('modules.admin.user') @Controller({ @@ -375,22 +375,60 @@ export class UserAdminController { ) file: IFileExtract ): Promise { - const role: RoleDoc = await this.roleService.findOneByName('user'); + const checkRole = await this.roleService.findOneByName('user'); + if (!checkRole) { + throw new NotFoundException({ + statusCode: ENUM_ROLE_STATUS_CODE_ERROR.ROLE_NOT_FOUND_ERROR, + message: 'role.error.notFound', + }); + } + + const mobileNumbers = + file.extracts[0].data.map((e) => e.mobileNumber).filter((e) => e) ?? + []; + const emails = file.extracts[0].data.map((e) => e.email) ?? []; + + const promises: Promise[] = [ + this.userService.existByEmails(emails), + ]; + + if (mobileNumbers && mobileNumbers.length > 0) { + promises.push(this.userService.existByMobileNumbers(mobileNumbers)); + } + + const [emailExist, mobileNumberExist] = await Promise.all(promises); + + if (emailExist) { + throw new ConflictException({ + statusCode: ENUM_USER_STATUS_CODE_ERROR.USER_EMAIL_EXIST_ERROR, + message: 'user.error.emailExist', + }); + } else if (mobileNumberExist) { + throw new ConflictException({ + statusCode: + ENUM_USER_STATUS_CODE_ERROR.USER_MOBILE_NUMBER_EXIST_ERROR, + message: 'user.error.mobileNumberExist', + }); + } const passwordString: string = await this.authService.createPasswordRandom(); const password: IAuthPassword = await this.authService.createPassword(passwordString); - await this.userService.import(file.dto, role._id, password); + await this.userService.import( + file.extracts[0].data, + checkRole._id, + password + ); return; } @UserAdminExportDoc() - @ResponseFile({ - serialization: UserListSerialization, - fileType: ENUM_HELPER_FILE_TYPE.CSV, + @ResponseFileExcel({ + serialization: [UserListSerialization], + type: ENUM_HELPER_FILE_EXCEL_TYPE.CSV, }) @PolicyAbilityProtected({ subject: ENUM_POLICY_SUBJECT.USER, @@ -400,7 +438,7 @@ export class UserAdminController { @ApiKeyPublicProtected() @HttpCode(HttpStatus.OK) @Post('/export') - async export(): Promise { + async export(): Promise { const users: IUserEntity[] = await this.userService.findAll( {}, @@ -409,6 +447,6 @@ export class UserAdminController { } ); - return { data: users }; + return { data: [{ data: users }] }; } } diff --git a/src/modules/user/dtos/user.import.dto.ts b/src/modules/user/dtos/user.import.dto.ts index 5fe2ef6d5..e4ac8aa3d 100644 --- a/src/modules/user/dtos/user.import.dto.ts +++ b/src/modules/user/dtos/user.import.dto.ts @@ -4,4 +4,6 @@ import { UserCreateDto } from './user.create.dto'; export class UserImportDto extends OmitType(UserCreateDto, [ 'role', 'password', + 'signUpFrom', + 'role', ] as const) {} diff --git a/src/modules/user/interfaces/user.service.interface.ts b/src/modules/user/interfaces/user.service.interface.ts index 2ba409d22..9ae920aab 100644 --- a/src/modules/user/interfaces/user.service.interface.ts +++ b/src/modules/user/interfaces/user.service.interface.ts @@ -140,4 +140,12 @@ export interface IUserService { { passwordCreated, passwordHash, salt }: IAuthPassword, options?: IDatabaseCreateManyOptions ): Promise; + existByEmails( + emails: string[], + options?: IDatabaseExistOptions + ): Promise; + existByMobileNumbers( + mobileNumbers: string[], + options?: IDatabaseExistOptions + ): Promise; } diff --git a/src/modules/user/services/user.service.ts b/src/modules/user/services/user.service.ts index 93b2741e8..9f5b12046 100644 --- a/src/modules/user/services/user.service.ts +++ b/src/modules/user/services/user.service.ts @@ -28,6 +28,7 @@ import { UserImportDto } from 'src/modules/user/dtos/user.import.dto'; import { UserUpdateUsernameDto } from 'src/modules/user/dtos/user.update-username.dto'; import { UserUpdatePasswordAttemptDto } from 'src/modules/user/dtos/user.update-password-attempt.dto'; import { AwsS3Serialization } from 'src/common/aws/serializations/aws.s3.serialization'; +import { ENUM_USER_SIGN_UP_FROM } from 'src/modules/user/constants/user.enum.constant'; @Injectable() export class UserService implements IUserService { @@ -51,10 +52,7 @@ export class UserService implements IUserService { find?: Record, options?: IDatabaseFindAllOptions ): Promise { - return this.userRepository.findAll(find, { - ...options, - join: true, - }); + return this.userRepository.findAll(find, options); } async findOneById( @@ -335,7 +333,7 @@ export class UserService implements IUserService { ): Promise { const passwordExpired: Date = this.helperDateService.backwardInDays(1); const users: UserEntity[] = data.map( - ({ email, firstName, lastName, mobileNumber, signUpFrom }) => { + ({ email, firstName, lastName, mobileNumber }) => { const create: UserEntity = new UserEntity(); create.firstName = firstName; create.email = email; @@ -351,7 +349,7 @@ export class UserService implements IUserService { create.signUpDate = this.helperDateService.create(); create.passwordAttempt = 0; create.mobileNumber = mobileNumber ?? undefined; - create.signUpFrom = signUpFrom; + create.signUpFrom = ENUM_USER_SIGN_UP_FROM.ADMIN; return create; } @@ -370,4 +368,33 @@ export class UserService implements IUserService { async getMobileNumberCountryCodeAllowed(): Promise { return this.mobileNumberCountryCodeAllowed; } + + async existByEmails( + emails: string[], + options?: IDatabaseExistOptions + ): Promise { + return this.userRepository.exists( + { + email: { + $regex: new RegExp(`\\b${emails.join('|')}\\b`), + $options: 'i', + }, + }, + { ...options, withDeleted: true } + ); + } + + async existByMobileNumbers( + mobileNumbers: string[], + options?: IDatabaseExistOptions + ): Promise { + return this.userRepository.exists( + { + mobileNumber: { + $in: mobileNumbers, + }, + }, + { ...options, withDeleted: true } + ); + } } diff --git a/src/swagger.ts b/src/swagger.ts index a6250c0c2..bc8ad3ae5 100644 --- a/src/swagger.ts +++ b/src/swagger.ts @@ -3,12 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { NestApplication } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { ENUM_APP_ENVIRONMENT } from 'src/app/constants/app.enum.constant'; -import { - AwsS3MultipartPartsSerialization, - AwsS3MultipartSerialization, -} from 'src/common/aws/serializations/aws.s3-multipart.serialization'; -import { AwsS3Serialization } from 'src/common/aws/serializations/aws.s3.serialization'; -import { ResponseDefaultSerialization } from 'src/common/response/serializations/response.default.serialization'; +import { ResponseSerialization } from 'src/common/response/serializations/response.serialization'; import { ResponsePagingSerialization } from 'src/common/response/serializations/response.paging.serialization'; import { writeFileSync } from 'fs'; @@ -48,13 +43,7 @@ export default async function (app: NestApplication) { const document = SwaggerModule.createDocument(app, documentBuild, { deepScanRoutes: true, - extraModels: [ - ResponseDefaultSerialization, - ResponsePagingSerialization, - AwsS3MultipartPartsSerialization, - AwsS3MultipartSerialization, - AwsS3Serialization, - ], + extraModels: [ResponseSerialization, ResponsePagingSerialization], }); writeFileSync('./data/swagger.json', JSON.stringify(document)); diff --git a/test/debugger/debugger.options.service.spec.ts b/test/debugger/debugger.options.service.spec.ts index 5402b1d10..21457d12a 100644 --- a/test/debugger/debugger.options.service.spec.ts +++ b/test/debugger/debugger.options.service.spec.ts @@ -45,7 +45,7 @@ describe('DebuggerOptionService', () => { expect(loggerOptions.format).toBeDefined; expect(loggerOptions).toHaveProperty('transports'); - expect(loggerOptions.transports.length).toEqual(4); + expect(loggerOptions.transports.length).toEqual(2); }); it('should return an object containing necessary options for winston logger, can into console', () => { @@ -70,7 +70,7 @@ describe('DebuggerOptionService', () => { expect(loggerOptions.format).toBeDefined; expect(loggerOptions).toHaveProperty('transports'); - expect(loggerOptions.transports.length).toEqual(1); + expect(loggerOptions.transports.length).toEqual(0); }); }); }); diff --git a/test/helper/helper.array.service.spec.ts b/test/helper/helper.array.service.spec.ts index 3b40fad7d..5f7d68b36 100644 --- a/test/helper/helper.array.service.spec.ts +++ b/test/helper/helper.array.service.spec.ts @@ -19,133 +19,63 @@ describe('HelperArrayService', () => { describe('getCombinations', () => { it('should return correct value', () => { - const testArray = [ + const result = service.getCombinations( ['a', 'b', 'c'], - [1, 2], - ]; - const result = service.getCombinations(testArray); - expect(result).toEqual([ - ['a', 1], - ['a', 2], - ['b', 1], - ['b', 2], - ['c', 1], - ['c', 2], - ]); - }); - }); - - describe('getLast', () => { - it('should return value of last array', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.getLast(testArray); - expect(result).toEqual('d'); - }); - }); - - describe('getFirst', () => { - it('should return value of first array', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.getFirst(testArray); - expect(result).toEqual('a'); + [1, 2] + ); + expect(result).toEqual([]); }); }); - describe('getFirstByIndex', () => { + describe('getFromLeft', () => { it('should return value of array by index, from first', () => { const testArray = ['a', 'b', 'c', 'd']; - const result = service.getFirstByIndex(testArray, 2); - expect(result).toEqual('c'); - }); - }); - - describe('getLastByIndex', () => { - it('should return value of array by index, from last', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.getLastByIndex(testArray, 2); - expect(result).toEqual('c'); - }); - }); - - describe('takeFirst', () => { - it('should return array, get from first', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.takeFirst(testArray, 2); + const result = service.getFromLeft(testArray, 2); expect(result).toEqual(['a', 'b']); }); }); - describe('takeLast', () => { - it('should return array, get from last', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.takeLast(testArray, 2); - expect(result).toEqual(['c', 'd']); - }); - }); - - describe('indexOf', () => { - it('should return index of variable', () => { - const testArray = ['a', 'b', 'c', 'd', 'c']; - const result = service.indexOf(testArray, 'c'); - expect(result).toEqual(2); - }); - }); - - describe('lastIndexOf', () => { - it('should return last index of variable', () => { - const testArray = ['a', 'b', 'c', 'd', 'c']; - const result = service.lastIndexOf(testArray, 'c'); - expect(result).toEqual(4); - }); - }); - - describe('remove', () => { - it('should return removed array', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result: string[] = service.remove(testArray, 'c'); - expect(result).toEqual(['c']); - }); - }); - - describe('removeFromLeft', () => { - it('should remove array element from left', () => { + describe('getFromRight', () => { + it('should return value of array by index, from last', () => { const testArray = ['a', 'b', 'c', 'd']; - const result = service.removeFromLeft(testArray, 2); + const result = service.getFromRight(testArray, 2); expect(result).toEqual(['c', 'd']); }); }); - describe('removeFromRight', () => { - it('should remove array element from right', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.removeFromRight(testArray, 2); - expect(result).toEqual(['a', 'b']); + describe('getDifference', () => { + it('should return difference between array', () => { + const a = [1, 2, 3]; + const b = [4, 5, 6]; + const result = service.getDifference(a, b); + expect(result).toEqual([1, 2, 3]); }); }); - describe('join', () => { - it('should return string value of array', () => { - const testArray = ['a', 'b', 'c', 'd']; - const delimiter = ','; - const result = service.join(testArray, delimiter); - expect(result).toEqual('a,b,c,d'); + describe('getIntersection', () => { + it('should return intersection between array', () => { + const a = [1, 2, 3]; + const b = [4, 3, 6]; + const result = service.getIntersection(a, b); + expect(result).toEqual([3]); }); }); - describe('split', () => { - it('should return array value from string', () => { - const testArray = 'a,b,c,d'; - const delimiter = ','; - const result = service.split(testArray, delimiter); - expect(result).toEqual(['a', 'b', 'c', 'd']); + describe('concat', () => { + it('should concat two arrays', () => { + const a = [1, 2, 3]; + const b = [4, 5, 6]; + const result = service.concat(a, b); + expect(result).toEqual([1, 2, 3, 4, 5, 6]); }); }); - describe('reverse', () => { - it('should return reversed array', () => { - const testArray = ['a', 'b', 'c', 'd']; - const result = service.reverse(testArray); - expect(result).toEqual(['d', 'c', 'b', 'a']); + describe('concatUnique', () => { + it('should concat two arrays with only unique values', () => { + const a = [1, 2, 3, 3]; + const b = [3, 4, 5]; + const result = service.concatUnique(a, b); + expect(result).toEqual([1, 2, 3, 4, 5]); }); }); @@ -166,24 +96,6 @@ describe('HelperArrayService', () => { }); }); - describe('merge', () => { - it('should merge two arrays', () => { - const a = [1, 2, 3]; - const b = [4, 5, 6]; - const result = service.merge(a, b); - expect(result).toEqual([1, 2, 3, 4, 5, 6]); - }); - }); - - describe('mergeUnique', () => { - it('should merge two arrays with only unique values', () => { - const a = [1, 2, 3, 3]; - const b = [3, 4, 5]; - const result = service.mergeUnique(a, b); - expect(result).toEqual([1, 2, 3, 4, 5]); - }); - }); - describe('equals', () => { it('should return true if two arrays are equal', () => { const a = [1, 2, 3]; @@ -247,39 +159,6 @@ describe('HelperArrayService', () => { expect(result).toEqual(false); }); }); - describe('intersection', () => { - it('should return intersection between array', () => { - const a = [1, 2, 3]; - const b = [4, 3, 6]; - const result = service.intersection(a, b); - expect(result).toEqual([3]); - }); - }); - - describe('difference', () => { - it('should return difference between array', () => { - const a = [1, 2, 3]; - const b = [4, 5, 6]; - const result = service.difference(a, b); - expect(result).toEqual([1, 2, 3]); - }); - }); - - describe('includes', () => { - it('should return true if array includes given value', () => { - const a = [1, 2, 3]; - const b = 3; - const result = service.includes(a, b); - expect(result).toEqual(true); - }); - - it('should return false if array does not include given value', () => { - const a = [1, 2, 3]; - const b = 4; - const result = service.includes(a, b); - expect(result).toEqual(false); - }); - }); describe('chunk', () => { it('should return chunks of desired size', () => { diff --git a/test/helper/helper.date.service.spec.ts b/test/helper/helper.date.service.spec.ts index 5b7d9c80c..bce76f0f1 100644 --- a/test/helper/helper.date.service.spec.ts +++ b/test/helper/helper.date.service.spec.ts @@ -98,20 +98,20 @@ describe('HelperDateService', () => { }); }); - describe('checkDateTime', () => { + describe('checkIso', () => { it('should check date if a given date is valid', () => { const validDate = '2021-01-01'; - expect(service.checkDateTime(validDate)).toEqual(true); + expect(service.checkIso(validDate)).toEqual(true); }); it('should check date time if a given date is valid', () => { const validDate = '2021-01-01T01:01:01.000Z'; - expect(service.checkDateTime(validDate)).toEqual(true); + expect(service.checkIso(validDate)).toEqual(true); }); it('should check date as invalid', () => { const invalidDate = 'abcd'; - expect(service.checkDateTime(invalidDate)).toEqual(false); + expect(service.checkIso(invalidDate)).toEqual(false); }); }); @@ -152,9 +152,9 @@ describe('HelperDateService', () => { }); }); - describe('timestamp', () => { + describe('createTimestamp', () => { it('should return a current timestamp', () => { - const createdTimestamp = service.timestamp(); + const createdTimestamp = service.createTimestamp(); expect(createdTimestamp).toEqual( new Date(createdTimestamp).getTime() ); @@ -163,7 +163,9 @@ describe('HelperDateService', () => { it('should return a timestamp with given options', () => { const date = '2021-01-01T00:00:00.000Z'; const startOfDay = true; - const createdTimestamp = service.timestamp(date, { startOfDay }); + const createdTimestamp = service.createTimestamp(date, { + startOfDay, + }); expect(createdTimestamp).toEqual(new Date(date).getTime()); }); }); @@ -183,33 +185,27 @@ describe('HelperDateService', () => { }); }); - describe('formatIsoDuration', () => { + describe('formatIsoDurationFromMinutes', () => { it('should return the duration as iso date string', () => { const inMinutes = 5; - const duration = service.formatIsoDuration(inMinutes); + const duration = service.formatIsoDurationFromMinutes(inMinutes); expect(duration).toEqual('PT5M'); }); }); - describe('forwardInMilliseconds', () => { - it('should add milliseconds to a date', () => { - const fromDate = new Date('2021-01-01'); - const milliseconds = 10000; - const resultDate = service.forwardInMilliseconds(milliseconds, { - fromDate, - }); - expect(resultDate).toEqual(new Date('2021-01-01T00:00:10.000Z')); + describe('formatIsoDurationFromHours', () => { + it('should return the duration as iso date string', () => { + const inHours = 5; + const duration = service.formatIsoDurationFromHours(inHours); + expect(duration).toEqual('PT5H'); }); }); - describe('backwardInMilliseconds', () => { - it('should subtract milliseconds from a date', () => { - const fromDate = new Date('2021-01-01T00:00:10.000Z'); - const milliseconds = 10000; - const resultDate = service.backwardInMilliseconds(milliseconds, { - fromDate, - }); - expect(resultDate).toEqual(new Date('2021-01-01T00:00:00.000Z')); + describe('formatIsoDurationFromDays', () => { + it('should return the duration as iso date string', () => { + const inDays = 5; + const duration = service.formatIsoDurationFromDays(inDays); + expect(duration).toEqual('P5D'); }); }); @@ -303,6 +299,24 @@ describe('HelperDateService', () => { }); }); + describe('forwardInYears', () => { + it('should add years to a date', () => { + const fromDate = new Date('2021-01-01'); + const years = 1; + const resultDate = service.forwardInYears(years, { fromDate }); + expect(resultDate).toEqual(new Date('2022-01-01T00:00:00.000Z')); + }); + }); + + describe('backwardInYears', () => { + it('should subtract years from a date', () => { + const fromDate = new Date('2021-02-01T00:00:00.000Z'); + const years = 1; + const resultDate = service.backwardInYears(years, { fromDate }); + expect(resultDate).toEqual(new Date('2020-02-01T00:00:00.000Z')); + }); + }); + describe('endOfMonth', () => { it('should return the end of the month for a given date if no date is provided', () => { const date = '2021-01-31T23:59:59.999Z'; @@ -377,11 +391,11 @@ describe('HelperDateService', () => { }); }); - describe('minusTime', () => { + describe('subtractTime', () => { it('should return date adn time added', () => { const date = '2021-01-01T00:00:00.000Z'; const startDate = service.create(date); - const setTime = service.minusTime(startDate, { + const setTime = service.subtractTime(startDate, { hour: 0, minute: 10, second: 0, @@ -390,19 +404,6 @@ describe('HelperDateService', () => { }); }); - describe('extractDate', () => { - it('should extract day, month, and year from a given date', () => { - const date = new Date('2021-01-01'); - const extractedDate = service.extractDate(date); - expect(extractedDate).toEqual({ - date, - day: '01', - month: '01', - year: '2021', - }); - }); - }); - describe('roundDown', () => { it('should round down a given date', () => { const date = new Date('2021-01-01T12:34:56.789Z'); @@ -410,6 +411,7 @@ describe('HelperDateService', () => { hour: true, minute: true, second: true, + millisecond: true, }); expect(roundedDate).toEqual(new Date('2021-01-01T00:00:00.000Z')); }); diff --git a/test/helper/helper.encryption.service.spec.ts b/test/helper/helper.encryption.service.spec.ts index 28a03ec5f..9139d88fe 100644 --- a/test/helper/helper.encryption.service.spec.ts +++ b/test/helper/helper.encryption.service.spec.ts @@ -86,6 +86,20 @@ describe('HelperEncryptionService', () => { }); }); + describe('aes256Compare', () => { + it('should return true when given two identical base64 strings', () => { + expect( + service.aes256Compare('SGVsbG8gV29ybGQh', 'SGVsbG8gV29ybGQh') + ).toBe(true); + }); + + it('should return false when given two different base64 strings', () => { + expect( + service.aes256Compare('SGVsbG8gV29ybGQh', 'SGVsbG8gV29ybw==') + ).toBe(false); + }); + }); + describe('jwtEncrypt', () => { it('should return JWT token when given payload and options', () => { const payload = { name: 'Jane Doe' }; diff --git a/test/helper/helper.file.service.spec.ts b/test/helper/helper.file.service.spec.ts index 90a58c414..8bdb1dff1 100644 --- a/test/helper/helper.file.service.spec.ts +++ b/test/helper/helper.file.service.spec.ts @@ -17,47 +17,61 @@ describe('HelperFileService', () => { expect(service).toBeDefined(); }); - describe('createExcelWorkbook', () => { - it('should return a workbook when given rows', () => { + describe('writeCsv', () => { + it('should return a buffer of csv', () => { const rows = [ { make: 'Ford', model: 'Mustang', year: 2020 }, { make: 'Tesla', model: 'Model S', year: 2021 }, ]; - const workbook = service.createExcelWorkbook(rows); - expect(workbook).toBeDefined(); + const buffer = service.writeCsv({ data: rows }); + expect(buffer).toBeDefined(); + expect(buffer).toBeInstanceOf(Buffer); }); }); - describe('writeExcelToBuffer', () => { - it('should return a buffer when given a workbook', () => { + describe('writeExcel', () => { + it('should return a buffer of excel', () => { const rows = [ { make: 'Ford', model: 'Mustang', year: 2020 }, { make: 'Tesla', model: 'Model S', year: 2021 }, ]; - const workbook = service.createExcelWorkbook(rows); - const buffer = service.writeExcelToBuffer(workbook); + const buffer = service.writeExcel([{ data: rows }]); + expect(buffer).toBeDefined(); expect(buffer).toBeInstanceOf(Buffer); }); }); - describe('readExcelFromBuffer', () => { - it('should return rows when given a buffer', () => { + describe('readCsv', () => { + it('should return rows when given a buffer csv', () => { const rows = [ { make: 'Ford', model: 'Mustang', year: 2020 }, { make: 'Tesla', model: 'Model S', year: 2021 }, ]; - const workbook = service.createExcelWorkbook(rows); - const buffer = service.writeExcelToBuffer(workbook); - const newRows = service.readExcelFromBuffer(buffer); - expect(newRows).toEqual([rows]); + const buffer = service.writeCsv({ data: rows, sheetName: 'test' }); + const newRows = service.readCsv(buffer); + expect(newRows).toBeDefined(); + expect(newRows.sheetName).toBe('Sheet1'); + expect(newRows.data.length).toBe(2); + expect(newRows.data[0].make).toBe('Ford'); }); }); - describe('convertToBytes', () => { - it('should return bytes when given a megabyte string', () => { - const megabytes = '1MB'; - const bytes = service.convertToBytes(megabytes); - expect(bytes).toEqual(1048576); + describe('readExcel', () => { + it('should return rows when given a buffer excel', () => { + const rows = [ + { make: 'Ford', model: 'Mustang', year: 2020 }, + { make: 'Tesla', model: 'Model S', year: 2021 }, + ]; + const buffer = service.writeExcel([ + { data: rows, sheetName: 'test' }, + ]); + const newRows = service.readExcel(buffer); + + expect(newRows).toBeDefined(); + expect(newRows.length).toBe(1); + expect(newRows[0].sheetName).toBe('test'); + expect(newRows[0].data.length).toBe(2); + expect(newRows[0].data[0].make).toBe('Ford'); }); }); }); diff --git a/test/helper/helper.number.service.spec.ts b/test/helper/helper.number.service.spec.ts index 665a653bc..b4275de35 100644 --- a/test/helper/helper.number.service.spec.ts +++ b/test/helper/helper.number.service.spec.ts @@ -27,12 +27,6 @@ describe('HelperNumberService', () => { }); }); - describe('create', () => { - it('should return a number when given a string number', () => { - expect(service.create(mockNumber)).toBe(1234); - }); - }); - describe('random', () => { it('should return a random number of the given length', () => { expect(service.random(4)).toBeGreaterThanOrEqual(1000); diff --git a/test/helper/helper.string.service.spec.ts b/test/helper/helper.string.service.spec.ts index c9c0dbaf2..c396731bc 100644 --- a/test/helper/helper.string.service.spec.ts +++ b/test/helper/helper.string.service.spec.ts @@ -17,28 +17,8 @@ describe('HelperStringService', () => { expect(service).toBeDefined(); }); - describe('checkEmail', () => { - it('should return true for a valid email', () => { - const email = 'test@example.com'; - expect(service.checkEmail(email)).toBe(true); - }); - - it('should return false for an invalid email', () => { - const email = 'invalid-email'; - expect(service.checkEmail(email)).toBe(false); - }); - }); - describe('randomReference', () => { - it('should return a random reference with a timestamp prefix', () => { - const length = 8; - const prefix = 'order'; - const reference = service.randomReference(length, prefix); - const regex = new RegExp(`^${prefix}-\\d{13}\\w{${length}}$`); - expect(regex.test(reference)).toBe(true); - }); - - it('should return a random reference with only a timestamp', () => { + it('should return a random reference', () => { const length = 8; const reference = service.randomReference(length); const regex = new RegExp(`^\\d{13}\\w{${length}}$`); @@ -59,32 +39,49 @@ describe('HelperStringService', () => { const options: IHelperStringRandomOptions = { safe: true, upperCase: true, - prefix: 'AB', }; const randomString = service.random(length, options); - const regex = new RegExp(`^AB[A-Z]{6}$`); + const regex = new RegExp(`^[A-Z]{8}$`); expect(regex.test(randomString)).toBe(true); }); }); describe('censor', () => { - it('should not censor strings less than equals 5 characters in length', () => { + it('should not censor strings less than equals 3 characters in length', () => { const value = 'her'; const censoredValue = service.censor(value); - expect(censoredValue).toBe('her'); + expect(censoredValue).toBe('**r'); + }); + + it('should not censor strings less than equals 10 characters in length', () => { + const value = 'ensorMe'; + const censoredValue = service.censor(value); + expect(censoredValue).toBe('*******rMe'); }); - it('should censor string from start, because string length is less than equals 10', () => { - const value = 'censor me'; + it('should censor string from start, because string length is less than equals 25', () => { + const value = 'censorMeGogoNow'; const censoredValue = service.censor(value); - expect(censoredValue).toBe('********or me'); + expect(censoredValue).toBe('********goNow'); }); it('should censor in the middle of string, because string length more than 10', () => { - const value = 'censor me gogo'; + const value = 'censorMeGogoNowLongestMoreThan25'; const censoredValue = service.censor(value); - expect(censoredValue).toBe('cen******** gogo'); + expect(censoredValue).toBe('cen**********MoreThan25'); + }); + }); + + describe('checkEmail', () => { + it('should return true for a valid email', () => { + const email = 'test@example.com'; + expect(service.checkEmail(email)).toBe(true); + }); + + it('should return false for an invalid email', () => { + const email = 'invalid-email'; + expect(service.checkEmail(email)).toBe(false); }); }); @@ -95,7 +92,7 @@ describe('HelperStringService', () => { }); it('should return false if the password is not weak pattern', () => { - const password = 'strongpassword1'; + const password = 'weakpassword'; expect(service.checkPasswordWeak(password)).toBe(false); }); }); @@ -107,7 +104,7 @@ describe('HelperStringService', () => { }); it('should return false if the password is not medium strength pattern', () => { - const password = 'STRONGPassword'; + const password = 'mediumpassword'; expect(service.checkPasswordMedium(password)).toBe(false); }); }); @@ -119,7 +116,7 @@ describe('HelperStringService', () => { }); it('should return false if the password is not strong pattern', () => { - const password = 'weakpassword'; + const password = 'strongpassword'; expect(service.checkPasswordStrong(password)).toBe(false); }); }); @@ -140,7 +137,15 @@ describe('HelperStringService', () => { it('should return string that formatted as currency', () => { const num = 1000; - expect(service.formatCurrency(num)).toBe('1.000'); + expect(service.formatCurrency(num)).toBe('1,000'); + }); + + it('should return string that formatted as currency with locale id-ID', () => { + const num = 1000; + + expect(service.formatCurrency(num, { locale: 'id-ID' })).toBe( + '1.000' + ); }); }); }); diff --git a/test/message/message.service.spec.ts b/test/message/message.service.spec.ts index dce29f31c..699823eb0 100644 --- a/test/message/message.service.spec.ts +++ b/test/message/message.service.spec.ts @@ -3,8 +3,8 @@ import { ConfigService } from '@nestjs/config'; import { I18nService } from 'nestjs-i18n'; import { ValidationError } from 'class-validator'; import { MessageService } from 'src/common/message/services/message.service'; -import { IValidationErrorImport } from 'src/common/error/interfaces/error.interface'; import { HelperArrayService } from 'src/common/helper/services/helper.array.service'; +import { IErrorValidationImport } from 'src/common/error/interfaces/error.interface'; describe('MessageService', () => { let service: MessageService; @@ -17,7 +17,7 @@ describe('MessageService', () => { let validationError2: ValidationError[]; let validationError3: ValidationError[]; let validationError4: ValidationError[]; - let validationErrorImport: IValidationErrorImport[]; + let validationErrorImport: IErrorValidationImport[]; beforeEach(async () => { const moduleRefRef = await Test.createTestingModule({ @@ -163,7 +163,6 @@ describe('MessageService', () => { validationErrorImport = [ { row: 0, - file: 'error.xlsx', errors: [ { target: { @@ -185,7 +184,6 @@ describe('MessageService', () => { }, { row: 1, - file: 'error.xlsx', errors: [ { target: { @@ -205,7 +203,6 @@ describe('MessageService', () => { }, { row: 2, - file: 'error.xlsx', errors: [ { target: { @@ -243,7 +240,6 @@ describe('MessageService', () => { }, { row: 3, - file: 'error.xlsx', errors: [ { target: { @@ -264,7 +260,6 @@ describe('MessageService', () => { }, { row: 4, - file: 'error.xlsx', errors: [ { target: { @@ -300,7 +295,6 @@ describe('MessageService', () => { }, { row: 5, - file: 'error.xlsx', errors: [ { target: { @@ -438,7 +432,6 @@ describe('MessageService', () => { expect(message.length).toEqual(validationErrorImport.length); expect(message[0].errors.length).toEqual(2); - expect(message[0].file).toBeDefined(); expect(message[0].row).toBeDefined(); }); }); diff --git a/yarn.lock b/yarn.lock index e09ad444e..3c8e7ca84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,18 +26,6 @@ rxjs "7.8.1" source-map "0.7.4" -"@angular-devkit/core@17.0.9": - version "17.0.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-17.0.9.tgz#f79ff77fc38e8af1af4694acfb5b480339f073e1" - integrity sha512-r5jqwpWOgowqe9KSDqJ3iSbmsEt2XPjSvRG4DSI2T9s31bReoMtreo8b7wkRa2B3hbcDnstFbn8q27VvJDqRaQ== - dependencies: - ajv "8.12.0" - ajv-formats "2.1.1" - jsonc-parser "3.2.0" - picomatch "3.0.1" - rxjs "7.8.1" - source-map "0.7.4" - "@angular-devkit/core@17.1.2": version "17.1.2" resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-17.1.2.tgz#bf2c3475e9ff853dc53d8dc8ce9bbf8b2f1193f8" @@ -73,17 +61,6 @@ ora "5.4.1" rxjs "7.8.1" -"@angular-devkit/schematics@17.0.9": - version "17.0.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-17.0.9.tgz#8370d21cf0ac0f5f99b7a27fcf626cc5cd682c95" - integrity sha512-5ti7g45F2KjDJS0DbgnOGI1GyKxGpn4XsKTYJFJrSAWj6VpuvPy/DINRrXNuRVo09VPEkqA+IW7QwaG9icptQg== - dependencies: - "@angular-devkit/core" "17.0.9" - jsonc-parser "3.2.0" - magic-string "0.30.5" - ora "5.4.1" - rxjs "7.8.1" - "@angular-devkit/schematics@17.1.2": version "17.1.2" resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-17.1.2.tgz#ca77a86ed44ab227614aff6e1f7ce4f3cd0c6ded" @@ -172,37 +149,37 @@ "@aws-sdk/util-utf8-browser" "^3.0.0" tslib "^1.11.1" -"@aws-sdk/client-s3@^3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.507.0.tgz#3e4205a844d8fbd8656f66d0a3ba1c8aaa7b9b96" - integrity sha512-rRLiC5Ly3e7kZVNoRsG6JhZ8Yat5uEnDeShdWNdHchyTO88AaEnHaeyiVG9ecmKI8jYl6NbWSHB8xL0l9KIr/w== +"@aws-sdk/client-s3@^3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.513.0.tgz#3353cd48a3815c2ca8ed492e7cd5e4c3ea3f9269" + integrity sha512-Y7kbPLvVVgcn38sTyQP/WnD5Zc7lnJ4XQ8qIPobbkwhCL+rl4hIWcxpQLf1OGS4zw2fBFQAxZnDotuBrAvgNsw== dependencies: "@aws-crypto/sha1-browser" "3.0.0" "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.507.0" - "@aws-sdk/core" "3.496.0" - "@aws-sdk/credential-provider-node" "3.507.0" - "@aws-sdk/middleware-bucket-endpoint" "3.502.0" - "@aws-sdk/middleware-expect-continue" "3.502.0" - "@aws-sdk/middleware-flexible-checksums" "3.502.0" - "@aws-sdk/middleware-host-header" "3.502.0" - "@aws-sdk/middleware-location-constraint" "3.502.0" - "@aws-sdk/middleware-logger" "3.502.0" - "@aws-sdk/middleware-recursion-detection" "3.502.0" - "@aws-sdk/middleware-sdk-s3" "3.502.0" - "@aws-sdk/middleware-signing" "3.502.0" - "@aws-sdk/middleware-ssec" "3.502.0" - "@aws-sdk/middleware-user-agent" "3.502.0" - "@aws-sdk/region-config-resolver" "3.502.0" - "@aws-sdk/signature-v4-multi-region" "3.502.0" - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" - "@aws-sdk/util-user-agent-browser" "3.502.0" - "@aws-sdk/util-user-agent-node" "3.502.0" + "@aws-sdk/client-sts" "3.513.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/credential-provider-node" "3.513.0" + "@aws-sdk/middleware-bucket-endpoint" "3.511.0" + "@aws-sdk/middleware-expect-continue" "3.511.0" + "@aws-sdk/middleware-flexible-checksums" "3.511.0" + "@aws-sdk/middleware-host-header" "3.511.0" + "@aws-sdk/middleware-location-constraint" "3.511.0" + "@aws-sdk/middleware-logger" "3.511.0" + "@aws-sdk/middleware-recursion-detection" "3.511.0" + "@aws-sdk/middleware-sdk-s3" "3.511.0" + "@aws-sdk/middleware-signing" "3.511.0" + "@aws-sdk/middleware-ssec" "3.511.0" + "@aws-sdk/middleware-user-agent" "3.511.0" + "@aws-sdk/region-config-resolver" "3.511.0" + "@aws-sdk/signature-v4-multi-region" "3.511.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" + "@aws-sdk/util-user-agent-browser" "3.511.0" + "@aws-sdk/util-user-agent-node" "3.511.0" "@aws-sdk/xml-builder" "3.496.0" "@smithy/config-resolver" "^2.1.1" - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/eventstream-serde-browser" "^2.1.1" "@smithy/eventstream-serde-config-resolver" "^2.1.1" "@smithy/eventstream-serde-node" "^2.1.1" @@ -227,7 +204,7 @@ "@smithy/util-body-length-browser" "^2.1.1" "@smithy/util-body-length-node" "^2.2.1" "@smithy/util-defaults-mode-browser" "^2.1.1" - "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" "@smithy/util-endpoints" "^1.1.1" "@smithy/util-retry" "^2.1.1" "@smithy/util-stream" "^2.1.1" @@ -236,28 +213,27 @@ fast-xml-parser "4.2.5" tslib "^2.5.0" -"@aws-sdk/client-ses@^3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ses/-/client-ses-3.507.0.tgz#0fbe6800cf9e00758b92be2b536466a81842733c" - integrity sha512-eX/OHHA4Zk7EgsaPnL4sQmghekipmiGJBm/E+JEoiaBoPJOPj0q28pnJKm6rMVUnhddaQZUuAYw9cSCyT3zoDg== +"@aws-sdk/client-ses@^3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ses/-/client-ses-3.513.0.tgz#7042dfe387c848dfe14cf04b8b0033d07564a060" + integrity sha512-9pvzyCZGVO283OPAdUkSC4QPY7Sfk9jNqs0gzLQvqM1FggjS1jc6vbMqBcRCte87fXkSPyLo0IEX/kaMH4dEMQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.507.0" - "@aws-sdk/core" "3.496.0" - "@aws-sdk/credential-provider-node" "3.507.0" - "@aws-sdk/middleware-host-header" "3.502.0" - "@aws-sdk/middleware-logger" "3.502.0" - "@aws-sdk/middleware-recursion-detection" "3.502.0" - "@aws-sdk/middleware-signing" "3.502.0" - "@aws-sdk/middleware-user-agent" "3.502.0" - "@aws-sdk/region-config-resolver" "3.502.0" - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" - "@aws-sdk/util-user-agent-browser" "3.502.0" - "@aws-sdk/util-user-agent-node" "3.502.0" + "@aws-sdk/client-sts" "3.513.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/credential-provider-node" "3.513.0" + "@aws-sdk/middleware-host-header" "3.511.0" + "@aws-sdk/middleware-logger" "3.511.0" + "@aws-sdk/middleware-recursion-detection" "3.511.0" + "@aws-sdk/middleware-user-agent" "3.511.0" + "@aws-sdk/region-config-resolver" "3.511.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" + "@aws-sdk/util-user-agent-browser" "3.511.0" + "@aws-sdk/util-user-agent-node" "3.511.0" "@smithy/config-resolver" "^2.1.1" - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/fetch-http-handler" "^2.4.1" "@smithy/hash-node" "^2.1.1" "@smithy/invalid-dependency" "^2.1.1" @@ -276,35 +252,35 @@ "@smithy/util-body-length-browser" "^2.1.1" "@smithy/util-body-length-node" "^2.2.1" "@smithy/util-defaults-mode-browser" "^2.1.1" - "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" "@smithy/util-retry" "^2.1.1" "@smithy/util-utf8" "^2.1.1" "@smithy/util-waiter" "^2.1.1" fast-xml-parser "4.2.5" tslib "^2.5.0" -"@aws-sdk/client-sso-oidc@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.507.0.tgz#d1357d212d9510146d325ca1e6acd06d5744623b" - integrity sha512-ms5CH2ImhqqCIbo5irxayByuPOlVAmSiqDVfjZKwgIziqng2bVgNZMeKcT6t0bmrcgScEAVnZwY7j/iZTIw73g== +"@aws-sdk/client-sso-oidc@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.513.0.tgz#a82c5eb7806781d1bbf48d514b37998e68912cb6" + integrity sha512-DyncBVOR5aENL6vOeHPllIAwWUaDZdj1aRKVWiNECG4LuuwwjASX0wFLxTRe/4al3Ugob0OLqsrgC2hd59BLJA== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.507.0" - "@aws-sdk/core" "3.496.0" - "@aws-sdk/middleware-host-header" "3.502.0" - "@aws-sdk/middleware-logger" "3.502.0" - "@aws-sdk/middleware-recursion-detection" "3.502.0" - "@aws-sdk/middleware-signing" "3.502.0" - "@aws-sdk/middleware-user-agent" "3.502.0" - "@aws-sdk/region-config-resolver" "3.502.0" - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" - "@aws-sdk/util-user-agent-browser" "3.502.0" - "@aws-sdk/util-user-agent-node" "3.502.0" + "@aws-sdk/client-sts" "3.513.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.511.0" + "@aws-sdk/middleware-logger" "3.511.0" + "@aws-sdk/middleware-recursion-detection" "3.511.0" + "@aws-sdk/middleware-user-agent" "3.511.0" + "@aws-sdk/region-config-resolver" "3.511.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" + "@aws-sdk/util-user-agent-browser" "3.511.0" + "@aws-sdk/util-user-agent-node" "3.511.0" "@smithy/config-resolver" "^2.1.1" - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/fetch-http-handler" "^2.4.1" "@smithy/hash-node" "^2.1.1" "@smithy/invalid-dependency" "^2.1.1" @@ -323,31 +299,32 @@ "@smithy/util-body-length-browser" "^2.1.1" "@smithy/util-body-length-node" "^2.2.1" "@smithy/util-defaults-mode-browser" "^2.1.1" - "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" "@smithy/util-retry" "^2.1.1" "@smithy/util-utf8" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/client-sso@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.507.0.tgz#90a5de90f662aa680c0ffdc5e04695734ca8afb2" - integrity sha512-pFeaKwqv4tXD6QVxWC2V4N62DUoP3bPSm/mCe2SPhaNjNsmwwA53viUHz/nwxIbs8w4vV44UQsygb0AgKm+HoQ== +"@aws-sdk/client-sso@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.513.0.tgz#d81c3fe2ba915e81826f3e96c85fa445c925e8f4" + integrity sha512-621Aj/KrgvKJXXViatb3zM+TdM3n+lodmMbSm+FH37RqYoj36s5FgmXan3Ebu9WBu1lUzKm+a3ZyRWVces52uQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/core" "3.496.0" - "@aws-sdk/middleware-host-header" "3.502.0" - "@aws-sdk/middleware-logger" "3.502.0" - "@aws-sdk/middleware-recursion-detection" "3.502.0" - "@aws-sdk/middleware-user-agent" "3.502.0" - "@aws-sdk/region-config-resolver" "3.502.0" - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" - "@aws-sdk/util-user-agent-browser" "3.502.0" - "@aws-sdk/util-user-agent-node" "3.502.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.511.0" + "@aws-sdk/middleware-logger" "3.511.0" + "@aws-sdk/middleware-recursion-detection" "3.511.0" + "@aws-sdk/middleware-user-agent" "3.511.0" + "@aws-sdk/region-config-resolver" "3.511.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" + "@aws-sdk/util-user-agent-browser" "3.511.0" + "@aws-sdk/util-user-agent-node" "3.511.0" "@smithy/config-resolver" "^2.1.1" - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/fetch-http-handler" "^2.4.1" "@smithy/hash-node" "^2.1.1" "@smithy/invalid-dependency" "^2.1.1" @@ -366,31 +343,32 @@ "@smithy/util-body-length-browser" "^2.1.1" "@smithy/util-body-length-node" "^2.2.1" "@smithy/util-defaults-mode-browser" "^2.1.1" - "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" "@smithy/util-retry" "^2.1.1" "@smithy/util-utf8" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/client-sts@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.507.0.tgz#0a99b5b04ca8d2e30a52840cc67181b3f2ac990a" - integrity sha512-TOWBe0ApEh32QOib0R+irWGjd1F9wnhbGV5PcB9SakyRwvqwG5MKOfYxG7ocoDqLlaRwzZMidcy/PV8/OEVNKg== +"@aws-sdk/client-sts@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.513.0.tgz#cc957fc3a764bc983335266aefa37b97c5ea73a6" + integrity sha512-reWhX5CO+XZhT8xIdDPnEws0KQNBuvcSY2W7niSPVYfq1mOLkQgYenP/sC/TyvnNuZDzgcmJQdbdAKHuZvMuUQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/core" "3.496.0" - "@aws-sdk/middleware-host-header" "3.502.0" - "@aws-sdk/middleware-logger" "3.502.0" - "@aws-sdk/middleware-recursion-detection" "3.502.0" - "@aws-sdk/middleware-user-agent" "3.502.0" - "@aws-sdk/region-config-resolver" "3.502.0" - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" - "@aws-sdk/util-user-agent-browser" "3.502.0" - "@aws-sdk/util-user-agent-node" "3.502.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.511.0" + "@aws-sdk/middleware-logger" "3.511.0" + "@aws-sdk/middleware-recursion-detection" "3.511.0" + "@aws-sdk/middleware-user-agent" "3.511.0" + "@aws-sdk/region-config-resolver" "3.511.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" + "@aws-sdk/util-user-agent-browser" "3.511.0" + "@aws-sdk/util-user-agent-node" "3.511.0" "@smithy/config-resolver" "^2.1.1" - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/fetch-http-handler" "^2.4.1" "@smithy/hash-node" "^2.1.1" "@smithy/invalid-dependency" "^2.1.1" @@ -409,7 +387,7 @@ "@smithy/util-body-length-browser" "^2.1.1" "@smithy/util-body-length-node" "^2.2.1" "@smithy/util-defaults-mode-browser" "^2.1.1" - "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" "@smithy/util-endpoints" "^1.1.1" "@smithy/util-middleware" "^2.1.1" "@smithy/util-retry" "^2.1.1" @@ -417,34 +395,34 @@ fast-xml-parser "4.2.5" tslib "^2.5.0" -"@aws-sdk/core@3.496.0": - version "3.496.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.496.0.tgz#ec1394753b6b2f6e38aea593e30b2db5c7390969" - integrity sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A== +"@aws-sdk/core@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.513.0.tgz#9fce86d472f7b38724cb1156d06a854124a51aaa" + integrity sha512-L+9DL4apWuqNKVOMJ8siAuWoRM9rZf9w1iPv8S2o83WO2jVK7E/m+rNW1dFo9HsA5V1ccDl2H2qLXx24HiHmOw== dependencies: - "@smithy/core" "^1.3.1" + "@smithy/core" "^1.3.2" "@smithy/protocol-http" "^3.1.1" "@smithy/signature-v4" "^2.1.1" "@smithy/smithy-client" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-env@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.502.0.tgz#800e63b2b9d90b078a120d474d5a3b1ec5b48514" - integrity sha512-KIB8Ae1Z7domMU/jU4KiIgK4tmYgvuXlhR54ehwlVHxnEoFPoPuGHFZU7oFn79jhhSLUFQ1lRYMxP0cEwb7XeQ== +"@aws-sdk/credential-provider-env@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.511.0.tgz#54084b6f8762cb102dc31a7604c618adb7e2865d" + integrity sha512-4VUsnLRox8YzxnZwnFrfZM4bL5KKLhsjjjX7oiuLyzFkhauI4HFYt7rTB8YNGphpqAg/Wzw5DBZfO3Bw1iR1HA== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-http@3.503.1": - version "3.503.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.503.1.tgz#e882a4b740c9193650053033b3001b03ca4b12c8" - integrity sha512-rTdlFFGoPPFMF2YjtlfRuSgKI+XsF49u7d98255hySwhsbwd3Xp+utTTPquxP+CwDxMHbDlI7NxDzFiFdsoZug== +"@aws-sdk/credential-provider-http@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.511.0.tgz#21b303766573649ff4cb3931159dab0ae1760077" + integrity sha512-y83Gt8GPpgMe/lMFxIq+0G2rbzLTC6lhrDocHUzqcApLD6wet8Esy2iYckSRlJgYY+qsVAzpLrSMtt85DwRPTw== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/fetch-http-handler" "^2.4.1" "@smithy/node-http-handler" "^2.3.1" "@smithy/property-provider" "^2.1.1" @@ -454,82 +432,82 @@ "@smithy/util-stream" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-ini@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.507.0.tgz#c2b9cd1bf172a0057bf0ad888c19ce5450df13f2" - integrity sha512-2CnyduoR9COgd7qH1LPYK8UggGqVs8R4ASDMB5bwGxbg9ZerlStDiHpqvJNNg1k+VlejBr++utxfmHd236XgmQ== - dependencies: - "@aws-sdk/client-sts" "3.507.0" - "@aws-sdk/credential-provider-env" "3.502.0" - "@aws-sdk/credential-provider-process" "3.502.0" - "@aws-sdk/credential-provider-sso" "3.507.0" - "@aws-sdk/credential-provider-web-identity" "3.507.0" - "@aws-sdk/types" "3.502.0" +"@aws-sdk/credential-provider-ini@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.513.0.tgz#66578517442f4284b5ae4c4b2f801b2ed750ff28" + integrity sha512-J9FAmTVHm9RsXxXluXCmJ+crkZPDpdNQhiVrbmPPq989lfr0u33rf1aKFMF5AyHNcNEWeAYKKBQwJJkcsxStIA== + dependencies: + "@aws-sdk/client-sts" "3.513.0" + "@aws-sdk/credential-provider-env" "3.511.0" + "@aws-sdk/credential-provider-process" "3.511.0" + "@aws-sdk/credential-provider-sso" "3.513.0" + "@aws-sdk/credential-provider-web-identity" "3.513.0" + "@aws-sdk/types" "3.511.0" "@smithy/credential-provider-imds" "^2.2.1" "@smithy/property-provider" "^2.1.1" "@smithy/shared-ini-file-loader" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-node@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.507.0.tgz#b6c9f3c2c8294911c4f12e267f16a26e1eba4813" - integrity sha512-tkQnmOLkRBXfMLgDYHzogrqTNdtl0Im0ipzJb2IV5hfM5NoTfCf795e9A9isgwjSP/g/YEU0xQWxa4lq8LRtuA== - dependencies: - "@aws-sdk/credential-provider-env" "3.502.0" - "@aws-sdk/credential-provider-http" "3.503.1" - "@aws-sdk/credential-provider-ini" "3.507.0" - "@aws-sdk/credential-provider-process" "3.502.0" - "@aws-sdk/credential-provider-sso" "3.507.0" - "@aws-sdk/credential-provider-web-identity" "3.507.0" - "@aws-sdk/types" "3.502.0" +"@aws-sdk/credential-provider-node@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.513.0.tgz#7ce79ce6faea1850fb8992bb86e79e5f5e6f4e9c" + integrity sha512-Cp6tYUJ+g8zJxI8vE0A9W6AxRLq3iR2zGGKsrPLNmZkUaHoVaJiNEd+2nL9RwCqDRve+N+Sh3mbZrLiqh3DO6A== + dependencies: + "@aws-sdk/credential-provider-env" "3.511.0" + "@aws-sdk/credential-provider-http" "3.511.0" + "@aws-sdk/credential-provider-ini" "3.513.0" + "@aws-sdk/credential-provider-process" "3.511.0" + "@aws-sdk/credential-provider-sso" "3.513.0" + "@aws-sdk/credential-provider-web-identity" "3.513.0" + "@aws-sdk/types" "3.511.0" "@smithy/credential-provider-imds" "^2.2.1" "@smithy/property-provider" "^2.1.1" "@smithy/shared-ini-file-loader" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-process@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.502.0.tgz#6c41d8845a1c7073491a064c158363de04640381" - integrity sha512-fJJowOjQ4infYQX0E1J3xFVlmuwEYJAFk0Mo1qwafWmEthsBJs+6BR2RiWDELHKrSK35u4Pf3fu3RkYuCtmQFw== +"@aws-sdk/credential-provider-process@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.511.0.tgz#2b44f3159ff544239a81d0f9dfcd79b1f8e90361" + integrity sha512-88hLUPqcTwjSubPS+34ZfmglnKeLny8GbmZsyllk96l26PmDTAqo5RScSA8BWxL0l5pRRWGtcrFyts+oibHIuQ== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/shared-ini-file-loader" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-sso@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.507.0.tgz#e98cf7fad69b4c12aa85c44affe9aae4cc81d796" - integrity sha512-6WBjou52QukFpDi4ezb19bcAx/bM8ge8qnJnRT02WVRmU6zFQ5yLD2fW1MFsbX3cwbey+wSqKd5FGE1Hukd5wQ== +"@aws-sdk/credential-provider-sso@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.513.0.tgz#1a61776486ec98873b3d1140a5fcee4ab3b83b8b" + integrity sha512-q9rRwRWVut97+hnc0Yt77tGeKoPLLDpKKVpVGC6e+EQHlXM4H6oq2VGLgXYJPA9HpMJ3t5zmmgHxEafYeFZo+w== dependencies: - "@aws-sdk/client-sso" "3.507.0" - "@aws-sdk/token-providers" "3.507.0" - "@aws-sdk/types" "3.502.0" + "@aws-sdk/client-sso" "3.513.0" + "@aws-sdk/token-providers" "3.513.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/shared-ini-file-loader" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/credential-provider-web-identity@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.507.0.tgz#22e028e2dd2a0a927707da1408099bc4f5b7a606" - integrity sha512-f+aGMfazBimX7S06224JRYzGTaMh1uIhfj23tZylPJ05KxTVi5IO1RoqeI/uHLJ+bDOx+JHBC04g/oCdO4kHvw== +"@aws-sdk/credential-provider-web-identity@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.513.0.tgz#9ac61426c7ea969efc6e1d80eb4d0f92e0be2e37" + integrity sha512-0EZUQhbDaV3jxvIjcWEGiGmioFS0vEvUxaJrMgeRLUo9njZfLZ4VaEMsqPnZ9rMz2w9CxfpDeObEQlDzYeGRgA== dependencies: - "@aws-sdk/client-sts" "3.507.0" - "@aws-sdk/types" "3.502.0" + "@aws-sdk/client-sts" "3.513.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-bucket-endpoint@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.502.0.tgz#580ef680c8b3b1230d78598089414769331f2a4a" - integrity sha512-mUSP2DUcjhO5zM2b21CvZ9AqwI8DaAeZA6NYHOxWGTV9BUxHcdGWXEjDkcVj9CQ0gvNwTtw6B5L/q52rVAnZbw== +"@aws-sdk/middleware-bucket-endpoint@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.511.0.tgz#48c9c5242a488dcfa0323ce4db90d02fe253efb7" + integrity sha512-G4dAAHPUZbpDCVBaCcAOlFoctO9lcecSs0EZYrvzQc/9d4XJvNWGd1C7GSdf204VPOCPZCjNpTkdWGm25r00wA== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@aws-sdk/util-arn-parser" "3.495.0" "@smithy/node-config-provider" "^2.2.1" "@smithy/protocol-http" "^3.1.1" @@ -537,74 +515,74 @@ "@smithy/util-config-provider" "^2.2.1" tslib "^2.5.0" -"@aws-sdk/middleware-expect-continue@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.502.0.tgz#fd265571e1f3a4855714fda34252de751fb054dd" - integrity sha512-DxfAuBVuPSt8as9xP57o8ks6ySVSjwO2NNNAdpLwk4KhEAPYEpHlf2yWYorYLrS+dDmwfYgOhRNoguuBdCu6ow== +"@aws-sdk/middleware-expect-continue@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.511.0.tgz#ac96f26a55f5fd10e32c354f5c5e94be154dad6c" + integrity sha512-zjDzrJV9PFCkEqhNLKKK+9PB1vPveVZLJbcY71V3PZFvPII1bhlgwvI1e99MhEiaiH2a9I2PnS56bGwEKuNTrw== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/protocol-http" "^3.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-flexible-checksums@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.502.0.tgz#e4fa059f3c4603bd815f16d69e1c4277c4c4830a" - integrity sha512-kCt2zQDFumz/LnJJJOSd2GW4dr8oT8YMJKgxC/pph3aRXoSHXRwhrMbFnQ8swEE9vjywxtcED8sym0b0tNhhoA== +"@aws-sdk/middleware-flexible-checksums@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.511.0.tgz#a11d39c51d3f3ff4e2e5f745eceb6f1231d94bdb" + integrity sha512-oI8zULi6VXLXJ3zA6aCdbOoceSNOxGITosB7EKDsLllzAQFV1WlzmQCtjFY8DLLYZ521atgJNcVbzjxPQnrnJA== dependencies: "@aws-crypto/crc32" "3.0.0" "@aws-crypto/crc32c" "3.0.0" - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/is-array-buffer" "^2.1.1" "@smithy/protocol-http" "^3.1.1" "@smithy/types" "^2.9.1" "@smithy/util-utf8" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/middleware-host-header@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.502.0.tgz#2651fb3509990271c89eb50133fb17cb8ae435f6" - integrity sha512-EjnG0GTYXT/wJBmm5/mTjDcAkzU8L7wQjOzd3FTXuTCNNyvAvwrszbOj5FlarEw5XJBbQiZtBs+I5u9+zy560w== +"@aws-sdk/middleware-host-header@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.511.0.tgz#4efc08d7fecf73492b15cfc66fce9b2f4684173d" + integrity sha512-DbBzQP/6woSHR/+g9dHN3YiYaLIqFw9u8lQFMxi3rT3hqITFVYLzzXtEaHjDD6/is56pNT84CIKbyJ6/gY5d1Q== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/protocol-http" "^3.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-location-constraint@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.502.0.tgz#188c3bae2e908aff11030af10bc3b64c87905910" - integrity sha512-fLRwPuTZvEWQkPjys03m3D6tYN4kf7zU6+c8mJxwvEg+yfBuv2RBsbd+Vn2bTisUjXvIg1kyBzONlpHoIyFneg== +"@aws-sdk/middleware-location-constraint@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.511.0.tgz#196effea8560186d586742221803f423907476a0" + integrity sha512-PKHnOT3oBo41NELq3Esz3K9JuV1l9E+SrCcfr/07yU4EbqhS4UGPb22Yf5JakQu4fGbTFlAftcc8PXcE2zLr4g== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-logger@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.502.0.tgz#558cefdd233779f15687957f9f07497199b22d72" - integrity sha512-FDyv6K4nCoHxbjLGS2H8ex8I0KDIiu4FJgVRPs140ZJy6gE5Pwxzv6YTzZGLMrnqcIs9gh065Lf6DjwMelZqaw== +"@aws-sdk/middleware-logger@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.511.0.tgz#646525c397713a08f490beb5c955ccb326cf4207" + integrity sha512-EYU9dBlJXvQcCsM2Tfgi0NQoXrqovfDv/fDy8oGJgZFrgNuHDti8tdVVxeJTUJNEAF67xlDl5o+rWEkKthkYGQ== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-recursion-detection@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.502.0.tgz#c22e2c0c1d551e58c788264687324bb7186af2cc" - integrity sha512-hvbyGJbxeuezxOu8VfFmcV4ql1hKXLxHTe5FNYfEBat2KaZXVhc1Hg+4TvB06/53p+E8J99Afmumkqbxs2esUA== +"@aws-sdk/middleware-recursion-detection@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.511.0.tgz#ac3ce292e3dc3b5dca86a03d8e66fa9e11beb9fc" + integrity sha512-PlNPCV/6zpDVdNx1K69xDTh/wPNU4WyP4qa6hUo2/+4/PNG5HI9xbCWtpb4RjhdTRw6qDtkBNcPICHbtWx5aHg== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/protocol-http" "^3.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-s3@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.502.0.tgz#a2d968414247fd9cbfc90e1071f29e4375cb25b8" - integrity sha512-GbGugrfyL5bNA/zw8iQll92yXBONfWSC8Ns00DtkOU1saPXp4/7WHtyyZGYdvPa73T1IsuZy9egpoYRBmRcd5Q== +"@aws-sdk/middleware-sdk-s3@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.511.0.tgz#b49858e86bda505a2dea88207c68a02db9c961a5" + integrity sha512-SKJr8mKaqjcGpu0xxRPXZiKrJmyetDfgzvWuZ7QOgdnPa+6jk5fmEUTFoPb3VCarMkf8xo/l6cTZ5lei7Lbflw== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@aws-sdk/util-arn-parser" "3.495.0" "@smithy/node-config-provider" "^2.2.1" "@smithy/protocol-http" "^3.1.1" @@ -614,12 +592,12 @@ "@smithy/util-config-provider" "^2.2.1" tslib "^2.5.0" -"@aws-sdk/middleware-signing@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.502.0.tgz#48b3503147eecb1a53a63633462de353668f635a" - integrity sha512-4hF08vSzJ7L6sB+393gOFj3s2N6nLusYS0XrMW6wYNFU10IDdbf8Z3TZ7gysDJJHEGQPmTAesPEDBsasGWcMxg== +"@aws-sdk/middleware-signing@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.511.0.tgz#9491193ab983a78c08dc924cdf181ca90c30d978" + integrity sha512-IMijFLfm+QQHD6NNDX9k3op9dpBSlWKnqjcMU38Tytl2nbqV4gktkarOK1exHAmH7CdoYR5BufVtBzbASNSF/A== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/protocol-http" "^3.1.1" "@smithy/signature-v4" "^2.1.1" @@ -627,66 +605,66 @@ "@smithy/util-middleware" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/middleware-ssec@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.502.0.tgz#0abdebedd98b284112c2eda36f707111a8a3cbd5" - integrity sha512-1nidVTIba6/aVjjzD/WNqWdzSyTrXOHO3Ddz2MGD8S1yGSrYz4iYaq4Bm/uosfdr8B1L0Ws0pjdRXrNfzSw/DQ== +"@aws-sdk/middleware-ssec@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.511.0.tgz#655995a7dd08c890451c6ed22eee4e354c47acbf" + integrity sha512-8pfgBard9pj7oWJ79R6dbXHUGr7JPP/OmAsKBYZA0r/91a1XdFUDtRYZadstjcOv/X3QbeG3QqWOtNco+XgM7Q== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/middleware-user-agent@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.502.0.tgz#dd740f150d6f3110cf5b08fedf361d202f899c93" - integrity sha512-TxbBZbRiXPH0AUxegqiNd9aM9zNSbfjtBs5MEfcBsweeT/B2O7K1EjP9+CkB8Xmk/5FLKhAKLr19b1TNoE27rw== +"@aws-sdk/middleware-user-agent@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.511.0.tgz#e954070a928f16f93e9cccb84e6174554fdf94ac" + integrity sha512-eLs+CxP2QCXh3tCGYCdAml3oyWj8MSIwKbH+8rKw0k/5vmY1YJDBy526whOxx61ivhz2e0muuijN4X5EZZ2Pnw== dependencies: - "@aws-sdk/types" "3.502.0" - "@aws-sdk/util-endpoints" "3.502.0" + "@aws-sdk/types" "3.511.0" + "@aws-sdk/util-endpoints" "3.511.0" "@smithy/protocol-http" "^3.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/region-config-resolver@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.502.0.tgz#c18a04060879eb03c47c05b05fc296119ee073ba" - integrity sha512-mxmsX2AGgnSM+Sah7mcQCIneOsJQNiLX0COwEttuf8eO+6cLMAZvVudH3BnWTfea4/A9nuri9DLCqBvEmPrilg== +"@aws-sdk/region-config-resolver@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.511.0.tgz#abe0334f975414119a38eba0f85d1239a074b510" + integrity sha512-RzBLSNaRd4iEkQyEGfiSNvSnWU/x23rsiFgA9tqYFA0Vqx7YmzSWC8QBUxpwybB8HkbbL9wNVKQqTbhI3mYneQ== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/node-config-provider" "^2.2.1" "@smithy/types" "^2.9.1" "@smithy/util-config-provider" "^2.2.1" "@smithy/util-middleware" "^2.1.1" tslib "^2.5.0" -"@aws-sdk/signature-v4-multi-region@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.502.0.tgz#2d3fab86051eb98a4e4216e0f2f3d957a854b42c" - integrity sha512-NpOXtUXH0ZAgnyI3Y3s2fPrgwbsWoNMwdoXdFZvH0eDzzX80tim7Yuy6dzVA5zrxSzOYs1xjcOhM+4CmM0QZiw== +"@aws-sdk/signature-v4-multi-region@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.511.0.tgz#6a33b9f540983c8c32ea3b0de4827f4a29da19f6" + integrity sha512-lwbU3LX5TpYu1DHBMH2Wz+2MWGccn5G3psu1Y9WTPc+1bubVQHWf8UD2lzON5L2QirT9tQheQjTke1u5JC7FTQ== dependencies: - "@aws-sdk/middleware-sdk-s3" "3.502.0" - "@aws-sdk/types" "3.502.0" + "@aws-sdk/middleware-sdk-s3" "3.511.0" + "@aws-sdk/types" "3.511.0" "@smithy/protocol-http" "^3.1.1" "@smithy/signature-v4" "^2.1.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/token-providers@3.507.0": - version "3.507.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.507.0.tgz#7456cec822a7f59a4b58a2eda1a0ff963c4c3c6b" - integrity sha512-ehOINGjoGJc6Puzon7ev4bXckkaZx18WNgMTNttYJhj3vTpj5LPSQbI/5SS927bEbpGMFz1+hJ6Ra5WGfbTcEQ== +"@aws-sdk/token-providers@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.513.0.tgz#e096873c841373a3754cfb21c2483f11de48c9f8" + integrity sha512-S27iFzj3dVRw1q+xLtqTGZOfYG95OwvTN7crvS2daqSYfcWN+dhEPzQJdDvGaAnAI45bWm8rppH/EYzrlxeZoA== dependencies: - "@aws-sdk/client-sso-oidc" "3.507.0" - "@aws-sdk/types" "3.502.0" + "@aws-sdk/client-sso-oidc" "3.513.0" + "@aws-sdk/types" "3.511.0" "@smithy/property-provider" "^2.1.1" "@smithy/shared-ini-file-loader" "^2.3.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" -"@aws-sdk/types@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.502.0.tgz#c23dda4df7fdbe32642d4f5ab23516f455fb6aba" - integrity sha512-M0DSPYe/gXhwD2QHgoukaZv5oDxhW3FfvYIrJptyqUq3OnPJBcDbihHjrE0PBtfh/9kgMZT60/fQ2NVFANfa2g== +"@aws-sdk/types@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.511.0.tgz#b873bcd8d0db1265234a5a8b920a3c43a6ca28ff" + integrity sha512-P03ufufxmkvd7nO46oOeEqYIMPJ8qMCKxAsfJk1JBVPQ1XctVntbail4/UFnrnzij8DTl4Mk/D62uGo7+RolXA== dependencies: "@smithy/types" "^2.9.1" tslib "^2.5.0" @@ -705,12 +683,12 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-endpoints@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.502.0.tgz#aee818c0c53dfedfd49599fc260cd880faea5e82" - integrity sha512-6LKFlJPp2J24r1Kpfoz5ESQn+1v5fEjDB3mtUKRdpwarhm3syu7HbKlHCF3KbcCOyahobvLvhoedT78rJFEeeg== +"@aws-sdk/util-endpoints@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.511.0.tgz#f2f7f0ca1c7a1caaede5345e700eeed41316be00" + integrity sha512-J/5hsscJkg2pAOdLx1YKlyMCk5lFRxRxEtup9xipzOxVBlqOIE72Tuu31fbxSlF8XzO/AuCJcZL4m1v098K9oA== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/types" "^2.9.1" "@smithy/util-endpoints" "^1.1.1" tslib "^2.5.0" @@ -722,22 +700,22 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/util-user-agent-browser@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.502.0.tgz#87b42abff6944052c78a84981637ac21859dd016" - integrity sha512-v8gKyCs2obXoIkLETAeEQ3AM+QmhHhst9xbM1cJtKUGsRlVIak/XyyD+kVE6kmMm1cjfudHpHKABWk9apQcIZQ== +"@aws-sdk/util-user-agent-browser@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.511.0.tgz#986c0f76141f6180fad6f9a0a4a8566d81c02e12" + integrity sha512-5LuESdwtIcA10aHcX7pde7aCIijcyTPBXFuXmFlDTgm/naAayQxelQDpvgbzuzGLgePf8eTyyhDKhzwPZ2EqiQ== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/types" "^2.9.1" bowser "^2.11.0" tslib "^2.5.0" -"@aws-sdk/util-user-agent-node@3.502.0": - version "3.502.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.502.0.tgz#04ac4d0371d4f243f12ddc23b42ca8ceb27dfad9" - integrity sha512-9RjxpkGZKbTdl96tIJvAo+vZoz4P/cQh36SBUt9xfRfW0BtsaLyvSrvlR5wyUYhvRcC12Axqh/8JtnAPq//+Vw== +"@aws-sdk/util-user-agent-node@3.511.0": + version "3.511.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.511.0.tgz#2cb4f56050e2f173870d6bcccb0f12f68dbf73ce" + integrity sha512-UopdlRvYY5mxlS4wwFv+QAWL6/T302wmoQj7i+RY+c/D3Ej3PKBb/mW3r2wEOgZLJmPpeeM1SYMk+rVmsW1rqw== dependencies: - "@aws-sdk/types" "3.502.0" + "@aws-sdk/types" "3.511.0" "@smithy/node-config-provider" "^2.2.1" "@smithy/types" "^2.9.1" tslib "^2.5.0" @@ -1452,10 +1430,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== -"@faker-js/faker@^8.4.0": - version "8.4.0" - resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-8.4.0.tgz#dc09924ee5fa6438eaaa49d0a8820c64d2f8518f" - integrity sha512-htW87352wzUCdX1jyUQocUcmAaFqcR/w082EC8iP/gtkF0K+aKcBp0hR5Arb7dzR8tQ1TrhE9DNa5EbJELm84w== +"@faker-js/faker@^8.4.1": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-8.4.1.tgz#5d5e8aee8fce48f5e189bf730ebd1f758f491451" + integrity sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg== "@graphql-tools/merge@9.0.0": version "9.0.0" @@ -1898,6 +1876,11 @@ resolved "https://registry.yarnpkg.com/@lukeed/csprng/-/csprng-1.0.1.tgz#625e93a0edb2c830e3c52ce2d67b9d53377c6a66" integrity sha512-uSvJdwQU5nK+Vdf6zxcWAY2A8r7uqe+gePwLWzJ+fsQehq18pc0I2hJKwypZ2aLM90+Er9u1xn4iLJPZ+xlL4g== +"@microsoft/tsdoc@^0.14.2": + version "0.14.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" + integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== + "@mongodb-js/saslprep@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz#022fa36620a7287d17acd05c4aae1e5f390d250d" @@ -1905,22 +1888,22 @@ dependencies: sparse-bitfield "^3.0.3" -"@nestjs/axios@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@nestjs/axios/-/axios-3.0.1.tgz#b006f81dd54a49def92cfaf9a8970434567e75ce" - integrity sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ== +"@nestjs/axios@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@nestjs/axios/-/axios-3.0.2.tgz#0078c101a29fb46f5c566d68a4315fddabc083ed" + integrity sha512-Z6GuOUdNQjP7FX+OuV2Ybyamse+/e0BFdTWBX5JxpBDKA+YkdLynDgG6HTF04zy6e9zPa19UX0WA2VDoehwhXQ== -"@nestjs/cli@^10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-10.3.1.tgz#f13af238fd17ce22f5c4a3439828248938aca8e8" - integrity sha512-xzabUxTdZ7IcNXLzAq1YZgGJkAt6JNeeLVORj8MfMV0io2edgAn5ASn4tIOHvnsmKh6yX1kBaVEhTHiuENlplA== +"@nestjs/cli@^10.3.2": + version "10.3.2" + resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-10.3.2.tgz#42d2764ead6633e278c55d42de871b4cc1db002b" + integrity sha512-aWmD1GLluWrbuC4a1Iz/XBk5p74Uj6nIVZj6Ov03JbTfgtWqGFLtXuMetvzMiHxfrHehx/myt2iKAPRhKdZvTg== dependencies: "@angular-devkit/core" "17.1.2" "@angular-devkit/schematics" "17.1.2" "@angular-devkit/schematics-cli" "17.1.2" "@nestjs/schematics" "^10.0.1" chalk "4.1.2" - chokidar "3.5.3" + chokidar "3.6.0" cli-table3 "0.6.3" commander "4.1.1" fork-ts-checker-webpack-plugin "9.0.2" @@ -1938,29 +1921,29 @@ webpack "5.90.1" webpack-node-externals "3.0.0" -"@nestjs/common@^10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.3.1.tgz#7aa5a0ffbd0123533adc1cfee8fd184b74bc2fc1" - integrity sha512-YuxeIlVemVQCuXMkNbBpNlmwZgp/Cu6dwCOjki63mhyYHEFX48GNNA4zZn5MFRjF4h7VSceABsScROuzsxs9LA== +"@nestjs/common@^10.3.3": + version "10.3.3" + resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.3.3.tgz#ba20f756dbed62f5fe29737c42384ad41156c9e9" + integrity sha512-LAkTe8/CF0uNWM0ecuDwUNTHCi1lVSITmmR4FQ6Ftz1E7ujQCnJ5pMRzd8JRN14vdBkxZZ8VbVF0BDUKoKNxMQ== dependencies: uid "2.0.2" iterare "1.2.1" tslib "2.6.2" -"@nestjs/config@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-3.1.1.tgz#51e23ed84debd08afb86acf7b92bc4bf341797da" - integrity sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ== +"@nestjs/config@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-3.2.0.tgz#4ca70f88b0636f86741ba192dd51dd2f01eaa7c1" + integrity sha512-BpYRn57shg7CH35KGT6h+hT7ZucB6Qn2B3NBNdvhD4ApU8huS5pX/Wc2e/aO5trIha606Bz2a9t9/vbiuTBTww== dependencies: - dotenv "16.3.1" + dotenv "16.4.1" dotenv-expand "10.0.0" lodash "4.17.21" - uuid "9.0.0" + uuid "9.0.1" -"@nestjs/core@^10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.3.1.tgz#96f34ad7e6efab080ac7c3f07d5454c9705eccc4" - integrity sha512-mh6FwTKh2R3CmLRuB50BF5q/lzc+Mz+7qAlEvpgCiTSIfSXzbQ47vWpfgLirwkL3SlCvtFS8onxOeI69RpxvXA== +"@nestjs/core@^10.3.3": + version "10.3.3" + resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.3.3.tgz#f957068ddda59252b7c36fcdb07a0fb323b52bcf" + integrity sha512-kxJWggQAPX3RuZx9JVec69eSLaYLNIox2emkZJpfBJ5Qq7cAq7edQIt1r4LGjTKq6kFubNTPsqhWf5y7yFRBPw== dependencies: uid "2.0.2" "@nuxtjs/opencollective" "0.3.2" @@ -2002,25 +1985,25 @@ resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.2.tgz#c8a090a8d22145b85ed977414c158534210f2e4f" integrity sha512-V0izw6tWs6fTp9+KiiPUbGHWALy563Frn8X6Bm87ANLRuE46iuBMD5acKBDP5lKL/75QFvrzSJT7HkCbB0jTpg== -"@nestjs/mapped-types@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.4.tgz#97280b06bf85d34ea9bad1e847e5e3cbaca8f04f" - integrity sha512-xl+gUSp0B+ln1VSNoUftlglk8dfpUes3DHGxKZ5knuBxS5g2H/8p9/DSBOYWUfO5f4u9s6ffBPZ71WO+tbe5SA== +"@nestjs/mapped-types@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz#485d6b44e19779c98d04e52bd1d2bcc7001df0ea" + integrity sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg== -"@nestjs/mongoose@^10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@nestjs/mongoose/-/mongoose-10.0.2.tgz#33018e22f0ba03a37ffb30d8b3c6b7cf904894d8" - integrity sha512-ITHh075DynjPIaKeJh6WkarS21WXYslu4nrLkNPbWaCP6JfxVAOftaA2X5tPSiiE/gNJWgs+QFWsfCFZUUenow== +"@nestjs/mongoose@^10.0.4": + version "10.0.4" + resolved "https://registry.yarnpkg.com/@nestjs/mongoose/-/mongoose-10.0.4.tgz#7f993f7da47189d8dc918113996bba5d5ad95a48" + integrity sha512-OXcguhrv+ahXmpPD3FJgnCLU3eUSBcbE7OwClJL+3inpPAyvMbhLrYvk3Zi7/34aMCzBOILdCBh95AQ7ghd1sg== "@nestjs/passport@^10.0.3": version "10.0.3" resolved "https://registry.yarnpkg.com/@nestjs/passport/-/passport-10.0.3.tgz#26ec5b2167d364e04962c115fcef80d10e185367" integrity sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ== -"@nestjs/platform-express@^10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.3.1.tgz#f72f337ddd96895e56284b13971bdbd3479e24b3" - integrity sha512-Rj21quI5h4Lry7q9an+nO4ADQiQUy9A6XK74o5aTUHo3Ysm25ujqh2NgU4XbT3M2oXU9qzhE59OfhkQ7ZUvTAg== +"@nestjs/platform-express@^10.3.3": + version "10.3.3" + resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.3.3.tgz#c1484d30d1e7666c4c8d0d7cde31cfc0b9d166d7" + integrity sha512-GGKSEU48Os7nYFIsUM0nutuFUGn5AbeP8gzFBiBCAtiuJWrXZXpZ58pMBYxAbMf7IrcOZFInHEukjHGAQU0OZw== dependencies: body-parser "1.20.2" cors "2.8.5" @@ -2028,12 +2011,12 @@ multer "1.4.4-lts.1" tslib "2.6.2" -"@nestjs/schedule@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.0.0.tgz#522fa0c79a2b44a66aab16a46bdf4c11ae73f3c3" - integrity sha512-zz4h54m/F/1qyQKvMJCRphmuwGqJltDAkFxUXCVqJBXEs5kbPt93Pza3heCQOcMH22MZNhGlc9DmDMLXVHmgVQ== +"@nestjs/schedule@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.0.1.tgz#beb69f974e7adc96fd799f555ba0121c10d2d61b" + integrity sha512-cz2FNjsuoma+aGsG0cMmG6Dqg/BezbBWet1UTHtAuu6d2mXNTVcmoEQM2DIVG5Lfwb2hfSE2yZt8Moww+7y+mA== dependencies: - cron "3.1.3" + cron "3.1.6" uuid "9.0.1" "@nestjs/schematics@^10.0.1": @@ -2047,49 +2030,48 @@ jsonc-parser "3.2.0" pluralize "8.0.0" -"@nestjs/schematics@^10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-10.1.0.tgz#bf9be846bafad0f45f0ea5ed80aaaf971bb90873" - integrity sha512-HQWvD3F7O0Sv3qHS2jineWxPLmBTLlyjT6VdSw2EAIXulitmV+ErxB3TCVQQORlNkl5p5cwRYWyBaOblDbNFIQ== +"@nestjs/schematics@^10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-10.1.1.tgz#a67fb178a7ad6025ccc3314910b077ac454fcdf3" + integrity sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig== dependencies: - "@angular-devkit/core" "17.0.9" - "@angular-devkit/schematics" "17.0.9" + "@angular-devkit/core" "17.1.2" + "@angular-devkit/schematics" "17.1.2" comment-json "4.2.3" - jsonc-parser "3.2.0" + jsonc-parser "3.2.1" pluralize "8.0.0" -"@nestjs/swagger@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@nestjs/swagger/-/swagger-7.2.0.tgz#a449ab0a2319eca8e695cf3892f4e63bbd8a916d" - integrity sha512-W7WPq561/79w27ZEgViXS7c5hqPwT7QXhsLsSeu2jeBROUhMM825QKDFKbMmtb643IW5dznJ4PjherlZZgtMvg== +"@nestjs/swagger@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@nestjs/swagger/-/swagger-7.3.0.tgz#0b5e397cc5a592422df9afb24c79af928fea5954" + integrity sha512-zLkfKZ+ioYsIZ3dfv7Bj8YHnZMNAGWFUmx2ZDuLp/fBE4P8BSjB7hldzDueFXsmwaPL90v7lgyd82P+s7KME1Q== dependencies: - "@nestjs/mapped-types" "2.0.4" + "@microsoft/tsdoc" "^0.14.2" + "@nestjs/mapped-types" "2.0.5" js-yaml "4.1.0" lodash "4.17.21" path-to-regexp "3.2.0" - swagger-ui-dist "5.11.0" + swagger-ui-dist "5.11.2" -"@nestjs/terminus@^10.2.1": - version "10.2.1" - resolved "https://registry.yarnpkg.com/@nestjs/terminus/-/terminus-10.2.1.tgz#1bb1cd5532f34c9d80b348412dbe681ceaeb3ad4" - integrity sha512-23abPhotIP4+hrCZ8YkLEOmZ3m7eUYh1QOwdyrNkU9eMz/nc5LpVzy7jFbsNUuvlnT4MPV/7KXfyQTruQkTouw== +"@nestjs/terminus@^10.2.2": + version "10.2.2" + resolved "https://registry.yarnpkg.com/@nestjs/terminus/-/terminus-10.2.2.tgz#3044d1c4d73331c2a074e286fe1fcb5c602a2900" + integrity sha512-tZdTSqgHyxekN8PJmJJ1ptZG97q/1nBIBwLdMcmB7Dsz4XDTQvYuhs20F1qkEgFuQwarNkb/2AF5Qib31g2bmA== dependencies: boxen "5.1.2" check-disk-space "3.4.0" -"@nestjs/testing@^10.3.1": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@nestjs/testing/-/testing-10.3.1.tgz#ea28a7d29122dd3a2df1542842e741a52dd7c474" - integrity sha512-74aSAugWT31jSPnStyRWDXgjHXWO3GYaUfAZ2T7Dml88UGkGy95iwaWgYy7aYM8/xVFKcDYkfL5FAYqZYce/yg== +"@nestjs/testing@^10.3.3": + version "10.3.3" + resolved "https://registry.yarnpkg.com/@nestjs/testing/-/testing-10.3.3.tgz#09924fca887dc5c9020feff1414da69f5bce30ac" + integrity sha512-kX20GfjAImL5grd/i69uD/x7sc00BaqGcP2dRG3ilqshQUuy5DOmspLCr3a2C8xmVU7kzK4spT0oTxhe6WcCAA== dependencies: tslib "2.6.2" -"@nestjs/throttler@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@nestjs/throttler/-/throttler-5.1.1.tgz#cefdf1bc28c6692769412692db78753317f9e59b" - integrity sha512-0fJAGroqpQLnQlERslx2fG264YCXU35nMfiFhykY6/chgc56/W0QPM6BEEf9Q/Uca9lXh5IyjE0fqFToksbP/A== - dependencies: - md5 "^2.2.1" +"@nestjs/throttler@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@nestjs/throttler/-/throttler-5.1.2.tgz#dc65634153c8b887329b1cc6061db2e556517dcb" + integrity sha512-60MqhSLYUqWOgc38P6C6f76JIpf6mVjly7gpuPBCKtVd0p5e8Fq855j7bJuO4/v25vgaOo1OdVs0U1qtgYioGw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -2133,44 +2115,44 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@sentry-internal/tracing@7.99.0": - version "7.99.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.99.0.tgz#ad13f8343444ecf7323a4220d4e57a55166565d7" - integrity sha512-z3JQhHjoM1KdM20qrHwRClKJrNLr2CcKtCluq7xevLtXHJWNAQQbafnWD+Aoj85EWXBzKt9yJMv2ltcXJ+at+w== +"@sentry-internal/tracing@7.101.0": + version "7.101.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.101.0.tgz#9a92ee722d071449a61c061867aa43a5beefcfb6" + integrity sha512-rp9oOLQs6vMuzvAnAHRRCNu5Z0o/ZVRI3WPYedxpdMWKD1Z3G9o+0joP+ZIUqHsamWWYiIgPqXgL9AK6AWjFRg== dependencies: - "@sentry/core" "7.99.0" - "@sentry/types" "7.99.0" - "@sentry/utils" "7.99.0" + "@sentry/core" "7.101.0" + "@sentry/types" "7.101.0" + "@sentry/utils" "7.101.0" -"@sentry/core@7.99.0": - version "7.99.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.99.0.tgz#6881aae5ac1436637b3d88e0b12df4ab56016c5f" - integrity sha512-vOAtzcAXEUtS/oW7wi3wMkZ3hsb5Ch96gKyrrj/mXdOp2zrcwdNV6N9/pawq2E9P/7Pw8AXw4CeDZztZrjQLuA== +"@sentry/core@7.101.0": + version "7.101.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.101.0.tgz#7ddae48771bad6d3170df0d9807f86c39824dd0a" + integrity sha512-dRNrNV5OLGARkOGgxJsVDhA98Pev5G1LVJcud5E83cRg49BCUx2riqEtDP6iIS1nvem6cApkSnLC1kvl/T5/Cw== dependencies: - "@sentry/types" "7.99.0" - "@sentry/utils" "7.99.0" + "@sentry/types" "7.101.0" + "@sentry/utils" "7.101.0" -"@sentry/node@^7.99.0": - version "7.99.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.99.0.tgz#c70e174527bbd86294dd446dbc1ae9036fb729f2" - integrity sha512-34wYtLddnPcQ8qvKq62AfxowaMFw+GMUZGv7fIs9FxeBqqqn6Ckl0gFCTADudIIBQ3rSbmN7sHJIXdyiQv+pcw== +"@sentry/node@^7.101.0": + version "7.101.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.101.0.tgz#acafd4efc81035bb3ffe73ef92f348099c7c5df1" + integrity sha512-4z01VAFjRYk7XcajbWPJlhkPN6PBG4nVX8n1dl+OH2OeqTxFxcnmY5zR5v+AtEbNJgg5PMwy8mnnGZRG/wLZgA== dependencies: - "@sentry-internal/tracing" "7.99.0" - "@sentry/core" "7.99.0" - "@sentry/types" "7.99.0" - "@sentry/utils" "7.99.0" + "@sentry-internal/tracing" "7.101.0" + "@sentry/core" "7.101.0" + "@sentry/types" "7.101.0" + "@sentry/utils" "7.101.0" -"@sentry/types@7.99.0": - version "7.99.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.99.0.tgz#bba7a514abab445026ee42f40f92f81275a6deba" - integrity sha512-94qwOw4w40sAs5mCmzcGyj8ZUu/KhnWnuMZARRq96k+SjRW/tHFAOlIdnFSrt3BLPvSOK7R3bVAskZQ0N4FTmA== +"@sentry/types@7.101.0": + version "7.101.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.101.0.tgz#0174a32d6c12def73f438dc2a10bd52cc0ba0c81" + integrity sha512-YC+ltO/AlbEyJHjCUYQ4is1HcDT2zSMuLkIAcyQmK7fUdlGT4iR5sfENriY9ZopYHgjPdJKfhI8ohScam7zp/A== -"@sentry/utils@7.99.0": - version "7.99.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.99.0.tgz#ef96c3b59e23c79f3ef500db508234a48fa1cfbe" - integrity sha512-cYZy5WNTkWs5GgggGnjfGqC44CWir0pAv4GVVSx0fsup4D4pMKBJPrtub15f9uC+QkUf3vVkqwpBqeFxtmJQTQ== +"@sentry/utils@7.101.0": + version "7.101.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.101.0.tgz#0eadb9709c9b6fbc03d509acf7fe6a00ab4e6220" + integrity sha512-px1NUkCLsD9UKLE4W4DghpyzmAVHgYhskrjRt30ubyUKqlggtHkOXRvS8MjuWowR/i0wF0GuTCbU9StBd7JMrw== dependencies: - "@sentry/types" "7.99.0" + "@sentry/types" "7.101.0" "@sideway/address@^4.1.5": version "4.1.5" @@ -2247,10 +2229,10 @@ "@smithy/util-middleware" "^2.1.1" tslib "^2.5.0" -"@smithy/core@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@smithy/core/-/core-1.3.1.tgz#ecedc564e68453b02c20db9e8435d59005c066d8" - integrity sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q== +"@smithy/core@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-1.3.2.tgz#e11f3860b69ec0bdbd31e6afaa54963c02dc7f8e" + integrity sha512-tYDmTp0f2TZVE18jAOH1PnmkngLQ+dOGUlMd1u67s87ieueNeyqhja6z/Z4MxhybEiXKOWFOmGjfTZWFxljwJw== dependencies: "@smithy/middleware-endpoint" "^2.4.1" "@smithy/middleware-retry" "^2.1.1" @@ -2593,10 +2575,10 @@ bowser "^2.11.0" tslib "^2.5.0" -"@smithy/util-defaults-mode-node@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.1.tgz#0910ee00aac3e8a08aac3e6ae8794e52f3efef02" - integrity sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA== +"@smithy/util-defaults-mode-node@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.2.0.tgz#72fd6f945c265f1ef9be647fe829d55df5101390" + integrity sha512-iFJp/N4EtkanFpBUtSrrIbtOIBf69KNuve03ic1afhJ9/korDxdM0c6cCH4Ehj/smI9pDCfVv+bqT3xZjF2WaA== dependencies: "@smithy/config-resolver" "^2.1.1" "@smithy/credential-provider-imds" "^2.2.1" @@ -2959,10 +2941,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.3.tgz#463fc47f13ec0688a33aec75d078a0541a447199" integrity sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ== -"@types/node@^20.11.16": - version "20.11.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708" - integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ== +"@types/node@^20.11.17": + version "20.11.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.17.tgz#cdd642d0e62ef3a861f88ddbc2b61e32578a9292" + integrity sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw== dependencies: undici-types "~5.26.4" @@ -3086,16 +3068,16 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" - integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== +"@typescript-eslint/eslint-plugin@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz#407daffe09d964d57aceaf3ac51846359fbe61b0" + integrity sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/type-utils" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/scope-manager" "7.0.1" + "@typescript-eslint/type-utils" "7.0.1" + "@typescript-eslint/utils" "7.0.1" + "@typescript-eslint/visitor-keys" "7.0.1" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -3103,47 +3085,47 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@^6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== +"@typescript-eslint/parser@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.0.1.tgz#e9c61d9a5e32242477d92756d36086dc40322eed" + integrity sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ== dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/scope-manager" "7.0.1" + "@typescript-eslint/types" "7.0.1" + "@typescript-eslint/typescript-estree" "7.0.1" + "@typescript-eslint/visitor-keys" "7.0.1" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== +"@typescript-eslint/scope-manager@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz#611ec8e78c70439b152a805e1b10aaac36de7c00" + integrity sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w== dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/types" "7.0.1" + "@typescript-eslint/visitor-keys" "7.0.1" -"@typescript-eslint/type-utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" - integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== +"@typescript-eslint/type-utils@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz#0fba92c1f81cad561d7b3adc812aa1cc0e35cdae" + integrity sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw== dependencies: - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/typescript-estree" "7.0.1" + "@typescript-eslint/utils" "7.0.1" debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== +"@typescript-eslint/types@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.0.1.tgz#dcfabce192db5b8bf77ea3c82cfaabe6e6a3c901" + integrity sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg== -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== +"@typescript-eslint/typescript-estree@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz#1d52ac03da541693fa5bcdc13ad655def5046faf" + integrity sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig== dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/types" "7.0.1" + "@typescript-eslint/visitor-keys" "7.0.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -3151,25 +3133,25 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" - integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== +"@typescript-eslint/utils@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.0.1.tgz#b8ceac0ba5fef362b4a03a33c0e1fedeea3734ed" + integrity sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/scope-manager" "7.0.1" + "@typescript-eslint/types" "7.0.1" + "@typescript-eslint/typescript-estree" "7.0.1" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== +"@typescript-eslint/visitor-keys@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz#864680ac5a8010ec4814f8a818e57595f79f464e" + integrity sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw== dependencies: - "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/types" "7.0.1" eslint-visitor-keys "^3.4.1" "@ucast/core@^1.0.0", "@ucast/core@^1.4.1", "@ucast/core@^1.6.1": @@ -3967,11 +3949,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== - check-disk-space@3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/check-disk-space/-/check-disk-space-3.4.0.tgz#eb8e69eee7a378fd12e35281b8123a8b4c4a8ff7" @@ -3992,6 +3969,21 @@ chokidar@3.5.3, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -4331,10 +4323,10 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cron@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.3.tgz#4eac8f6691ce7e24c8e89b5317b8097d6f2d0053" - integrity sha512-KVxeKTKYj2eNzN4ElnT6nRSbjbfhyxR92O/Jdp6SH3pc05CDJws59jBrZWEMQlxevCiE6QUTrXy+Im3vC3oD3A== +cron@3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.6.tgz#e7e1798a468e017c8d31459ecd7c2d088f97346c" + integrity sha512-cvFiQCeVzsA+QPM6fhjBtlKGij7tLLISnTSvFxVdnFGLdz+ZdXN37kNe0i2gefmdD17XuZA6n2uPVwzl4FxW/w== dependencies: "@types/luxon" "~3.3.0" luxon "~3.4.0" @@ -4355,11 +4347,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypt@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== - crypto-js@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" @@ -4631,10 +4618,15 @@ dotenv-expand@10.0.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== -dotenv@16.3.1: - version "16.3.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" - integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== +dotenv@16.4.1: + version "16.4.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.1.tgz#1d9931f1d3e5d2959350d1250efab299561f7f11" + integrity sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ== + +drange@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/drange/-/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" + integrity sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA== dset@^3.1.2: version "3.1.3" @@ -5578,10 +5570,10 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -google-auth-library@^9.6.2: - version "9.6.2" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.6.2.tgz#c615b9186ee1871eab4703a9d07206c8c73d46a7" - integrity sha512-8G5i+uELrRE244PGnTc9UxiWZ2FMWD5jiIe9P2XSxCvXv/0ip/phjeHSE4bhJnLBdJb+Bu/Gj9Lr33TmDnbAiw== +google-auth-library@^9.6.3: + version "9.6.3" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.6.3.tgz#add8935bc5b842a8e80f84fef2b5ed9febb41d48" + integrity sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ== dependencies: base64-js "^1.3.0" ecdsa-sig-formatter "^1.0.11" @@ -5729,10 +5721,10 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -husky@^9.0.10: - version "9.0.10" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.10.tgz#ddca8908deb5f244e9286865ebc80b54387672c2" - integrity sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA== +husky@^9.0.11: + version "9.0.11" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" + integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" @@ -5911,11 +5903,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -6690,6 +6677,11 @@ jsonc-parser@3.2.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== +jsonc-parser@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -6957,15 +6949,6 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -md5@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -7127,10 +7110,10 @@ mongodb@6.3.0: bson "^6.2.0" mongodb-connection-string-url "^3.0.0" -mongoose@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.1.1.tgz#2ea2dcdcf4943196f585b3915f63001e79214e1b" - integrity sha512-DbLb0NsiEXmaqLOpEz+AtAsgwhRw6f25gwa1dF5R7jj6lS1D8X6uTdhBSC8GDVtOwe5Tfw2EL7nTn6hiJT3Bgg== +mongoose@^8.1.2: + version "8.1.2" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.1.2.tgz#f8a91da3e8c4b7489d4cbf35c20cd6908bbfcbce" + integrity sha512-5KMq7k6KmFCIB8/YMKMFsWdsdNkBwuARDRHDRpp5GKC78eT0LwHIaMEKo6gDUg3zBuMoy9OdcM/6f4dkW06C/A== dependencies: bson "^6.2.0" kareem "2.5.1" @@ -7290,10 +7273,10 @@ object-assign@^4, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-hash@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" - integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== object-inspect@^1.13.1: version "1.13.1" @@ -7679,6 +7662,14 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +randexp@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.5.3.tgz#f31c2de3148b30bdeb84b7c3f59b0ebb9fec3738" + integrity sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w== + dependencies: + drange "^1.0.2" + ret "^0.2.0" + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -7837,6 +7828,11 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +ret@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" + integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -8348,10 +8344,10 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -swagger-ui-dist@5.11.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.11.0.tgz#9bcfd75278b1fa9c36fe52f206f8fc611470547c" - integrity sha512-j0PIATqQSEFGOLmiJOJZj1X1Jt6bFIur3JpY7+ghliUnfZs0fpWDdHEkn9q7QUlBtKbkn6TepvSxTqnE8l3s0A== +swagger-ui-dist@5.11.2: + version "5.11.2" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.11.2.tgz#b423e820928df703586ff58f80b09ffcf2434e08" + integrity sha512-jQG0cRgJNMZ7aCoiFofnoojeSaa/+KgWaDlfgs8QN+BXoGMpxeMVY5OEnjq4OlNvF3yjftO8c9GRAgcHlO+u7A== symbol-observable@4.0.0: version "4.0.0" @@ -8464,6 +8460,11 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== +triple-beam@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" + integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== + "true-myth@^4.1.0": version "4.1.1" resolved "https://registry.yarnpkg.com/true-myth/-/true-myth-4.1.1.tgz#ff4ac9d5130276e34aa338757e2416ec19248ba2" @@ -8763,11 +8764,6 @@ utils-merge@1.0.1, utils-merge@^1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== - uuid@9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" @@ -8941,17 +8937,17 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -winston-daily-rotate-file@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz#f60a643af87f8867f23170d8cd87dbe3603a625f" - integrity sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA== +winston-daily-rotate-file@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-5.0.0.tgz#8cd94800025490e47c00ec892b655a5821f4266d" + integrity sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw== dependencies: file-stream-rotator "^0.6.1" - object-hash "^2.0.1" - triple-beam "^1.3.0" - winston-transport "^4.4.0" + object-hash "^3.0.0" + triple-beam "^1.4.1" + winston-transport "^4.7.0" -winston-transport@^4.4.0, winston-transport@^4.5.0: +winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== @@ -8960,6 +8956,15 @@ winston-transport@^4.4.0, winston-transport@^4.5.0: readable-stream "^3.6.0" triple-beam "^1.3.0" +winston-transport@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0" + integrity sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg== + dependencies: + logform "^2.3.2" + readable-stream "^3.6.0" + triple-beam "^1.3.0" + winston@^3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/winston/-/winston-3.11.0.tgz#2d50b0a695a2758bb1c95279f0a88e858163ed91"