diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 5a2a79dc..ce7ce8cc 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -24,7 +24,7 @@ module.exports = { 'node_modules', 'coverage', 'src/database/migrations', - 'src/exported/api/@types/i18n.d.ts', + 'src/types/i18n.d.ts', ], settings: { 'import/resolver': { diff --git a/jest.config.ts b/jest.config.ts index bbb1ce47..40002f56 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -15,18 +15,19 @@ const config: JestConfigWithTsJest = { detectOpenHandles: true, maxConcurrency: 1, moduleNameMapper: { - '@env': '/src/env.ts', - '@mikro-orm.config': '/src/mikro-orm.config.ts', - '@app.module': '/src/app.module.ts', - '@main': '/src/main.ts', + '~/env': '/src/env.ts', + '~/mikro-orm.config': '/src/mikro-orm.config.ts', + '~/app.module': '/src/app.module.ts', + '~/main': '/src/main.ts', '^src/(.*)$': '/src/$1', - '^@database/(.*)$': '/src/database/$1', - '^@exported/(.*)$': '/src/exported/$1', - '^@i18n': '/src/i18n/index.ts', - '^@modules/(.*)$': '/src/modules/$1', - '^@templates/(.*)$': '/src/templates/$1', - '^@types/(.*)$': '/src/types/$1', - '^@utils/(.*)$': '/src/utils/$1', + '^~/database/(.*)$': '/src/database/$1', + '^~/i18n': '/src/i18n/index.ts', + '^~/modules/(.*)$': '/src/modules/$1', + '^~/templates/(.*)$': '/src/templates/$1', + '^~/types/(.*)$': '/src/types/$1', + '^~/utils/(.*)$': '/src/utils/$1', + '^~/constants/(.*)$': '/src/types/exported/constants/$1', + '^~/utils': '/src/utils/index.ts', }, modulePathIgnorePatterns: ['/dist', '/node_modules'], preset: 'ts-jest', diff --git a/package.json b/package.json index 493cc170..51279c32 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "prepare": "husky install" }, "dependencies": { - "@ae_utbm/typings": "file:src/exported", "@mikro-orm/cli": "^5.9.1", "@mikro-orm/core": "^5.9.1", "@mikro-orm/migrations": "^5.9.1", diff --git a/src/app.module.ts b/src/app.module.ts index ba30e587..b03ce46d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,15 +6,15 @@ import { APP_INTERCEPTOR } from '@nestjs/core'; import { ScheduleModule } from '@nestjs/schedule'; import { AcceptLanguageResolver, I18nModule } from 'nestjs-i18n'; -import { AuthModule } from '@modules/auth/auth.module'; -import { EmailsModule } from '@modules/emails/emails.module'; -import { FilesModule } from '@modules/files/files.module'; -import { LoggingInterceptor } from '@modules/logs/interceptor/logging.interceptor'; -import { LogsModule } from '@modules/logs/logs.module'; -import { PermissionsModule } from '@modules/permissions/permissions.module'; -import { PromotionsModule } from '@modules/promotions/promotions.module'; -import { RolesModule } from '@modules/roles/roles.module'; -import { UsersModule } from '@modules/users/users.module'; +import { AuthModule } from '~/modules/auth/auth.module'; +import { EmailsModule } from '~/modules/emails/emails.module'; +import { FilesModule } from '~/modules/files/files.module'; +import { LoggingInterceptor } from '~/modules/logs/interceptor/logging.interceptor'; +import { LogsModule } from '~/modules/logs/logs.module'; +import { PermissionsModule } from '~/modules/permissions/permissions.module'; +import { PromotionsModule } from '~/modules/promotions/promotions.module'; +import { RolesModule } from '~/modules/roles/roles.module'; +import { UsersModule } from '~/modules/users/users.module'; @Module({ imports: [ @@ -28,7 +28,7 @@ import { UsersModule } from '@modules/users/users.module'; watch: true, }, resolvers: [AcceptLanguageResolver], - typesOutputPath: join(__dirname, '../src/exported/api/@types/i18n.d.ts').replace(`${sep}dist`, ''), + typesOutputPath: join(__dirname, '../src/types/i18n.d.ts').replace(`${sep}dist`, ''), }), LogsModule, MikroOrmModule.forRoot(), diff --git a/src/database/seeders/database.seeder.ts b/src/database/seeders/database.seeder.ts index 31d4ccb7..045b251b 100644 --- a/src/database/seeders/database.seeder.ts +++ b/src/database/seeders/database.seeder.ts @@ -3,11 +3,11 @@ import type { EntityManager } from '@mikro-orm/core'; import { Seeder } from '@mikro-orm/seeder'; import { hashSync } from 'bcrypt'; -import { FileVisibilityGroup } from '@modules/files/entities/file-visibility.entity'; -import { Permission } from '@modules/permissions/entities/permission.entity'; -import { Promotion } from '@modules/promotions/entities/promotion.entity'; -import { UserVisibility } from '@modules/users/entities/user-visibility.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { FileVisibilityGroup } from '~/modules/files/entities/file-visibility.entity'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; +import { Promotion } from '~/modules/promotions/entities/promotion.entity'; +import { UserVisibility } from '~/modules/users/entities/user-visibility.entity'; +import { User } from '~/modules/users/entities/user.entity'; /** * This class is used to populate the database with some base data diff --git a/src/database/seeders/tests.seeder.ts b/src/database/seeders/tests.seeder.ts index e8a90ef4..a83f199b 100644 --- a/src/database/seeders/tests.seeder.ts +++ b/src/database/seeders/tests.seeder.ts @@ -2,12 +2,12 @@ import { EntityManager } from '@mikro-orm/core'; import { Seeder } from '@mikro-orm/seeder'; import { hashSync } from 'bcrypt'; -import { FileVisibilityGroup } from '@modules/files/entities/file-visibility.entity'; -import { Permission } from '@modules/permissions/entities/permission.entity'; -import { RoleExpiration } from '@modules/roles/entities/role-expiration.entity'; -import { Role } from '@modules/roles/entities/role.entity'; -import { UserVisibility } from '@modules/users/entities/user-visibility.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { FileVisibilityGroup } from '~/modules/files/entities/file-visibility.entity'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; +import { RoleExpiration } from '~/modules/roles/entities/role-expiration.entity'; +import { Role } from '~/modules/roles/entities/role.entity'; +import { UserVisibility } from '~/modules/users/entities/user-visibility.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { DatabaseSeeder } from './database.seeder'; diff --git a/src/exported b/src/exported deleted file mode 160000 index e2ed2db0..00000000 --- a/src/exported +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e2ed2db07067b350fb8847d72dbcde53c9d89136 diff --git a/src/main.ts b/src/main.ts index 703d236f..d1d24e14 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,9 +4,9 @@ import { NestExpressApplication } from '@nestjs/platform-express'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { I18nValidationExceptionFilter, I18nValidationPipe } from 'nestjs-i18n'; -import { VALIDATION_PIPE_OPTIONS, env } from '@env'; -import { I18nHttpExceptionFilter } from '@modules/base/http-errors'; -import '@exported/global/utils'; +import { VALIDATION_PIPE_OPTIONS, env } from '~/env'; +import { I18nHttpExceptionFilter } from '~/modules/base/http-errors'; +import '~/utils'; import { AppModule } from './app.module'; import pkg from '../package.json'; diff --git a/src/mikro-orm.config.ts b/src/mikro-orm.config.ts index 819c4220..d4a93a30 100644 --- a/src/mikro-orm.config.ts +++ b/src/mikro-orm.config.ts @@ -6,7 +6,7 @@ import { TsMorphMetadataProvider } from '@mikro-orm/reflection'; import { SqlHighlighter } from '@mikro-orm/sql-highlighter'; import { Logger } from '@nestjs/common'; -import { env } from '@env'; +import { env } from '~/env'; const logger = new Logger('MikroORM'); diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 2b8d5467..f0bb328f 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -1,9 +1,9 @@ import { Controller, Post, Body, Param, Get } from '@nestjs/common'; import { ApiOkResponse, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { OutputCreatedDTO, OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { OutputCreatedDTO, OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { AuthService } from './auth.service'; import { InputEmailParamsDTO, InputRegisterUserDTO, InputSignInDTO } from './dto/input.dto'; diff --git a/src/modules/auth/auth.module.ts b/src/modules/auth/auth.module.ts index 46aae104..6c2326c9 100644 --- a/src/modules/auth/auth.module.ts +++ b/src/modules/auth/auth.module.ts @@ -2,8 +2,8 @@ import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { PassportModule } from '@nestjs/passport'; -import { env } from '@env'; -import { UsersModule } from '@modules/users/users.module'; +import { env } from '~/env'; +import { UsersModule } from '~/modules/users/users.module'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 004eda60..c5ec8e27 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -1,14 +1,13 @@ -import type { email as Email } from '#types'; -import type { JWTPayload } from '#types/api'; +import type { email as Email, JWTPayload } from '~/types'; import { CreateRequestContext, MikroORM } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { compareSync } from 'bcrypt'; -import { env } from '@env'; -import { i18nForbiddenException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { User } from '@modules/users/entities/user.entity'; +import { env } from '~/env'; +import { i18nForbiddenException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { User } from '~/modules/users/entities/user.entity'; import { OutputTokenDTO } from './dto/output.dto'; diff --git a/src/modules/auth/decorators/permissions.decorator.ts b/src/modules/auth/decorators/permissions.decorator.ts index 98144eb6..771009e7 100644 --- a/src/modules/auth/decorators/permissions.decorator.ts +++ b/src/modules/auth/decorators/permissions.decorator.ts @@ -1,4 +1,4 @@ -import type { PERMISSION_NAMES } from '#types/api'; +import type { PERMISSION_NAMES } from '~/types'; import { SetMetadata, applyDecorators } from '@nestjs/common'; import { ApiForbiddenResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'; diff --git a/src/modules/auth/decorators/self-or-perms.decorator.ts b/src/modules/auth/decorators/self-or-perms.decorator.ts index 5579678b..be87ce73 100644 --- a/src/modules/auth/decorators/self-or-perms.decorator.ts +++ b/src/modules/auth/decorators/self-or-perms.decorator.ts @@ -1,4 +1,4 @@ -import type { PERMISSION_NAMES } from '#types/api'; +import type { PERMISSION_NAMES } from '~/types'; import { applyDecorators } from '@nestjs/common'; diff --git a/src/modules/auth/dto/input.dto.ts b/src/modules/auth/dto/input.dto.ts index 81eb8106..396d5a7a 100644 --- a/src/modules/auth/dto/input.dto.ts +++ b/src/modules/auth/dto/input.dto.ts @@ -1,18 +1,18 @@ -import type { email } from '#types'; import type { + email, InputSignInDto, InputRegisterUserAdminDto, InputRegisterUserDto, I18nTranslations, InputRegisterUsersAdminDto, -} from '#types/api'; +} from '~/types'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { ArrayNotEmpty, ArrayUnique, ValidateNested } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { I18nIsId, I18nIsEmail, I18nIsDate, I18nIsString, I18nIsStrongPassword } from '@modules/base/decorators'; +import { I18nIsId, I18nIsEmail, I18nIsDate, I18nIsString, I18nIsStrongPassword } from '~/modules/base/decorators'; export class InputRegisterUserAdminDTO implements InputRegisterUserAdminDto { @ApiProperty({ example: 'example@domain.com' }) diff --git a/src/modules/auth/dto/output.dto.ts b/src/modules/auth/dto/output.dto.ts index ba779838..f9c0d228 100644 --- a/src/modules/auth/dto/output.dto.ts +++ b/src/modules/auth/dto/output.dto.ts @@ -1,4 +1,4 @@ -import type { OutputTokenDto } from '#types/api'; +import type { OutputTokenDto } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; diff --git a/src/modules/auth/guards/permission.guard.ts b/src/modules/auth/guards/permission.guard.ts index 01a43941..bd4449de 100644 --- a/src/modules/auth/guards/permission.guard.ts +++ b/src/modules/auth/guards/permission.guard.ts @@ -1,11 +1,11 @@ -import type { PERMISSION_NAMES } from '#types/api'; import type { Request } from 'express'; +import type { PERMISSION_NAMES } from '~/types'; import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { JwtService } from '@nestjs/jwt'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { AuthService } from '../auth.service'; diff --git a/src/modules/auth/guards/self-or-perms.guard.ts b/src/modules/auth/guards/self-or-perms.guard.ts index 68d54052..e5ac086f 100644 --- a/src/modules/auth/guards/self-or-perms.guard.ts +++ b/src/modules/auth/guards/self-or-perms.guard.ts @@ -2,7 +2,7 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { JwtService } from '@nestjs/jwt'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { PermissionGuard } from './permission.guard'; import { SelfGuard } from './self.guard'; diff --git a/src/modules/auth/guards/self.guard.ts b/src/modules/auth/guards/self.guard.ts index c543ce49..2ade87bc 100644 --- a/src/modules/auth/guards/self.guard.ts +++ b/src/modules/auth/guards/self.guard.ts @@ -4,7 +4,7 @@ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { z } from 'zod'; -import { i18nBadRequestException } from '@modules/base/http-errors'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; import { AuthService } from '../auth.service'; diff --git a/src/modules/auth/strategies/jwt.strategy.ts b/src/modules/auth/strategies/jwt.strategy.ts index 46d3c2df..07874c9f 100644 --- a/src/modules/auth/strategies/jwt.strategy.ts +++ b/src/modules/auth/strategies/jwt.strategy.ts @@ -1,11 +1,11 @@ -import type { JWTPayload } from '#types/api'; +import type { JWTPayload } from '~/types'; import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { z } from 'zod'; -import { env } from '@env'; +import { env } from '~/env'; import { AuthService } from '../auth.service'; diff --git a/src/modules/base/decorators/is-boolean.decorator.ts b/src/modules/base/decorators/is-boolean.decorator.ts index 6d194fbe..a7550fbb 100644 --- a/src/modules/base/decorators/is-boolean.decorator.ts +++ b/src/modules/base/decorators/is-boolean.decorator.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { IsBoolean } from 'class-validator'; diff --git a/src/modules/base/decorators/is-date.decorator.ts b/src/modules/base/decorators/is-date.decorator.ts index b7ca85d4..c8a356bb 100644 --- a/src/modules/base/decorators/is-date.decorator.ts +++ b/src/modules/base/decorators/is-date.decorator.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { IsDateString } from 'class-validator'; diff --git a/src/modules/base/decorators/is-email.decorator.ts b/src/modules/base/decorators/is-email.decorator.ts index de44359c..f5b363cf 100644 --- a/src/modules/base/decorators/is-email.decorator.ts +++ b/src/modules/base/decorators/is-email.decorator.ts @@ -1,11 +1,10 @@ -import type { email } from '#types'; -import type { I18nTranslations } from '#types/api'; +import type { email, I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { IsEmail, ValidationOptions, registerDecorator } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { EmailsService } from '@modules/emails/emails.service'; +import { EmailsService } from '~/modules/emails/emails.service'; /** * Custom class validator to check if the email can be used or not. diff --git a/src/modules/base/decorators/is-id.decorator.ts b/src/modules/base/decorators/is-id.decorator.ts index 7724aa2e..38970c6b 100644 --- a/src/modules/base/decorators/is-id.decorator.ts +++ b/src/modules/base/decorators/is-id.decorator.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { ValidationOptions, isNumber, isNumberString, registerDecorator } from 'class-validator'; diff --git a/src/modules/base/decorators/is-phone.decorator.ts b/src/modules/base/decorators/is-phone.decorator.ts index 4271cabc..0dd4c9a1 100644 --- a/src/modules/base/decorators/is-phone.decorator.ts +++ b/src/modules/base/decorators/is-phone.decorator.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { IsPhoneNumber } from 'class-validator'; diff --git a/src/modules/base/decorators/is-string.decorator.ts b/src/modules/base/decorators/is-string.decorator.ts index bdcb3197..136637db 100644 --- a/src/modules/base/decorators/is-string.decorator.ts +++ b/src/modules/base/decorators/is-string.decorator.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { IsString } from 'class-validator'; diff --git a/src/modules/base/decorators/is-strong-pass.decorator.ts b/src/modules/base/decorators/is-strong-pass.decorator.ts index 38d46013..4969c453 100644 --- a/src/modules/base/decorators/is-strong-pass.decorator.ts +++ b/src/modules/base/decorators/is-strong-pass.decorator.ts @@ -1,11 +1,11 @@ -import type { I18nTranslations } from '#types/api'; +import type { I18nTranslations } from '~/types'; import { applyDecorators } from '@nestjs/common'; import { ValidationOptions, registerDecorator } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { env } from '@env'; -import { randomInt } from '@exported/global/utils'; +import { env } from '~/env'; +import { randomInt } from '~/utils'; const SYMBOL_CHARS = '!@#$%^&*()'; const LOWERCASE_CHARS = 'abcdefghijklmnopqrstuvwxyz'; diff --git a/src/modules/base/dto/input.dto.ts b/src/modules/base/dto/input.dto.ts index b5b59e1f..a8c400ae 100644 --- a/src/modules/base/dto/input.dto.ts +++ b/src/modules/base/dto/input.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { I18nIsId } from '@modules/base/decorators'; +import { I18nIsId } from '~/modules/base/decorators'; export class InputIdParamDTO { @ApiProperty({ minimum: 1 }) diff --git a/src/modules/base/dto/output.dto.ts b/src/modules/base/dto/output.dto.ts index f9063a5d..45fbfb89 100644 --- a/src/modules/base/dto/output.dto.ts +++ b/src/modules/base/dto/output.dto.ts @@ -4,7 +4,7 @@ import type { OutputResponseDto, HttpStatusNames, I18nTranslations, -} from '#types/api'; +} from '~/types'; import { PathImpl2 } from '@nestjs/config'; import { ApiProperty } from '@nestjs/swagger'; diff --git a/src/modules/base/entities/base.entity.ts b/src/modules/base/entities/base.entity.ts index a200ce54..32306cf0 100644 --- a/src/modules/base/entities/base.entity.ts +++ b/src/modules/base/entities/base.entity.ts @@ -1,4 +1,4 @@ -import type { OutputBaseDto } from '#types/api'; +import type { OutputBaseDto } from '~/types'; import { BaseEntity as BE, Entity, PrimaryKey, Property } from '@mikro-orm/core'; diff --git a/src/modules/base/http-errors/bad-request.ts b/src/modules/base/http-errors/bad-request.ts index 1d152741..9a87f43d 100644 --- a/src/modules/base/http-errors/bad-request.ts +++ b/src/modules/base/http-errors/bad-request.ts @@ -1,4 +1,4 @@ -import type { HttpStatusNames } from '#types/api'; +import type { HttpStatusNames } from '~/types'; import { I18nHttpException } from './http-exception'; diff --git a/src/modules/base/http-errors/forbidden.ts b/src/modules/base/http-errors/forbidden.ts index 94985385..73f37ae9 100644 --- a/src/modules/base/http-errors/forbidden.ts +++ b/src/modules/base/http-errors/forbidden.ts @@ -1,4 +1,4 @@ -import type { HttpStatusNames } from '#types/api'; +import type { HttpStatusNames } from '~/types'; import { I18nHttpException } from './http-exception'; diff --git a/src/modules/base/http-errors/http-exception.ts b/src/modules/base/http-errors/http-exception.ts index bf7653e6..ca414a95 100644 --- a/src/modules/base/http-errors/http-exception.ts +++ b/src/modules/base/http-errors/http-exception.ts @@ -1,4 +1,4 @@ -import type { I18nTranslations, OutputErrorResponseDto } from '#types/api'; +import type { I18nTranslations, OutputErrorResponseDto } from '~/types'; import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common'; import { Response } from 'express'; diff --git a/src/modules/base/http-errors/not-found.ts b/src/modules/base/http-errors/not-found.ts index f14e242b..26bd3ee6 100644 --- a/src/modules/base/http-errors/not-found.ts +++ b/src/modules/base/http-errors/not-found.ts @@ -1,4 +1,4 @@ -import type { HttpStatusNames } from '#types/api'; +import type { HttpStatusNames } from '~/types'; import { I18nHttpException } from './http-exception'; diff --git a/src/modules/base/http-errors/unauthorized.ts b/src/modules/base/http-errors/unauthorized.ts index 1268a94e..37973079 100644 --- a/src/modules/base/http-errors/unauthorized.ts +++ b/src/modules/base/http-errors/unauthorized.ts @@ -1,4 +1,4 @@ -import type { HttpStatusNames } from '#types/api'; +import type { HttpStatusNames } from '~/types'; import { I18nHttpException } from './http-exception'; diff --git a/src/modules/emails/emails.service.ts b/src/modules/emails/emails.service.ts index fc3227f5..30f8b5e4 100644 --- a/src/modules/emails/emails.service.ts +++ b/src/modules/emails/emails.service.ts @@ -1,13 +1,13 @@ /* istanbul ignore file */ // TODO: (KEY: 3) Find a way to test emails (sending / receiving) -import type { email } from '#types'; +import type { email } from '~/types'; import { Injectable } from '@nestjs/common'; import { Transporter, createTransport } from 'nodemailer'; -import { env } from '@env'; -import { i18nBadRequestException } from '@modules/base/http-errors'; +import { env } from '~/env'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; interface EmailOptions { to: string[]; diff --git a/src/modules/files/dto/output.dto.ts b/src/modules/files/dto/output.dto.ts index e8d21571..22327367 100644 --- a/src/modules/files/dto/output.dto.ts +++ b/src/modules/files/dto/output.dto.ts @@ -1,8 +1,8 @@ -import type { OutputFileDto, OutputFileVisibilityGroupDto } from '#types/api'; +import type { OutputFileDto, OutputFileVisibilityGroupDto } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; -import { OutputBaseDTO } from '@modules/base/dto/output.dto'; +import { OutputBaseDTO } from '~/modules/base/dto/output.dto'; export class OutputFileDTO implements OutputFileDto { @ApiProperty() diff --git a/src/modules/files/entities/file-visibility.entity.ts b/src/modules/files/entities/file-visibility.entity.ts index 1f0ebe63..385b1013 100644 --- a/src/modules/files/entities/file-visibility.entity.ts +++ b/src/modules/files/entities/file-visibility.entity.ts @@ -1,8 +1,8 @@ import { Collection, Entity, ManyToMany, OneToMany, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { File } from '@modules/files/entities/file.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { File } from '~/modules/files/entities/file.entity'; +import { User } from '~/modules/users/entities/user.entity'; @Entity({ tableName: 'files_visibility_groups' }) export class FileVisibilityGroup extends BaseEntity { diff --git a/src/modules/files/entities/file.entity.ts b/src/modules/files/entities/file.entity.ts index de5517c4..e8dbdc43 100644 --- a/src/modules/files/entities/file.entity.ts +++ b/src/modules/files/entities/file.entity.ts @@ -1,10 +1,10 @@ import { Entity, ManyToOne, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { FileVisibilityGroup } from '@modules/files/entities/file-visibility.entity'; -import { PromotionPicture } from '@modules/promotions/entities/promotion-picture.entity'; -import { UserBanner } from '@modules/users/entities/user-banner.entity'; -import { UserPicture } from '@modules/users/entities/user-picture.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { FileVisibilityGroup } from '~/modules/files/entities/file-visibility.entity'; +import { PromotionPicture } from '~/modules/promotions/entities/promotion-picture.entity'; +import { UserBanner } from '~/modules/users/entities/user-banner.entity'; +import { UserPicture } from '~/modules/users/entities/user-picture.entity'; export type FileKind = UserPicture | UserBanner | PromotionPicture; diff --git a/src/modules/files/files.module.ts b/src/modules/files/files.module.ts index 07bd5d4d..4f405ea5 100644 --- a/src/modules/files/files.module.ts +++ b/src/modules/files/files.module.ts @@ -1,8 +1,8 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; -import { EmailsService } from '@modules/emails/emails.service'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { EmailsService } from '~/modules/emails/emails.service'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { FileVisibilityGroup } from './entities/file-visibility.entity'; import { FilesService } from './files.service'; diff --git a/src/modules/files/files.service.ts b/src/modules/files/files.service.ts index 62044d6c..8ed00e65 100644 --- a/src/modules/files/files.service.ts +++ b/src/modules/files/files.service.ts @@ -7,9 +7,9 @@ import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable, StreamableFile } from '@nestjs/common'; import { fromBuffer, MimeType } from 'file-type'; -import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { User } from '@modules/users/entities/user.entity'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { User } from '~/modules/users/entities/user.entity'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { FileVisibilityGroup } from './entities/file-visibility.entity'; import { File } from './entities/file.entity'; diff --git a/src/modules/files/images.service.ts b/src/modules/files/images.service.ts index c7974f46..5de77127 100644 --- a/src/modules/files/images.service.ts +++ b/src/modules/files/images.service.ts @@ -1,10 +1,10 @@ -import type { aspect_ratio } from '#types'; +import type { aspect_ratio } from '~/types'; import { Injectable } from '@nestjs/common'; import { fromBuffer } from 'file-type'; import sharp from 'sharp'; -import { i18nBadRequestException } from '@modules/base/http-errors'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; import { FilesService, WriteFileOptions } from './files.service'; diff --git a/src/modules/logs/dto/output.dto.ts b/src/modules/logs/dto/output.dto.ts index 3b0daad4..1f6728f9 100644 --- a/src/modules/logs/dto/output.dto.ts +++ b/src/modules/logs/dto/output.dto.ts @@ -1,4 +1,4 @@ -import type { OutputLogDto } from '#types/api'; +import type { OutputLogDto } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; diff --git a/src/modules/logs/entities/log.entity.ts b/src/modules/logs/entities/log.entity.ts index 761c8b9c..4e37405b 100644 --- a/src/modules/logs/entities/log.entity.ts +++ b/src/modules/logs/entities/log.entity.ts @@ -1,7 +1,7 @@ import { Entity, ManyToOne, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { User } from '~/modules/users/entities/user.entity'; @Entity({ tableName: 'users_logs' }) export class Log extends BaseEntity { diff --git a/src/modules/logs/interceptor/logging.interceptor.ts b/src/modules/logs/interceptor/logging.interceptor.ts index 12ec64ce..529be069 100644 --- a/src/modules/logs/interceptor/logging.interceptor.ts +++ b/src/modules/logs/interceptor/logging.interceptor.ts @@ -4,7 +4,7 @@ import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { tap, type Observable } from 'rxjs'; -import { User } from '@modules/users/entities/user.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { Log } from '../entities/log.entity'; diff --git a/src/modules/logs/logs.controller.ts b/src/modules/logs/logs.controller.ts index 026ca8ff..93e80318 100644 --- a/src/modules/logs/logs.controller.ts +++ b/src/modules/logs/logs.controller.ts @@ -2,13 +2,13 @@ import { Controller, Delete, Get, Param, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiBearerAuth, ApiOkResponse, ApiParam, ApiOperation } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { GuardSelfOrPermissions } from '@modules/auth/decorators/self-or-perms.decorator'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { SelfOrPermissionGuard } from '@modules/auth/guards/self-or-perms.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { InputIdParamDTO } from '@modules/base/dto/input.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { GuardSelfOrPermissions } from '~/modules/auth/decorators/self-or-perms.decorator'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { SelfOrPermissionGuard } from '~/modules/auth/guards/self-or-perms.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { InputIdParamDTO } from '~/modules/base/dto/input.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; import { OutputLogDTO } from './dto/output.dto'; import { LogsService } from './logs.service'; diff --git a/src/modules/logs/logs.module.ts b/src/modules/logs/logs.module.ts index ed78a1a4..18513640 100644 --- a/src/modules/logs/logs.module.ts +++ b/src/modules/logs/logs.module.ts @@ -2,8 +2,8 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { AuthService } from '@modules/auth/auth.service'; -import { UsersModule } from '@modules/users/users.module'; +import { AuthService } from '~/modules/auth/auth.service'; +import { UsersModule } from '~/modules/users/users.module'; import { Log } from './entities/log.entity'; import { LogsController } from './logs.controller'; diff --git a/src/modules/logs/logs.service.ts b/src/modules/logs/logs.service.ts index d24b5b6e..afa0be4e 100644 --- a/src/modules/logs/logs.service.ts +++ b/src/modules/logs/logs.service.ts @@ -2,7 +2,7 @@ import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; import { OutputLogDTO } from './dto/output.dto'; import { Log } from './entities/log.entity'; diff --git a/src/modules/permissions/dto/input.dto.ts b/src/modules/permissions/dto/input.dto.ts index 3a595dfd..15863d81 100644 --- a/src/modules/permissions/dto/input.dto.ts +++ b/src/modules/permissions/dto/input.dto.ts @@ -1,16 +1,11 @@ -import type { - InputUpdatePermissionDto, - PERMISSION_NAMES, - InputCreatePermissionDto, - I18nTranslations, -} from '#types/api'; +import type { InputUpdatePermissionDto, PERMISSION_NAMES, InputCreatePermissionDto, I18nTranslations } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; import { IsIn } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { I18nIsDate, I18nIsId, I18nIsBoolean } from '@modules/base/decorators'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { I18nIsDate, I18nIsId, I18nIsBoolean } from '~/modules/base/decorators'; export class InputCreatePermissionDTO implements InputCreatePermissionDto { @ApiProperty() diff --git a/src/modules/permissions/dto/output.dto.ts b/src/modules/permissions/dto/output.dto.ts index 83ab8b04..b585d562 100644 --- a/src/modules/permissions/dto/output.dto.ts +++ b/src/modules/permissions/dto/output.dto.ts @@ -1,9 +1,9 @@ -import type { OutputPermissionDto, OutputPermissionsOfRoleDto, PERMISSION_NAMES } from '#types/api'; +import type { OutputPermissionDto, OutputPermissionsOfRoleDto, PERMISSION_NAMES } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { OutputBaseDTO } from '@modules/base/dto/output.dto'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { OutputBaseDTO } from '~/modules/base/dto/output.dto'; export class OutputPermissionsOfRoleDTO implements OutputPermissionsOfRoleDto { @ApiProperty() diff --git a/src/modules/permissions/entities/permission.entity.ts b/src/modules/permissions/entities/permission.entity.ts index 60f7253f..6c335684 100644 --- a/src/modules/permissions/entities/permission.entity.ts +++ b/src/modules/permissions/entities/permission.entity.ts @@ -1,9 +1,9 @@ -import type { PERMISSION_NAMES } from '#types/api'; +import type { PERMISSION_NAMES } from '~/types'; import { Entity, ManyToOne, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { User } from '~/modules/users/entities/user.entity'; @Entity({ tableName: 'permissions' }) export class Permission extends BaseEntity { diff --git a/src/modules/permissions/permissions.controller.ts b/src/modules/permissions/permissions.controller.ts index 56006b86..fac86a6e 100644 --- a/src/modules/permissions/permissions.controller.ts +++ b/src/modules/permissions/permissions.controller.ts @@ -2,12 +2,12 @@ import { Body, Controller, Get, Param, Post, UseGuards, Patch } from '@nestjs/co import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { GuardSelfOrPermissions } from '@modules/auth/decorators/self-or-perms.decorator'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { SelfOrPermissionGuard } from '@modules/auth/guards/self-or-perms.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { InputIdParamDTO } from '@modules/base/dto/input.dto'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { GuardSelfOrPermissions } from '~/modules/auth/decorators/self-or-perms.decorator'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { SelfOrPermissionGuard } from '~/modules/auth/guards/self-or-perms.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { InputIdParamDTO } from '~/modules/base/dto/input.dto'; import { InputUpdatePermissionDTO, InputCreatePermissionDTO } from './dto/input.dto'; import { OutputPermissionDTO } from './dto/output.dto'; diff --git a/src/modules/permissions/permissions.module.ts b/src/modules/permissions/permissions.module.ts index 0049d36c..7d54665b 100644 --- a/src/modules/permissions/permissions.module.ts +++ b/src/modules/permissions/permissions.module.ts @@ -2,8 +2,8 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { AuthService } from '@modules/auth/auth.service'; -import { UsersModule } from '@modules/users/users.module'; +import { AuthService } from '~/modules/auth/auth.service'; +import { UsersModule } from '~/modules/users/users.module'; import { Permission } from './entities/permission.entity'; import { PermissionsController } from './permissions.controller'; diff --git a/src/modules/permissions/permissions.service.ts b/src/modules/permissions/permissions.service.ts index 61d1468e..f1ba5d9b 100644 --- a/src/modules/permissions/permissions.service.ts +++ b/src/modules/permissions/permissions.service.ts @@ -2,7 +2,7 @@ import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; import { InputUpdatePermissionDTO, InputCreatePermissionDTO } from './dto/input.dto'; import { OutputPermissionDTO } from './dto/output.dto'; diff --git a/src/modules/promotions/dto/input.dto.ts b/src/modules/promotions/dto/input.dto.ts index c807c50a..215314f1 100644 --- a/src/modules/promotions/dto/input.dto.ts +++ b/src/modules/promotions/dto/input.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { I18nIsId } from '@modules/base/decorators'; +import { I18nIsId } from '~/modules/base/decorators'; export class InputPromotionNumberParamDTO { @ApiProperty({ minimum: 1 }) diff --git a/src/modules/promotions/dto/output.dto.ts b/src/modules/promotions/dto/output.dto.ts index 2147d5b5..861b8b6a 100644 --- a/src/modules/promotions/dto/output.dto.ts +++ b/src/modules/promotions/dto/output.dto.ts @@ -1,9 +1,9 @@ -import type { OutputPromotionPictureDto, OutputPromotionDto } from '#types/api'; +import type { OutputPromotionPictureDto, OutputPromotionDto } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; -import { OutputBaseDTO } from '@modules/base/dto/output.dto'; -import { OutputFileDTO } from '@modules/files/dto/output.dto'; +import { OutputBaseDTO } from '~/modules/base/dto/output.dto'; +import { OutputFileDTO } from '~/modules/files/dto/output.dto'; export class OutputPromotionDTO extends OutputBaseDTO implements OutputPromotionDto { @ApiProperty() diff --git a/src/modules/promotions/entities/promotion-picture.entity.ts b/src/modules/promotions/entities/promotion-picture.entity.ts index 7c968aef..cfc36214 100644 --- a/src/modules/promotions/entities/promotion-picture.entity.ts +++ b/src/modules/promotions/entities/promotion-picture.entity.ts @@ -1,6 +1,6 @@ import { Entity, OneToOne, Property } from '@mikro-orm/core'; -import { File } from '@modules/files/entities/file.entity'; +import { File } from '~/modules/files/entities/file.entity'; import { Promotion } from './promotion.entity'; diff --git a/src/modules/promotions/entities/promotion.entity.ts b/src/modules/promotions/entities/promotion.entity.ts index f142ba49..da5b13d6 100644 --- a/src/modules/promotions/entities/promotion.entity.ts +++ b/src/modules/promotions/entities/promotion.entity.ts @@ -1,7 +1,7 @@ import { Cascade, Collection, Entity, OneToMany, OneToOne, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { PromotionPicture } from './promotion-picture.entity'; diff --git a/src/modules/promotions/promotions.controller.ts b/src/modules/promotions/promotions.controller.ts index 57305f70..d8faaf8c 100644 --- a/src/modules/promotions/promotions.controller.ts +++ b/src/modules/promotions/promotions.controller.ts @@ -2,15 +2,15 @@ import { Controller, Delete, Get, Param, Post, Req, UploadedFile, UseGuards } fr import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException } from '@modules/base/http-errors'; -import { ApiDownloadFile } from '@modules/files/decorators/download.decorator'; -import { ApiUploadFile } from '@modules/files/decorators/upload.decorator'; -import { FilesService } from '@modules/files/files.service'; -import { Request } from '@modules/users/entities/user.entity'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; +import { ApiDownloadFile } from '~/modules/files/decorators/download.decorator'; +import { ApiUploadFile } from '~/modules/files/decorators/upload.decorator'; +import { FilesService } from '~/modules/files/files.service'; +import { Request } from '~/modules/users/entities/user.entity'; import { InputPromotionNumberParamDTO } from './dto/input.dto'; import { OutputPromotionDTO } from './dto/output.dto'; diff --git a/src/modules/promotions/promotions.module.ts b/src/modules/promotions/promotions.module.ts index 67c46064..3d7da573 100644 --- a/src/modules/promotions/promotions.module.ts +++ b/src/modules/promotions/promotions.module.ts @@ -2,11 +2,11 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { AuthService } from '@modules/auth/auth.service'; -import { EmailsService } from '@modules/emails/emails.service'; -import { FilesService } from '@modules/files/files.service'; -import { ImagesService } from '@modules/files/images.service'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { AuthService } from '~/modules/auth/auth.service'; +import { EmailsService } from '~/modules/emails/emails.service'; +import { FilesService } from '~/modules/files/files.service'; +import { ImagesService } from '~/modules/files/images.service'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { PromotionPicture } from './entities/promotion-picture.entity'; import { Promotion } from './entities/promotion.entity'; diff --git a/src/modules/promotions/promotions.service.ts b/src/modules/promotions/promotions.service.ts index d5f696b9..9894a9f4 100644 --- a/src/modules/promotions/promotions.service.ts +++ b/src/modules/promotions/promotions.service.ts @@ -4,10 +4,10 @@ import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; -import { env } from '@env'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nNotFoundException } from '@modules/base/http-errors'; -import { ImagesService } from '@modules/files/images.service'; +import { env } from '~/env'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nNotFoundException } from '~/modules/base/http-errors'; +import { ImagesService } from '~/modules/files/images.service'; import { OutputPromotionPictureDTO, OutputPromotionDTO } from './dto/output.dto'; import { PromotionPicture } from './entities/promotion-picture.entity'; diff --git a/src/modules/roles/dto/input.dto.ts b/src/modules/roles/dto/input.dto.ts index b44ee5c9..89a9c1e7 100644 --- a/src/modules/roles/dto/input.dto.ts +++ b/src/modules/roles/dto/input.dto.ts @@ -6,15 +6,15 @@ import type { I18nTranslations, InputUpdateRoleUsersDto, InputDeleteRoleUsersDto, -} from '#types/api'; +} from '~/types'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { ArrayNotEmpty, ArrayUnique, IsEnum, IsUppercase, ValidateNested } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { I18nIsDate, I18nIsId, I18nIsString } from '@modules/base/decorators'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { I18nIsDate, I18nIsId, I18nIsString } from '~/modules/base/decorators'; export class InputCreateRoleDTO implements InputCreateRoleDto { @ApiProperty({ type: String, example: 'AE_ADMINS' }) diff --git a/src/modules/roles/dto/output.dto.ts b/src/modules/roles/dto/output.dto.ts index e1a4a8d6..6c51dfcc 100644 --- a/src/modules/roles/dto/output.dto.ts +++ b/src/modules/roles/dto/output.dto.ts @@ -1,9 +1,9 @@ -import type { OutputRoleDto, OutputRoleUserDto, PERMISSION_NAMES } from '#types/api'; +import type { OutputRoleDto, OutputRoleUserDto, PERMISSION_NAMES } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { OutputBaseUserDTO } from '@modules/users/dto/output.dto'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { OutputBaseUserDTO } from '~/modules/users/dto/output.dto'; export class OutputRoleUserDTO extends OutputBaseUserDTO implements OutputRoleUserDto { @ApiProperty({ type: Date }) diff --git a/src/modules/roles/entities/role-expiration.entity.ts b/src/modules/roles/entities/role-expiration.entity.ts index 1861654b..1cb2870c 100644 --- a/src/modules/roles/entities/role-expiration.entity.ts +++ b/src/modules/roles/entities/role-expiration.entity.ts @@ -1,8 +1,8 @@ import { Entity, ManyToOne, Property } from '@mikro-orm/core'; import { ApiProperty } from '@nestjs/swagger'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { Role } from './role.entity'; diff --git a/src/modules/roles/entities/role.entity.ts b/src/modules/roles/entities/role.entity.ts index 2e55cc20..d0fe65b0 100644 --- a/src/modules/roles/entities/role.entity.ts +++ b/src/modules/roles/entities/role.entity.ts @@ -1,9 +1,9 @@ -import type { PERMISSION_NAMES } from '#types/api'; +import type { PERMISSION_NAMES } from '~/types'; import { Collection, Entity, ManyToMany, Property } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { User } from '~/modules/users/entities/user.entity'; /** * Entity used to store roles, which are a collection of permissions diff --git a/src/modules/roles/roles.controller.ts b/src/modules/roles/roles.controller.ts index e0990747..0faa80be 100644 --- a/src/modules/roles/roles.controller.ts +++ b/src/modules/roles/roles.controller.ts @@ -2,10 +2,10 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, UseGuards } from '@n import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiBody, ApiParam } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { InputIdParamDTO } from '@modules/base/dto/input.dto'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { InputIdParamDTO } from '~/modules/base/dto/input.dto'; import { InputUpdateRoleDTO, diff --git a/src/modules/roles/roles.module.ts b/src/modules/roles/roles.module.ts index e20ca528..cab744b0 100644 --- a/src/modules/roles/roles.module.ts +++ b/src/modules/roles/roles.module.ts @@ -2,8 +2,8 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { AuthService } from '@modules/auth/auth.service'; -import { UsersModule } from '@modules/users/users.module'; +import { AuthService } from '~/modules/auth/auth.service'; +import { UsersModule } from '~/modules/users/users.module'; import { Role } from './entities/role.entity'; import { RolesController } from './roles.controller'; diff --git a/src/modules/roles/roles.service.ts b/src/modules/roles/roles.service.ts index 548d89b4..531c39bd 100644 --- a/src/modules/roles/roles.service.ts +++ b/src/modules/roles/roles.service.ts @@ -1,13 +1,13 @@ -import type { PERMISSION_NAMES } from '#types/api'; +import type { PERMISSION_NAMES } from '~/types'; import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; -import { OutputBaseUserDTO } from '@modules/users/dto/output.dto'; -import { User } from '@modules/users/entities/user.entity'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; +import { OutputBaseUserDTO } from '~/modules/users/dto/output.dto'; +import { User } from '~/modules/users/entities/user.entity'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { InputUpdateRoleDTO } from './dto/input.dto'; import { OutputRoleDTO, OutputRoleUserDTO } from './dto/output.dto'; diff --git a/src/modules/users/controllers/users-data.controller.ts b/src/modules/users/controllers/users-data.controller.ts index f5acc6ac..c70a49f8 100644 --- a/src/modules/users/controllers/users-data.controller.ts +++ b/src/modules/users/controllers/users-data.controller.ts @@ -2,17 +2,17 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Req, UseGuards } fro import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiBody, ApiOkResponse, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { GuardSelfOrPermissions } from '@modules/auth/decorators/self-or-perms.decorator'; -import { GuardSelfParam } from '@modules/auth/decorators/self.decorator'; -import { InputRegisterUsersAdminDTO } from '@modules/auth/dto/input.dto'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { SelfOrPermissionGuard } from '@modules/auth/guards/self-or-perms.guard'; -import { SelfGuard } from '@modules/auth/guards/self.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { InputIdParamDTO } from '@modules/base/dto/input.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { OutputPermissionDTO } from '@modules/permissions/dto/output.dto'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { GuardSelfOrPermissions } from '~/modules/auth/decorators/self-or-perms.decorator'; +import { GuardSelfParam } from '~/modules/auth/decorators/self.decorator'; +import { InputRegisterUsersAdminDTO } from '~/modules/auth/dto/input.dto'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { SelfOrPermissionGuard } from '~/modules/auth/guards/self-or-perms.guard'; +import { SelfGuard } from '~/modules/auth/guards/self.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { InputIdParamDTO } from '~/modules/base/dto/input.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { OutputPermissionDTO } from '~/modules/permissions/dto/output.dto'; import { InputUpdateUserDTO, InputUpdateUserVisibilityDTO } from '../dto/input.dto'; import { OutputUserDTO, OutputBaseUserDTO, OutputUserRoleDTO, OutputUserVisibilityDTO } from '../dto/output.dto'; diff --git a/src/modules/users/controllers/users-files.controller.ts b/src/modules/users/controllers/users-files.controller.ts index 70d93720..5b96bedc 100644 --- a/src/modules/users/controllers/users-files.controller.ts +++ b/src/modules/users/controllers/users-files.controller.ts @@ -2,17 +2,17 @@ import { Controller, Delete, Get, Param, Post, Req, UploadedFile, UseGuards } fr import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; -import { GuardPermissions } from '@modules/auth/decorators/permissions.decorator'; -import { GuardSelfOrPermissions } from '@modules/auth/decorators/self-or-perms.decorator'; -import { PermissionGuard } from '@modules/auth/guards/permission.guard'; -import { SelfOrPermissionGuard } from '@modules/auth/guards/self-or-perms.guard'; -import { ApiNotOkResponses } from '@modules/base/decorators/api-not-ok.decorator'; -import { InputIdParamDTO } from '@modules/base/dto/input.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException } from '@modules/base/http-errors'; -import { ApiDownloadFile } from '@modules/files/decorators/download.decorator'; -import { ApiUploadFile } from '@modules/files/decorators/upload.decorator'; -import { FilesService } from '@modules/files/files.service'; +import { GuardPermissions } from '~/modules/auth/decorators/permissions.decorator'; +import { GuardSelfOrPermissions } from '~/modules/auth/decorators/self-or-perms.decorator'; +import { PermissionGuard } from '~/modules/auth/guards/permission.guard'; +import { SelfOrPermissionGuard } from '~/modules/auth/guards/self-or-perms.guard'; +import { ApiNotOkResponses } from '~/modules/base/decorators/api-not-ok.decorator'; +import { InputIdParamDTO } from '~/modules/base/dto/input.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; +import { ApiDownloadFile } from '~/modules/files/decorators/download.decorator'; +import { ApiUploadFile } from '~/modules/files/decorators/upload.decorator'; +import { FilesService } from '~/modules/files/files.service'; import { OutputUserBannerDTO, OutputUserPictureDTO } from '../dto/output.dto'; import { Request } from '../entities/user.entity'; diff --git a/src/modules/users/dto/input.dto.ts b/src/modules/users/dto/input.dto.ts index 289e1782..302b06c8 100644 --- a/src/modules/users/dto/input.dto.ts +++ b/src/modules/users/dto/input.dto.ts @@ -1,11 +1,10 @@ -import type { email } from '#types'; -import type { GENDERS, InputUpdateUserVisibilityDto, InputUpdateUserDto, I18nTranslations } from '#types/api'; +import type { email, GENDERS, InputUpdateUserVisibilityDto, InputUpdateUserDto, I18nTranslations } from '~/types'; import { ApiProperty } from '@nestjs/swagger'; import { IsIn, IsOptional } from 'class-validator'; import { i18nValidationMessage } from 'nestjs-i18n'; -import { USER_GENDER } from '@exported/api/constants/genders'; +import { USER_GENDER } from '~/constants/genders'; import { I18nIsBoolean, I18nIsDate, @@ -13,7 +12,7 @@ import { I18nIsId, I18nIsPhoneNumber, I18nIsString, -} from '@modules/base/decorators'; +} from '~/modules/base/decorators'; export class InputUpdateUserDTO implements InputUpdateUserDto { @ApiProperty({ required: false }) diff --git a/src/modules/users/dto/output.dto.ts b/src/modules/users/dto/output.dto.ts index 6805d126..9c62c7f3 100644 --- a/src/modules/users/dto/output.dto.ts +++ b/src/modules/users/dto/output.dto.ts @@ -1,19 +1,19 @@ -import type { email } from '#types'; import type { + email, OutputUserBannerDto, OutputUserPictureDto, OutputUserRoleDto, OutputUserVisibilityDto, OutputBaseUserDto, -} from '#types/api'; +} from '~/types'; import { ApiProperty } from '@nestjs/swagger'; -import { OutputUserDto, PERMISSION_NAMES, GENDERS } from '#types/api'; -import { USER_GENDER } from '@exported/api/constants/genders'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { OutputBaseDTO } from '@modules/base/dto/output.dto'; -import { OutputFileDTO } from '@modules/files/dto/output.dto'; +import { USER_GENDER } from '~/constants/genders'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { OutputBaseDTO } from '~/modules/base/dto/output.dto'; +import { OutputFileDTO } from '~/modules/files/dto/output.dto'; +import { OutputUserDto, PERMISSION_NAMES, GENDERS } from '~/types'; export class OutputBaseUserDTO extends OutputBaseDTO implements OutputBaseUserDto { @ApiProperty() diff --git a/src/modules/users/entities/user-banner.entity.ts b/src/modules/users/entities/user-banner.entity.ts index f6331c7e..25202074 100644 --- a/src/modules/users/entities/user-banner.entity.ts +++ b/src/modules/users/entities/user-banner.entity.ts @@ -1,6 +1,6 @@ import { Entity, OneToOne, Property } from '@mikro-orm/core'; -import { File } from '@modules/files/entities/file.entity'; +import { File } from '~/modules/files/entities/file.entity'; import { User } from './user.entity'; diff --git a/src/modules/users/entities/user-picture.entity.ts b/src/modules/users/entities/user-picture.entity.ts index d479ebde..97e3f6e6 100644 --- a/src/modules/users/entities/user-picture.entity.ts +++ b/src/modules/users/entities/user-picture.entity.ts @@ -1,6 +1,6 @@ import { Entity, OneToOne, Property } from '@mikro-orm/core'; -import { File } from '@modules/files/entities/file.entity'; +import { File } from '~/modules/files/entities/file.entity'; import { User } from './user.entity'; diff --git a/src/modules/users/entities/user-visibility.entity.ts b/src/modules/users/entities/user-visibility.entity.ts index 43355e69..bba92fb5 100644 --- a/src/modules/users/entities/user-visibility.entity.ts +++ b/src/modules/users/entities/user-visibility.entity.ts @@ -1,6 +1,6 @@ import { Entity, Property, OneToOne } from '@mikro-orm/core'; -import { BaseEntity } from '@modules/base/entities/base.entity'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; import { User } from './user.entity'; diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 1fc047ec..ab73e035 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -1,14 +1,14 @@ -import type { email } from '#types'; +import type { email } from '~/types'; import { Cascade, Collection, Entity, ManyToMany, ManyToOne, OneToMany, OneToOne, Property } from '@mikro-orm/core'; -import { USER_GENDER } from '@exported/api/constants/genders'; -import { BaseEntity } from '@modules/base/entities/base.entity'; -import { FileVisibilityGroup } from '@modules/files/entities/file-visibility.entity'; -import { Log } from '@modules/logs/entities/log.entity'; -import { Permission } from '@modules/permissions/entities/permission.entity'; -import { Promotion } from '@modules/promotions/entities/promotion.entity'; -import { Role } from '@modules/roles/entities/role.entity'; +import { USER_GENDER } from '~/constants/genders'; +import { BaseEntity } from '~/modules/base/entities/base.entity'; +import { FileVisibilityGroup } from '~/modules/files/entities/file-visibility.entity'; +import { Log } from '~/modules/logs/entities/log.entity'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; +import { Promotion } from '~/modules/promotions/entities/promotion.entity'; +import { Role } from '~/modules/roles/entities/role.entity'; import { UserBanner } from './user-banner.entity'; import { UserPicture } from './user-picture.entity'; diff --git a/src/modules/users/services/users-data.service.ts b/src/modules/users/services/users-data.service.ts index 87305809..ab07299e 100644 --- a/src/modules/users/services/users-data.service.ts +++ b/src/modules/users/services/users-data.service.ts @@ -1,5 +1,4 @@ -import type { email } from '#types'; -import type { I18nTranslations, PERMISSION_NAMES } from '#types/api'; +import type { email, I18nTranslations, PERMISSION_NAMES } from '~/types'; import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; @@ -8,18 +7,18 @@ import { compareSync, hashSync } from 'bcrypt'; import { I18nContext, I18nService } from 'nestjs-i18n'; import { z } from 'zod'; -import { env } from '@env'; -import { InputRegisterUserAdminDTO, InputRegisterUserDTO } from '@modules/auth/dto/input.dto'; -import { generateRandomPassword, isStrongPassword } from '@modules/base/decorators'; -import { OutputCreatedDTO, OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { EmailsService } from '@modules/emails/emails.service'; -import { OutputPermissionDTO } from '@modules/permissions/dto/output.dto'; -import { RoleExpiration } from '@modules/roles/entities/role-expiration.entity'; -import { UserVisibility } from '@modules/users/entities/user-visibility.entity'; -import { User } from '@modules/users/entities/user.entity'; -import { checkBirthDate } from '@utils/dates'; -import { getTemplate } from '@utils/template'; +import { env } from '~/env'; +import { InputRegisterUserAdminDTO, InputRegisterUserDTO } from '~/modules/auth/dto/input.dto'; +import { generateRandomPassword, isStrongPassword } from '~/modules/base/decorators'; +import { OutputCreatedDTO, OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { EmailsService } from '~/modules/emails/emails.service'; +import { OutputPermissionDTO } from '~/modules/permissions/dto/output.dto'; +import { RoleExpiration } from '~/modules/roles/entities/role-expiration.entity'; +import { UserVisibility } from '~/modules/users/entities/user-visibility.entity'; +import { User } from '~/modules/users/entities/user.entity'; +import { checkBirthDate } from '~/utils/dates'; +import { getTemplate } from '~/utils/template'; import { InputUpdateUserDTO, InputUpdateUserVisibilityDTO } from '../dto/input.dto'; import { OutputUserDTO, OutputBaseUserDTO, OutputUserRoleDTO, OutputUserVisibilityDTO } from '../dto/output.dto'; diff --git a/src/modules/users/services/users-files.service.ts b/src/modules/users/services/users-files.service.ts index 87444623..a20f82c2 100644 --- a/src/modules/users/services/users-files.service.ts +++ b/src/modules/users/services/users-files.service.ts @@ -3,10 +3,10 @@ import { join } from 'path'; import { MikroORM, CreateRequestContext } from '@mikro-orm/core'; import { Injectable } from '@nestjs/common'; -import { env } from '@env'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { ImagesService } from '@modules/files/images.service'; +import { env } from '~/env'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { ImagesService } from '~/modules/files/images.service'; import { UsersDataService } from './users-data.service'; import { OutputUserBannerDTO, OutputUserPictureDTO } from '../dto/output.dto'; diff --git a/src/modules/users/users.module.ts b/src/modules/users/users.module.ts index 0f1e3b57..e8b3bedf 100644 --- a/src/modules/users/users.module.ts +++ b/src/modules/users/users.module.ts @@ -2,12 +2,12 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { AuthService } from '@modules/auth/auth.service'; -import { EmailsService } from '@modules/emails/emails.service'; -import { FilesService } from '@modules/files/files.service'; -import { ImagesService } from '@modules/files/images.service'; -import { UserVisibility } from '@modules/users/entities/user-visibility.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { AuthService } from '~/modules/auth/auth.service'; +import { EmailsService } from '~/modules/emails/emails.service'; +import { FilesService } from '~/modules/files/files.service'; +import { ImagesService } from '~/modules/files/images.service'; +import { UserVisibility } from '~/modules/users/entities/user-visibility.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { UsersDataController } from './controllers/users-data.controller'; import { UsersFilesController } from './controllers/users-files.controller'; diff --git a/src/types/exported/constants/genders.ts b/src/types/exported/constants/genders.ts new file mode 100644 index 00000000..7162c7d2 --- /dev/null +++ b/src/types/exported/constants/genders.ts @@ -0,0 +1,2 @@ +/* istanbul ignore file */ +export const USER_GENDER = ['OTHER', 'MALE', 'FEMALE'] as const; diff --git a/src/types/exported/constants/perms.ts b/src/types/exported/constants/perms.ts new file mode 100644 index 00000000..6c2497b9 --- /dev/null +++ b/src/types/exported/constants/perms.ts @@ -0,0 +1,87 @@ +/* istanbul ignore file */ +import type { PERMISSION_NAMES } from '../index'; + +/** + * This file contains all the permissions available in the API. + *! Please note that permissions are not stored in the database, they are hardcoded. + */ +export const PERMISSIONS = [ + { + name: 'ROOT', + description: 'As access to everything', + }, + + // LOGS + { + name: 'CAN_READ_LOGS_OF_USER', + description: 'Can read logs of users', + }, + { + name: 'CAN_DELETE_LOGS_OF_USER', + description: 'Can delete logs of users', + }, + + // PERMISSIONS + { + name: 'CAN_EDIT_PERMISSIONS_OF_USER', + description: 'Can assign/remove permissions of users', + }, + { + name: 'CAN_EDIT_PERMISSIONS_OF_ROLE', + description: 'Can assign/remove permissions of existing roles', + }, + { + name: 'CAN_READ_PERMISSIONS_OF_USER', + description: 'Can read permissions users', + }, + { + name: 'CAN_READ_PERMISSIONS_OF_ROLE', + description: 'Can read permissions roles', + }, + + // ROLES + { + name: 'CAN_EDIT_ROLE', + description: 'Can edit/create roles', + }, + { + name: 'CAN_READ_ROLE', + description: 'Can read all roles that exist', + }, + + // USERS + { + name: 'CAN_EDIT_USER', + description: 'Can create a new user or edit an existing one', + }, + { + name: 'CAN_DELETE_USER', + description: 'Can delete users', + }, + { + name: 'CAN_READ_USER', + description: 'Can read filtered information of users', + }, + { + name: 'CAN_READ_USER_PRIVATE', + description: 'Can read all information of users', + }, + + // PROMOTIONS + { + name: 'CAN_READ_PROMOTION', + description: "Can read a promotion's information", + }, + { + name: 'CAN_EDIT_PROMOTION', + description: 'Can edit a promotion (name, description, etc.)', + }, + + // FILES + { + name: 'CAN_READ_FILE', + description: 'Can read any file', + }, +] as const; + +export const PERMISSIONS_NAMES: PERMISSION_NAMES[] = PERMISSIONS.map((p) => p.name); diff --git a/src/types/exported/dtos/auth.d.ts b/src/types/exported/dtos/auth.d.ts new file mode 100644 index 00000000..1da8223f --- /dev/null +++ b/src/types/exported/dtos/auth.d.ts @@ -0,0 +1,17 @@ +import type { email } from '../index'; + +export interface InputSignInDto { + /** The user's email */ + email: email; + + /** The user's password */ + password: string; +} + +export interface OutputTokenDto { + /** The JWT Token */ + token: string; + + /** The user id */ + user_id: number; +} diff --git a/src/types/exported/dtos/files.d.ts b/src/types/exported/dtos/files.d.ts new file mode 100644 index 00000000..bd679d0a --- /dev/null +++ b/src/types/exported/dtos/files.d.ts @@ -0,0 +1,25 @@ +import { OutputBaseDto } from '.'; + +export interface OutputFileDto extends OutputBaseDto { + filename: string; + + mimetype: string; + + path: string; + + size: number; + + visibility_id?: number; + + description?: string; +} + +export interface OutputFileVisibilityGroupDto extends OutputBaseDto { + name: Uppercase; + + description: string; + + users_count: number; + + files_count: number; +} diff --git a/src/types/exported/dtos/index.d.ts b/src/types/exported/dtos/index.d.ts new file mode 100644 index 00000000..3715c448 --- /dev/null +++ b/src/types/exported/dtos/index.d.ts @@ -0,0 +1,31 @@ +export * from './auth'; +export * from './files'; +export * from './logs'; +export * from './permissions'; +export * from './promotions'; +export * from './roles'; +export * from './users'; + +export interface OutputBaseDto { + /** The entity ID */ + id: number; + + /** The entity updated date */ + updated: Date; + + /** The entity created date */ + created: Date; +} + +export interface OutputResponseDto { + /** The message */ + message: string; + + /** The status code */ + statusCode: number; +} + +export interface OutputErrorResponseDto extends OutputResponseDto { + /** The errors (if there is more than one) */ + errors: string[]; +} diff --git a/src/types/exported/dtos/logs.d.ts b/src/types/exported/dtos/logs.d.ts new file mode 100644 index 00000000..bf93ac35 --- /dev/null +++ b/src/types/exported/dtos/logs.d.ts @@ -0,0 +1,43 @@ +export interface OutputLogDto { + /** The user ID who made the action */ + user_id: number; + + /** The action made by the user */ + action: string; + + /** The ip address of the user */ + ip: string; + + /** The user agent of the user */ + user_agent: string; + + /** The route used by the user */ + route: string; + + /** The method used by the user */ + method: string; + + /** The body of the request */ + body: string; + + /** The query of the request */ + query: string; + + /** The params of the request */ + params: string; + + /** The response of the request */ + response?: string; + + /** The status code of the response */ + status_code?: number; + + /** The error of the response */ + error?: string; + + /** The error stack of the response */ + error_stack?: string; + + /** The error message of the response */ + error_message?: string; +} diff --git a/src/types/exported/dtos/permissions.d.ts b/src/types/exported/dtos/permissions.d.ts new file mode 100644 index 00000000..e5fd8e30 --- /dev/null +++ b/src/types/exported/dtos/permissions.d.ts @@ -0,0 +1,48 @@ +import { OutputBaseDto, PERMISSION_NAMES } from '../index'; + +export interface InputCreatePermissionDto { + /** The user OR role to add the permission to */ + id: number; + + /** The permission's name */ + permission: PERMISSION_NAMES; + + /** The expiration date */ + expires: Date; +} + +export interface InputUpdatePermissionDto { + /** The permission's id */ + id: number; + + /** The permission's name */ + name: PERMISSION_NAMES; + + /** The permission's expiration date */ + expires: Date; + + /** Whether the permission is revoked or not */ + revoked: boolean; +} + +export interface OutputPermissionDto extends OutputBaseDto { + /** Permission name */ + name: PERMISSION_NAMES; + + /** Whether the permission is revoked or not */ + revoked: boolean; + + /** The permission's expiration date */ + expires: Date; + + /** The user ID who has the permission */ + user_id: number; +} + +export interface OutputPermissionsOfRoleDto { + /** The Role ID */ + id: number; + + /** Permissions within the role */ + permissions: PERMISSION_NAMES[]; +} diff --git a/src/types/exported/dtos/promotions.d.ts b/src/types/exported/dtos/promotions.d.ts new file mode 100644 index 00000000..9a61dbb3 --- /dev/null +++ b/src/types/exported/dtos/promotions.d.ts @@ -0,0 +1,16 @@ +import type { OutputBaseDto, OutputFileDto } from '.'; + +export interface OutputPromotionDto extends OutputBaseDto { + /** Promotion number */ + number: number; + + /** Users in promotion */ + users_count: number; + + /** Promotion picture id */ + picture_id?: number; +} + +export interface OutputPromotionPictureDto extends OutputFileDto { + picture_promotion_id: number; +} diff --git a/src/types/exported/dtos/roles.d.ts b/src/types/exported/dtos/roles.d.ts new file mode 100644 index 00000000..0f3967a4 --- /dev/null +++ b/src/types/exported/dtos/roles.d.ts @@ -0,0 +1,51 @@ +import type { OutputBaseUserDto, PERMISSION_NAMES } from '../index'; + +export interface InputCreateRoleDto { + /** Name of the role, capitalized */ + name: Uppercase; + + /** Permissions of the role */ + permissions: PERMISSION_NAMES[]; +} + +export interface InputUpdateRoleDto extends InputCreateRoleDto { + /** ID of the role */ + id: number; +} + +export interface InputUpdateRoleUserDto { + /** ID of the user */ + id: number; + + /** Expiration date of the role for that user */ + expires: Date; +} + +export interface InputUpdateRoleUsersDto { + /** User role edition */ + users: InputUpdateRoleUserDto[]; +} + +export interface InputDeleteRoleUsersDto { + /** Users ID's */ + users: number[]; +} + +export interface OutputRoleUserDto extends OutputBaseUserDto { + /** Expiration date of the role for that user */ + role_expires: Date; +} + +export interface OutputRoleDto { + /** Role name */ + name: Uppercase; + + /** Determine wether the role is still active */ + revoked: boolean; + + /** Specify what permissions the role has */ + permissions: PERMISSION_NAMES[]; + + /** Specify to which user the role is attached */ + users_count: number; +} diff --git a/src/types/exported/dtos/users.d.ts b/src/types/exported/dtos/users.d.ts new file mode 100644 index 00000000..3d6e1055 --- /dev/null +++ b/src/types/exported/dtos/users.d.ts @@ -0,0 +1,170 @@ +import type { OutputBaseDto, OutputFileDto } from '.'; +import type { email, GENDERS, PERMISSION_NAMES } from '../index'; + +export interface InputRegisterUserAdminDto { + /** The user's email */ + email: email; + + /** The user's birth date */ + birth_date: Date; + + /** The user's first name */ + first_name: string; + + /** The user's last name */ + last_name: string; +} + +export interface InputRegisterUsersAdminDto { + users: InputRegisterUserAdminDto[]; +} + +export interface InputRegisterUserDto extends InputRegisterUserAdminDto { + /** The user's password */ + password: string; +} + +// We extends InputRegisterUserAdminDto as the password is not included as it should be updated +// with the password endpoint +export interface InputUpdateUserDto extends Partial { + /** User gender */ + gender?: GENDERS; + + /** User's pronouns */ + pronouns?: string; + + /** User's promotion ID */ + promotion?: number; + + /** User's secondary email */ + secondary_email?: email; + + /** User's phone number */ + phone?: string; + + /** User's parent contact */ + parents_phone?: string; +} + +export interface InputUpdateUsersDto { + users: InputUpdateUserDto[]; +} + +export interface OutputBaseUserDto extends OutputBaseDto { + /** User's first name */ + first_name: string; + + /** User's last name */ + last_name: string; + + /** User's nickname */ + nickname?: string; +} + +export interface OutputUserDto extends OutputBaseUserDto { + /** User full name (first name + last name) */ + full_name: string; + + /** User's profile picture ID */ + picture_id?: number; + + /** User's banner picture ID */ + banner_id?: number; + + /** User's email */ + email?: email; + + /** True if the email has been verified */ + email_verified?: boolean; + + /** True if the user is a minor */ + is_minor: boolean; + + /** User's birth date */ + birth_date?: Date; + + /** User's age */ + age: number; + + /** User gender */ + gender?: GENDERS; + + /** User's pronouns */ + pronouns?: string; + + /** User's promotion ID */ + promotion?: number; + + /** User's phone number */ + last_seen?: Date; + + /** True if the user is subscribed */ + subscribed: boolean; // TODO: (KEY: 2) Make a PR to implement subscriptions in the API + + /** User's secondary email */ + secondary_email?: email; + + /** User's phone number */ + phone?: string; + + /** User's parent contact */ + parents_phone?: string; + + /** Date of verification of the user, null if not verified */ + verified?: Date; +} + +export interface OutputUserRoleDto extends OutputBaseDto { + /** Name of the role */ + name: Uppercase; + + /** Date of expiration of the role on that user */ + expires: Date; + + /** True if the role has been revoked */ + revoked: boolean; + + /** List of permissions in that role */ + permissions: Array; +} + +export interface OutputUserVisibilityDto { + /** The User ID */ + user_id: number; + + /** User's email visibility */ + email: boolean; + + /** User's secondary email visibility */ + secondary_email: boolean; + + /** User's birth date visibility */ + birth_date: boolean; + + /** User's gender visibility */ + gender: boolean; + + /** User's pronouns visibility */ + pronouns: boolean; + + /** User's promotion visibility */ + promotion: boolean; + + /** User's phone visibility */ + phone: boolean; + + /** User's parent contact visibility */ + parents_phone: boolean; +} + +export type InputUpdateUserVisibilityDto = Omit; + +export interface OutputUserPictureDto extends OutputFileDto { + /** User owner ID */ + picture_user_id: number; +} + +export interface OutputUserBannerDto extends OutputFileDto { + /** User owner ID */ + banner_user_id: number; +} diff --git a/src/types/exported/index.d.ts b/src/types/exported/index.d.ts new file mode 100644 index 00000000..68c057e0 --- /dev/null +++ b/src/types/exported/index.d.ts @@ -0,0 +1,36 @@ +export * from './dtos'; + +import type { USER_GENDER } from './constants/genders'; +import type { PERMISSIONS } from './constants/perms'; + +export type PERMISSION_NAMES = (typeof PERMISSIONS)[number]['name']; +export type GENDERS = (typeof USER_GENDER)[number]; + +export type aspect_ratio = `${number}:${number}`; +export type base64 = `data:${string}/${string};base64,${string}`; +export type email = `${string}@${string}.${string}`; +export type imageURL = `blob:${URL}${string}`; +export type URL = `${string}://${string}.${string}`; + +export type KeysOf = Array; + +export type IsAny = unknown extends T ? ([keyof T] extends [never] ? false : true) : false; +export type PathImpl = Key extends string + ? IsAny extends true + ? never + : T[Key] extends Record + ? + | `${Key}.${PathImpl> & string}` + | `${Key}.${Exclude & string}` + : never + : never; + +export type PathImpl2 = PathImpl | keyof T; + +export type Path = keyof T extends string + ? PathImpl2 extends infer P + ? P extends string | keyof T + ? P + : keyof T + : keyof T + : never; diff --git a/src/types/i18n.d.ts b/src/types/i18n.d.ts new file mode 100644 index 00000000..0e01f755 --- /dev/null +++ b/src/types/i18n.d.ts @@ -0,0 +1,207 @@ +/* DO NOT EDIT, file generated by nestjs-i18n */ + +import { Path } from "nestjs-i18n"; +export type I18nTranslations = { + "templates": { + "common": { + "politeness": string; + "signature": string; + "questions": string; + "info": string; + }; + "email_changed": { + "subject": string; + "title": string; + "body": { + "text": string; + "link": { + "text": string; + "href": string; + }; + }; + }; + "register_common": { + "subject": string; + "title": string; + "body": { + "text": string; + }; + }; + "register_user": { + "body": { + "text": string; + "link": { + "text": string; + "href": string; + }; + "remark": string; + }; + }; + "register_user_by_admin": { + "body": { + "text": string; + "password": string; + }; + }; + }; + "validations": { + "array": { + "invalid": { + "format": string; + "duplicate": string; + "not_empty": string; + }; + }; + "boolean": { + "invalid": { + "format": string; + }; + }; + "birth_date": { + "invalid": { + "outbound": string; + }; + }; + "date": { + "invalid": { + "format": string; + }; + }; + "email": { + "invalid": { + "format": string; + "blacklisted": string; + "size": string; + "used": string; + "are_used": string; + "already_verified": string; + }; + "success": { + "verified": string; + }; + }; + "file": { + "invalid": { + "not_provided": string; + "not_found": string; + "no_mime_type": string; + "unauthorized_mime_type": string; + "infected": string; + }; + }; + "file_visibility_group": { + "invalid": { + "not_found": string; + }; + }; + "gender": { + "invalid": { + "format": string; + }; + }; + "id": { + "invalid": { + "format": string; + "min": string; + }; + }; + "ids": { + "invalid": { + "format": string; + }; + }; + "image": { + "invalid": { + "aspect_ratio": string; + }; + }; + "logs": { + "success": { + "deleted": string; + }; + }; + "number": { + "invalid": { + "format": string; + "min": string; + }; + }; + "password": { + "invalid": { + "mismatch": string; + "weak": string; + }; + }; + "permission": { + "invalid": { + "format": string; + "already_on": string; + }; + "not_found": string; + }; + "phone": { + "invalid": { + "format": string; + }; + }; + "promotion": { + "invalid": { + "not_found": string; + "no_logo": string; + }; + "success": { + "deleted_logo": string; + }; + }; + "role": { + "invalid": { + "already_exist": string; + "already_on": string; + }; + "not_found": string; + }; + "string": { + "invalid": { + "format": string; + "uppercase": string; + }; + }; + "token": { + "invalid": { + "format": string; + "expired": string; + "unknown": string; + }; + }; + "user": { + "invalid": { + "not_in_file_visibility_group": string; + }; + "success": { + "registered": string; + "deleted": string; + "deleted_picture": string; + "deleted_banner": string; + }; + "cannot_update": string; + "not_found": { + "email": string; + "id": string; + }; + "unverified": string; + "picture": { + "cooldown": string; + "not_found": string; + }; + "banner": { + "not_found": string; + }; + }; + "users": { + "not_found": { + "ids": string; + }; + }; + }; +}; +export type I18nPath = Path; diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 00000000..36b0ef32 --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,79 @@ +export * from './exported'; + +//--- Global types override for the API only ---// +import type { email } from '../../../types'; +import type { HttpStatus, RequestMethod } from '@nestjs/common'; +import type { Class, TitleCase } from 'type-fest'; + +import 'jest-extended'; + +// Exported types +export * from './exported/dtos'; +export * from './i18n'; + +export interface JWTPayload { + /** The user ID */ + sub: number; + + /** The user email */ + email: email; + + iat: number; + + /** The expiration of the token */ + exp: number; +} + +//--- Global types override for the API only ---// +declare global { + // @ts-ignore + declare namespace jest { + interface Expect { + /** + * Ensures that a value is an instance of a class. + * @param classType The class that the value is expected to be an instance of. + * + * @overload + * ```ts + * jest.Expect.any(classType: any): any; + * ``` + * + * @example + * expect("string").any(String); + */ + any(classType: Class): T; + } + + interface Describe { + ( + name: + | `${string} (e2e)` // Entity (e2e) + | `${string} (unit)` // Entity (unit) + | `.${string}()` // .method() + | `(${keyof typeof RequestMethod}) /${string}` // (GET) /routes + | StatusMessages, // 200 : Ok + fn: EmptyFunction, + ): void; + + /** @deprecated */ + (name: number | string | ((...args: unknown[]) => void) | FunctionLike, fn: EmptyFunction): void; + } + + interface It { + (name: `when ${string}` | `should ${string}`, fn?: ProvidesCallback, timeout?: number): void; + + /** @deprecated */ + (name: string, fn?: ProvidesCallback, timeout?: number): void; + } + } +} + +type ProvidesCallback = (done: unknown) => Promise | void; +type FunctionLike = (...args: unknown[]) => unknown; +type EmptyFunction = () => unknown; + +type StatusMessages_ = { + [Key in keyof typeof HttpStatus]: `${(typeof HttpStatus)[Key]} : ${TitleCase}`; +}; +type StatusMessages = StatusMessages_[keyof StatusMessages_]; +export type HttpStatusNames = TitleCase; diff --git a/src/types/lib.dom.d.ts b/src/types/lib.dom.d.ts new file mode 100644 index 00000000..9c1df60e --- /dev/null +++ b/src/types/lib.dom.d.ts @@ -0,0 +1,4 @@ +interface Storage { + getItem(key: string): T | null; + setItem(key: string, value: T): void; +} diff --git a/src/types/lib.es2015.core.d.ts b/src/types/lib.es2015.core.d.ts new file mode 100644 index 00000000..214762f4 --- /dev/null +++ b/src/types/lib.es2015.core.d.ts @@ -0,0 +1,10 @@ +/** + * Improve type definitions for Object.keys + */ +interface ObjectConstructor { + /** + * Returns the names of the enumerable string properties and methods of an object. + * @param {T} object - Object that contains the properties and methods. + */ + keys(object: T): Array; +} diff --git a/src/types/lib.es5.d.ts b/src/types/lib.es5.d.ts new file mode 100644 index 00000000..f9b5ffaf --- /dev/null +++ b/src/types/lib.es5.d.ts @@ -0,0 +1,21 @@ +/** + * Fix wrong type definitions for toLowerCase and toUpperCase methods in lib.es5.d.ts + * @see https://github.com/microsoft/TypeScript/issues/44268 + */ +interface String { + /** Converts all the alphabetic characters in a string to lowercase. */ + toLowerCase(): Lowercase; + + /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */ + toLocaleLowerCase(locales?: string | string[]): Lowercase; + + /** Converts all the alphabetic characters in a string to uppercase. */ + toUpperCase(): Uppercase; + + /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */ + toLocaleUpperCase(locales?: string | string[]): Uppercase; +} + +interface JSON { + parse(text: string, reviver?: (this: K, key: string, value: L) => unknown): T; +} diff --git a/src/types/type-fest.d.ts b/src/types/type-fest.d.ts new file mode 100644 index 00000000..f8c88b55 --- /dev/null +++ b/src/types/type-fest.d.ts @@ -0,0 +1,40 @@ +import type { Join, CamelCase } from 'type-fest'; +import type { SplitIncludingDelimiters } from 'type-fest/source/delimiter-case'; +import type { StringDigit, UpperCaseCharacters } from 'type-fest/source/internal'; + +declare module 'type-fest' { + type TitleCaseJoin = Parts extends [ + `${infer FirstPart}`, + `${infer SecondPart}`, + ...infer Rest, + ] + ? FirstPart extends StringDigit + ? `${Capitalize}${TitleCase< + Join<[SecondPart, Rest extends string[] | number[] ? Join : ''], ''> + >}` + : `${Capitalize} ${TitleCase< + Join<[SecondPart, Rest extends string[] | number[] ? Join : ''], ''> + >}` + : Parts extends [`${infer FirstPart}`, ...infer Rest] // @ts-expect-error (unknown is not assignable to string) + ? `${Capitalize}${Rest extends string ? Rest : TitleCaseJoin}` + : Parts extends [string | number] + ? Parts extends [string] + ? Capitalize + : `${Parts[0]}` + : ''; + + /** + * Converts a string literal to title case. + * @see https://github.com/sindresorhus/type-fest/pull/303 + * + * @example + * ```ts + * import type { TitleCase } from '~/types'; + * // Simple + * const someVariable: TitleCase<'thisIsASpecialProperty'> = 'This is a Special Property'; + * ``` + */ + export type TitleCase = K extends string + ? TitleCaseJoin, UpperCaseCharacters | StringDigit>> + : K; +} diff --git a/src/utils/array.ts b/src/utils/array.ts new file mode 100644 index 00000000..275770a5 --- /dev/null +++ b/src/utils/array.ts @@ -0,0 +1,91 @@ +import { randomInt } from './random'; + +export {}; + +declare global { + interface Array { + /** + * Remove specified items from the array. Removes any duplicates. + * @param {T[]} items Items to remove. + * @returns {T[]} The array without the specified items. + */ + remove(...items: T[]): T[]; + + /** + * Remove duplicate items from the array. + * @returns {T[]} The array without duplicate items. + */ + unique(): T[]; + + /** + * Shuffle the array. + * @returns {T[]} The shuffled array. + */ + shuffle(): T[]; + + /** + * Determines if the array is uniform. + * @returns {boolean} True if all elements in the array are of the same type. + * @example [].isUniform() // true + * @example [{ a: 1 }, { a: 2 }].isUniform() // true + * @example [{ a: 1 }, { a: 2, b: 'unexpected' }].isUniform() // false + */ + isUniform(): boolean; + } +} + +if (!Array.prototype.remove) { + Array.prototype.remove = function (this: T[], ...items: T[]): T[] { + items.forEach((item) => { + let index = this.indexOf(item); + + while (index !== -1) { + this.splice(index, 1); + index = this.indexOf(item); // Look for the next occurrence. + } + }); + + return this; + }; +} + +if (!Array.prototype.unique) { + Array.prototype.unique = function (this: T[]): T[] { + return this.filter((item, index) => this.indexOf(item) === index); + }; +} + +if (!Array.prototype.shuffle) { + Array.prototype.shuffle = function (this: T[]): T[] { + let currentIndex = this.length; + let randomIndex = null; + + // While there remain elements to shuffle. + while (currentIndex > 0) { + // Pick a remaining element. + randomIndex = randomInt(currentIndex - 1); + currentIndex--; + + // And swap it with the current element. + [this[currentIndex], this[randomIndex]] = [this[randomIndex], this[currentIndex]]; + } + + return this; + }; +} + +if (!Array.prototype.isUniform) { + Array.prototype.isUniform = function (this: T[]): boolean { + if (this.length === 0) return true; + const keysToHave = Object.keys(this[0]); + + for (let i = 1; i < this.length; i++) { + const keysToCheck = Object.keys(this[i]); + + if (keysToCheck.length !== keysToHave.length) return false; + if (!keysToCheck.every((key) => keysToHave.includes(key))) return false; + } + + return true; + }; +} diff --git a/src/utils/arrayBuffer.ts b/src/utils/arrayBuffer.ts new file mode 100644 index 00000000..8bfd6adc --- /dev/null +++ b/src/utils/arrayBuffer.ts @@ -0,0 +1,70 @@ +import type { base64, imageURL } from '~/types'; + +export {}; + +declare global { + interface ArrayBuffer { + /** + * Convert the ArrayBuffer to a base64 string + * @param {string} type The type of the file (@default 'image') + * @param {string} extension The extension of the file (@default 'webp') + * @returns {string} The base64 string + */ + toBase64(type?: string, extension?: string): base64; + + /** + * Convert the ArrayBuffer to a blob URL (imageURL) + * @see https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL + * + * @param type The type of the file (@default 'image') + * @param extension The extension of the file (@default 'webp') + */ + toImageURL(type?: string, extension?: string): imageURL; + + /** + * Convert the ArrayBuffer to a JSON object + * @returns {object} The JSON object + */ + toJSON(): T; + } +} + +if (!ArrayBuffer.prototype.toBase64) { + ArrayBuffer.prototype.toBase64 = function toBase64(type = 'image', extension = 'webp'): base64 { + let binary = ''; + const bytes = new Uint8Array(this); + const len = bytes.byteLength; + + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + + return `data:${type}/${extension};base64,${window.btoa(binary)}`; + }; +} + +// Not testable on NodeJS +/* istanbul ignore next */ +if (!ArrayBuffer.prototype.toImageURL) { + ArrayBuffer.prototype.toImageURL = function toImageURL(type = 'image', extension = 'webp'): imageURL { + const bytes = new Uint8Array(this); + const blob = new Blob([bytes], { type: `${type}/${extension}` }); + + const urlCreator = window.URL || window.webkitURL; + return urlCreator.createObjectURL(blob) as imageURL; + }; +} + +// Not easily testable on NodeJS +/* istanbul ignore next */ +if (!ArrayBuffer.prototype.toJSON) { + ArrayBuffer.prototype.toJSON = function toJSON(): T { + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + return JSON.parse(String.fromCharCode.apply(null, new Uint8Array(this) as unknown as number[])); + } catch (error) { + if (error instanceof SyntaxError) throw new SyntaxError('The ArrayBuffer cannot be converted to JSON'); + throw error; + } + }; +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 00000000..a08ca1e8 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,4 @@ +export * from './array'; +export * from './arrayBuffer'; +export * from './object'; +export * from './random'; diff --git a/src/utils/object.ts b/src/utils/object.ts new file mode 100644 index 00000000..82eca594 --- /dev/null +++ b/src/utils/object.ts @@ -0,0 +1,109 @@ +import type { UnionToIntersection } from 'type-fest'; +import type { Path } from '~/types'; + +export {}; + +declare global { + interface Object { + /** + * Deep merge two or more objects into the first one + * @param target The object to merge into + * @param sources The objects to merge into the target + * + * @example + * Object.merge({ a: 1, b: 2 }, { b: 3, c: 4 }) // { a: 1, b: 3, c: 4 } + * @example + * Object.merge({ a: 1, b: { c: 2, d: 3 } }, { b: { d: 4, e: 5 } }) // { a: 1, b: { c: 2, d: 4, e: 5 } } + */ + merge, U extends Record[]>( + target: T, + ...sources: U + ): T & UnionToIntersection; + + merge>(target: T): T; + merge, U extends Record[]>( + target: T, + ...sources: U + ): (T & UnionToIntersection) | T; + + /** + * Check if the given item is a JS Object + * @param {unknown} item to be tested + * @returns {boolean} true if the item is a JS Object + * + * @example + * Object.isObject({}) // true + * @example + * Object.isObject({ a: 1 }) // true + * @example + * Object.isObject({ a: 1, b: {} }) // true + * @example + * Object.isObject([]) // false + */ + isObject(item: unknown): boolean; + + /** + * Get keys of an object recursively + * @returns {Array} Recursive keys of the object + * + * @example Object.keysRecursive({ a: 1, b: { c: 2, d: 3 } }) // ['a', 'b.c', 'b.d'] + */ + keysRecursive>(target: T): Path[]; + } +} + +if (!Object.prototype.isObject) { + Object.defineProperty(Object.prototype, 'isObject', { + value: (item: unknown): boolean => { + return item !== undefined && item !== null && typeof item === 'object' && !Array.isArray(item); + }, + configurable: true, + writable: true, + }); +} + +if (!Object.prototype.merge) { + Object.defineProperty(Object.prototype, 'merge', { + value: , U extends Record[]>( + target: T, + ...sources: U + ): (T & UnionToIntersection) | T => { + if (!sources.length) return target; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const source: Record = sources.shift()!; + + if (Object.isObject(target) && Object.isObject(source)) { + for (const key in source) { + if (Object.isObject(source[key])) { + if (!(target as Record)[key]) Object.assign(target, { [key]: {} }); + + Object.merge(target[key] as Record, source[key] as Record); + } else Object.assign(target, { [key]: source[key] }); + } + } + + return Object.merge(target, ...sources); + }, + configurable: true, + writable: true, + }); +} + +if (!Object.prototype.keysRecursive) { + Object.defineProperty(Object.prototype, 'keysRecursive', { + value: >(target: T): Path[] => { + const keys: string[] = []; + + for (const key in target) { + if (Object.isObject(target[key])) { + const nestedKeys = Object.keysRecursive(target[key] as Record); + keys.push(...nestedKeys.map((nestedKey) => `${key}.${nestedKey}`)); + } else keys.push(key); + } + + return keys as Path[]; + }, + configurable: true, + writable: true, + }); +} diff --git a/src/utils/random.ts b/src/utils/random.ts new file mode 100644 index 00000000..edd53f01 --- /dev/null +++ b/src/utils/random.ts @@ -0,0 +1,24 @@ +// Crypto is a node native module, use webpack's node polyfill to use it in the browser +import * as crypto from 'crypto'; + +/** + * Safely generates a random integer between the given range. + * @param {number} max Maximum value **included** in the range @default 12 + * @param {number} min Minimum value **included** in the range @default 0 + * @returns {number} The generated integer + */ +export function randomInt(max = 12, min = 0): number { + if (max === min) return min; + if (max < min) [max, min] = [min, max]; + + const range = max - min + 1; + const byteCount = Math.ceil(Math.log2(range) / 8); // Number of bytes needed to represent the range + + let randomNumber = 0; + do { + const randomBytes = crypto.randomBytes(byteCount); + randomNumber = randomBytes.readUIntBE(0, byteCount); + } while (randomNumber >= range); + + return randomNumber + min; +} diff --git a/src/utils/template.ts b/src/utils/template.ts index ecec7506..ffc3f49b 100644 --- a/src/utils/template.ts +++ b/src/utils/template.ts @@ -4,7 +4,7 @@ import path from 'path'; import { PathImpl2 } from '@nestjs/config'; import { I18nContext, I18nService } from 'nestjs-i18n'; -import { I18nTranslations } from '#types/api'; +import { I18nTranslations } from '~/types'; export type templates = 'emails/register_user_by_admin' | 'emails/register_user' | 'emails/email_changed'; export type template_args = diff --git a/tests/database.setup.ts b/tests/database.setup.ts index 1055084b..2c612fe9 100644 --- a/tests/database.setup.ts +++ b/tests/database.setup.ts @@ -4,8 +4,8 @@ import { join } from 'path'; import { MikroORM } from '@mikro-orm/core'; import { Logger } from '@nestjs/common'; -import { TestSeeder } from '@database/seeders/tests.seeder'; -import config from '@mikro-orm.config'; +import { TestSeeder } from '~/database/seeders/tests.seeder'; +import config from '~/mikro-orm.config'; /** * This function is used to setup the database before running the tests. diff --git a/tests/e2e/auth.e2e-spec.ts b/tests/e2e/auth.e2e-spec.ts index 30ba1684..268196dc 100644 --- a/tests/e2e/auth.e2e-spec.ts +++ b/tests/e2e/auth.e2e-spec.ts @@ -1,14 +1,14 @@ -import type { email } from '#types'; +import type { email } from '~/types'; import { hashSync } from 'bcrypt'; import request from 'supertest'; -import { InputRegisterUserDTO } from '@modules/auth/dto/input.dto'; -import { generateRandomPassword } from '@modules/base/decorators'; -import { OutputCreatedDTO, OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nForbiddenException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { i18nBadRequestException } from '@modules/base/http-errors/bad-request'; -import { User } from '@modules/users/entities/user.entity'; +import { InputRegisterUserDTO } from '~/modules/auth/dto/input.dto'; +import { generateRandomPassword } from '~/modules/base/decorators'; +import { OutputCreatedDTO, OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nForbiddenException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { i18nBadRequestException } from '~/modules/base/http-errors/bad-request'; +import { User } from '~/modules/users/entities/user.entity'; import { orm, server } from '..'; diff --git a/tests/e2e/logs.e2e-spec.ts b/tests/e2e/logs.e2e-spec.ts index ca1f5c13..baec50e7 100644 --- a/tests/e2e/logs.e2e-spec.ts +++ b/tests/e2e/logs.e2e-spec.ts @@ -1,8 +1,8 @@ import request from 'supertest'; -import { OutputTokenDTO } from '@modules/auth/dto/output.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException } from '@modules/base/http-errors'; +import { OutputTokenDTO } from '~/modules/auth/dto/output.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; import { server } from '..'; diff --git a/tests/e2e/permissions.e2e-spec.ts b/tests/e2e/permissions.e2e-spec.ts index ecdeaf60..be47c79f 100644 --- a/tests/e2e/permissions.e2e-spec.ts +++ b/tests/e2e/permissions.e2e-spec.ts @@ -1,9 +1,9 @@ import request from 'supertest'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { OutputTokenDTO } from '@modules/auth/dto/output.dto'; -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; -import { Permission } from '@modules/permissions/entities/permission.entity'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { OutputTokenDTO } from '~/modules/auth/dto/output.dto'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; import { server, orm } from '..'; diff --git a/tests/e2e/promotions.e2e-spec.ts b/tests/e2e/promotions.e2e-spec.ts index a26673d0..411aecf8 100644 --- a/tests/e2e/promotions.e2e-spec.ts +++ b/tests/e2e/promotions.e2e-spec.ts @@ -3,12 +3,12 @@ import { join } from 'path'; import request from 'supertest'; -import { env } from '@env'; -import { OutputTokenDTO } from '@modules/auth/dto/output.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; -import { PromotionPicture } from '@modules/promotions/entities/promotion-picture.entity'; -import { Promotion } from '@modules/promotions/entities/promotion.entity'; +import { env } from '~/env'; +import { OutputTokenDTO } from '~/modules/auth/dto/output.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; +import { PromotionPicture } from '~/modules/promotions/entities/promotion-picture.entity'; +import { Promotion } from '~/modules/promotions/entities/promotion.entity'; import { server, orm } from '..'; diff --git a/tests/e2e/roles.e2e-spec.ts b/tests/e2e/roles.e2e-spec.ts index fae5595f..057e58c9 100644 --- a/tests/e2e/roles.e2e-spec.ts +++ b/tests/e2e/roles.e2e-spec.ts @@ -1,9 +1,9 @@ import request from 'supertest'; -import { PERMISSIONS_NAMES } from '@exported/api/constants/perms'; -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; -import { InputUpdateRoleUserDTO } from '@modules/roles/dto/input.dto'; -import { Role } from '@modules/roles/entities/role.entity'; +import { PERMISSIONS_NAMES } from '~/constants/perms'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; +import { InputUpdateRoleUserDTO } from '~/modules/roles/dto/input.dto'; +import { Role } from '~/modules/roles/entities/role.entity'; import { server, orm } from '..'; diff --git a/tests/e2e/users/users-data.e2e-spec.ts b/tests/e2e/users/users-data.e2e-spec.ts index 5f8b67f6..d4c2a17f 100644 --- a/tests/e2e/users/users-data.e2e-spec.ts +++ b/tests/e2e/users/users-data.e2e-spec.ts @@ -1,11 +1,11 @@ -import type { email } from '#types'; +import type { email } from '~/types'; import request from 'supertest'; -import { OutputTokenDTO } from '@modules/auth/dto/output.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { User } from '@modules/users/entities/user.entity'; +import { OutputTokenDTO } from '~/modules/auth/dto/output.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { User } from '~/modules/users/entities/user.entity'; import { orm, server } from '../..'; diff --git a/tests/e2e/users/users-files.e2e-spec.ts b/tests/e2e/users/users-files.e2e-spec.ts index 0566beca..d116b95e 100644 --- a/tests/e2e/users/users-files.e2e-spec.ts +++ b/tests/e2e/users/users-files.e2e-spec.ts @@ -3,13 +3,13 @@ import { join } from 'path'; import request from 'supertest'; -import { OutputTokenDTO } from '@modules/auth/dto/output.dto'; -import { OutputMessageDTO } from '@modules/base/dto/output.dto'; -import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '@modules/base/http-errors'; -import { FileVisibilityGroup } from '@modules/files/entities/file-visibility.entity'; -import { UserBanner } from '@modules/users/entities/user-banner.entity'; -import { UserPicture } from '@modules/users/entities/user-picture.entity'; -import { User } from '@modules/users/entities/user.entity'; +import { OutputTokenDTO } from '~/modules/auth/dto/output.dto'; +import { OutputMessageDTO } from '~/modules/base/dto/output.dto'; +import { i18nBadRequestException, i18nNotFoundException, i18nUnauthorizedException } from '~/modules/base/http-errors'; +import { FileVisibilityGroup } from '~/modules/files/entities/file-visibility.entity'; +import { UserBanner } from '~/modules/users/entities/user-banner.entity'; +import { UserPicture } from '~/modules/users/entities/user-picture.entity'; +import { User } from '~/modules/users/entities/user.entity'; import { orm, server } from '../..'; diff --git a/tests/index.ts b/tests/index.ts index e65c81e3..04907e1b 100644 --- a/tests/index.ts +++ b/tests/index.ts @@ -1,7 +1,7 @@ /* istanbul ignore file */ import 'tsconfig-paths/register'; -import '@exported/global/utils'; +import '~/utils'; import { MikroORM } from '@mikro-orm/core'; import { JwtService } from '@nestjs/jwt'; @@ -9,9 +9,9 @@ import { NestExpressApplication } from '@nestjs/platform-express'; import { TestingModule, Test } from '@nestjs/testing'; import { I18nContext, I18nService, I18nValidationExceptionFilter, I18nValidationPipe } from 'nestjs-i18n'; -import { AppModule } from '@app.module'; -import { VALIDATION_PIPE_OPTIONS } from '@env'; -import { I18nHttpExceptionFilter } from '@modules/base/http-errors'; +import { AppModule } from '~/app.module'; +import { VALIDATION_PIPE_OPTIONS } from '~/env'; +import { I18nHttpExceptionFilter } from '~/modules/base/http-errors'; let module_fixture: TestingModule; let jwt: JwtService; diff --git a/tests/units/services/auth.test.ts b/tests/units/services/auth.test.ts index 4045b41e..9164c746 100644 --- a/tests/units/services/auth.test.ts +++ b/tests/units/services/auth.test.ts @@ -1,6 +1,6 @@ -import { env } from '@env'; -import { AuthService } from '@modules/auth/auth.service'; -import { i18nUnauthorizedException } from '@modules/base/http-errors'; +import { env } from '~/env'; +import { AuthService } from '~/modules/auth/auth.service'; +import { i18nUnauthorizedException } from '~/modules/base/http-errors'; import { module_fixture, jwt } from '../..'; diff --git a/tests/units/services/files.test.ts b/tests/units/services/files.test.ts index aa0e5bf0..79d2daca 100644 --- a/tests/units/services/files.test.ts +++ b/tests/units/services/files.test.ts @@ -1,7 +1,7 @@ -import { i18nBadRequestException, i18nNotFoundException } from '@modules/base/http-errors'; -import { FilesService } from '@modules/files/files.service'; -import { PromotionPicture } from '@modules/promotions/entities/promotion-picture.entity'; -import { Promotion } from '@modules/promotions/entities/promotion.entity'; +import { i18nBadRequestException, i18nNotFoundException } from '~/modules/base/http-errors'; +import { FilesService } from '~/modules/files/files.service'; +import { PromotionPicture } from '~/modules/promotions/entities/promotion-picture.entity'; +import { Promotion } from '~/modules/promotions/entities/promotion.entity'; import { orm, module_fixture } from '../..'; diff --git a/tests/units/services/images.test.ts b/tests/units/services/images.test.ts index d9a2bada..1a03b835 100644 --- a/tests/units/services/images.test.ts +++ b/tests/units/services/images.test.ts @@ -1,5 +1,5 @@ -import { i18nBadRequestException } from '@modules/base/http-errors'; -import { ImagesService } from '@modules/files/images.service'; +import { i18nBadRequestException } from '~/modules/base/http-errors'; +import { ImagesService } from '~/modules/files/images.service'; import { module_fixture } from '../..'; diff --git a/tests/units/services/logs.test.ts b/tests/units/services/logs.test.ts index 33bbf936..7ea0dc75 100644 --- a/tests/units/services/logs.test.ts +++ b/tests/units/services/logs.test.ts @@ -1,6 +1,6 @@ -import { Log } from '@modules/logs/entities/log.entity'; -import { LogsService } from '@modules/logs/logs.service'; -import { User } from '@modules/users/entities/user.entity'; +import { Log } from '~/modules/logs/entities/log.entity'; +import { LogsService } from '~/modules/logs/logs.service'; +import { User } from '~/modules/users/entities/user.entity'; import { module_fixture, orm } from '../..'; diff --git a/tests/units/services/permissions.test.ts b/tests/units/services/permissions.test.ts index d82fcd38..0ab1d682 100644 --- a/tests/units/services/permissions.test.ts +++ b/tests/units/services/permissions.test.ts @@ -1,6 +1,6 @@ -import { Permission } from '@modules/permissions/entities/permission.entity'; -import { PermissionsService } from '@modules/permissions/permissions.service'; -import { User } from '@modules/users/entities/user.entity'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; +import { PermissionsService } from '~/modules/permissions/permissions.service'; +import { User } from '~/modules/users/entities/user.entity'; import { module_fixture, orm } from '../..'; diff --git a/tests/units/services/promotions.test.ts b/tests/units/services/promotions.test.ts index f308c487..7c898324 100644 --- a/tests/units/services/promotions.test.ts +++ b/tests/units/services/promotions.test.ts @@ -1,5 +1,5 @@ -import { Promotion } from '@modules/promotions/entities/promotion.entity'; -import { PromotionsService } from '@modules/promotions/promotions.service'; +import { Promotion } from '~/modules/promotions/entities/promotion.entity'; +import { PromotionsService } from '~/modules/promotions/promotions.service'; import { module_fixture, orm } from '../..'; diff --git a/tests/units/services/roles.test.ts b/tests/units/services/roles.test.ts index ea32b051..56ee94a1 100644 --- a/tests/units/services/roles.test.ts +++ b/tests/units/services/roles.test.ts @@ -1,7 +1,7 @@ -import { RoleExpiration } from '@modules/roles/entities/role-expiration.entity'; -import { Role } from '@modules/roles/entities/role.entity'; -import { RolesService } from '@modules/roles/roles.service'; -import { User } from '@modules/users/entities/user.entity'; +import { RoleExpiration } from '~/modules/roles/entities/role-expiration.entity'; +import { Role } from '~/modules/roles/entities/role.entity'; +import { RolesService } from '~/modules/roles/roles.service'; +import { User } from '~/modules/users/entities/user.entity'; import { module_fixture, orm } from '../..'; diff --git a/tests/units/services/users/users-data.test.ts b/tests/units/services/users/users-data.test.ts index e9e87094..643142d9 100644 --- a/tests/units/services/users/users-data.test.ts +++ b/tests/units/services/users/users-data.test.ts @@ -1,10 +1,10 @@ import { hashSync } from 'bcrypt'; -import { i18nNotFoundException } from '@modules/base/http-errors'; -import { Permission } from '@modules/permissions/entities/permission.entity'; -import { Role } from '@modules/roles/entities/role.entity'; -import { User } from '@modules/users/entities/user.entity'; -import { UsersDataService } from '@modules/users/services/users-data.service'; +import { i18nNotFoundException } from '~/modules/base/http-errors'; +import { Permission } from '~/modules/permissions/entities/permission.entity'; +import { Role } from '~/modules/roles/entities/role.entity'; +import { User } from '~/modules/users/entities/user.entity'; +import { UsersDataService } from '~/modules/users/services/users-data.service'; import { module_fixture, orm } from '../../..'; diff --git a/tests/units/utils/array.test.ts b/tests/units/utils/array.test.ts new file mode 100644 index 00000000..ebf2ac1f --- /dev/null +++ b/tests/units/utils/array.test.ts @@ -0,0 +1,54 @@ +import '~/utils'; + +describe('Array (unit)', () => { + describe('.remove()', () => { + it('should remove the specified items from the array', () => { + const array = [1, 2, 3, 4, 5]; + expect(array.remove(1, 2, 3)).toEqual([4, 5]); + }); + + it('should not remove anything if the specified items are not in the array', () => { + const array = [1, 2, 3, 4, 5]; + expect(array.remove(6, 7, 8)).toEqual([1, 2, 3, 4, 5]); + expect([].remove(1, 2, 3)).toEqual([]); + }); + + it('should remove any duplicates', () => { + const array = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]; + expect(array.remove(1, 2, 3)).toEqual([4, 5, 4, 5]); + }); + }); + + describe('.unique()', () => { + it('should remove any duplicates', () => { + const array = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]; + expect(array.unique()).toEqual([1, 2, 3, 4, 5]); + }); + + it('should not remove anything if there are no duplicates', () => { + const array = [1, 2, 3, 4, 5]; + expect(array.unique()).toEqual([1, 2, 3, 4, 5]); + }); + + it('should return an empty array if the input array is empty', () => { + expect([].unique()).toEqual([]); + }); + }); + + describe('.isUniform()', () => { + it('should return true if all objects in the array have the same type', () => { + expect([].isUniform()).toBe(true); + expect([{ a: 1 }, { a: 2 }].isUniform()).toBe(true); + }); + + it('should return false if not all objects in the array have the same type', () => { + expect([{ a: 1 }, { a: 2, b: 'unexpected' }].isUniform()).toBe(false); + expect( + [ + { a: 1, c: 2 }, + { a: 3, b: 'unexpected' }, + ].isUniform(), + ).toBe(false); + }); + }); +}); diff --git a/tests/units/utils/arrayBuffer.test.ts b/tests/units/utils/arrayBuffer.test.ts new file mode 100644 index 00000000..8593d40c --- /dev/null +++ b/tests/units/utils/arrayBuffer.test.ts @@ -0,0 +1,18 @@ +/** @jest-environment jsdom */ +import '~/utils'; + +describe('ArrayBuffer (unit)', () => { + describe('.toBase64()', () => { + it('should return a base64 string', () => { + const arrayBuffer = new ArrayBuffer(16); + + const view = new Uint8Array(arrayBuffer); + for (let i = 0; i < view.length; i++) { + view[i] = i; + } + + expect(arrayBuffer.toBase64()).toBe('data:image/webp;base64,AAECAwQFBgcICQoLDA0ODw=='); + expect(arrayBuffer.toBase64('image', 'png')).toBe('data:image/png;base64,AAECAwQFBgcICQoLDA0ODw=='); + }); + }); +}); diff --git a/tests/units/utils/dates.test.ts b/tests/units/utils/dates.test.ts index 3daa9bd8..bce9c902 100644 --- a/tests/units/utils/dates.test.ts +++ b/tests/units/utils/dates.test.ts @@ -1,4 +1,4 @@ -import { checkBirthDate } from '@utils/dates'; +import { checkBirthDate } from '~/utils/dates'; describe('.checkBirthDate()', () => { it('should return true if the date is more than 13 years old', () => { diff --git a/tests/units/utils/object.test.ts b/tests/units/utils/object.test.ts new file mode 100644 index 00000000..0642caad --- /dev/null +++ b/tests/units/utils/object.test.ts @@ -0,0 +1,36 @@ +import '~/utils'; + +describe('Object (unit)', () => { + describe('.isObject()', () => { + it('should return true if the given item is a JS Object', () => { + expect(Object.isObject({})).toBe(true); + expect(Object.isObject({ a: 1 })).toBe(true); + expect(Object.isObject({ a: 1, b: {} })).toBe(true); + }); + + it('should return false if the given item is not a JS Object', () => { + expect(Object.isObject([])).toBe(false); + expect(Object.isObject('')).toBe(false); + expect(Object.isObject(1)).toBe(false); + expect(Object.isObject(true)).toBe(false); + expect(Object.isObject(null)).toBe(false); + expect(Object.isObject(undefined)).toBe(false); + }); + }); + + describe('.merge()', () => { + it('should merge two or more objects into the first one', () => { + expect(Object.merge({ a: 1, b: 2 }, { b: 3, c: { d: 1 } })).toEqual({ a: 1, b: 3, c: { d: 1 } }); + expect(Object.merge({}, { a: 1 })).toEqual({ a: 1 }); + expect(Object.merge({ a: 1 }, {})).toEqual({ a: 1 }); + expect(Object.merge({ a: true }, { b: '2' }, { c: 3 })).toEqual({ a: true, b: '2', c: 3 }); + }); + }); + + describe('.keysRecursive()', () => { + it('should return all the keys of an object and its nested objects', () => { + const obj = { a: 1, b: { c: 2, d: { e: 3 } } }; + expect(Object.keysRecursive(obj)).toEqual(['a', 'b.c', 'b.d.e']); + }); + }); +}); diff --git a/tests/units/utils/password.test.ts b/tests/units/utils/password.test.ts index 0fd20e76..a557cc16 100644 --- a/tests/units/utils/password.test.ts +++ b/tests/units/utils/password.test.ts @@ -1,4 +1,4 @@ -import { generateRandomPassword } from '@modules/base/decorators/is-strong-pass.decorator'; +import { generateRandomPassword } from '~/modules/base/decorators/is-strong-pass.decorator'; describe('Password (unit)', () => { describe('.generateRandomPassword()', () => { diff --git a/tests/units/utils/random.test.ts b/tests/units/utils/random.test.ts new file mode 100644 index 00000000..2cb22d93 --- /dev/null +++ b/tests/units/utils/random.test.ts @@ -0,0 +1,23 @@ +import { randomInt } from '~/utils'; + +describe('.randomInt()', () => { + it('should generate a random integer between the given range', () => { + expect(randomInt(0, 0)).toBe(0); + + for (let i = 0; i < 24; i++) { + const n = randomInt(24, i); + expect(n).toBeGreaterThanOrEqual(i); + expect(n).toBeLessThanOrEqual(24); + } + + for (let i = 0; i < 24; i++) { + const n = randomInt(); + expect(n).toBeGreaterThanOrEqual(0); + expect(n).toBeLessThanOrEqual(12); + } + + const swapped = randomInt(0, 10); + expect(swapped).toBeGreaterThanOrEqual(0); + expect(swapped).toBeLessThanOrEqual(10); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index da7cbea8..0c145e8e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,13 +25,13 @@ "noPropertyAccessFromIndexSignature": true, "outDir": "./dist", "paths": { - "#types/api": [ - "src/exported/api/@types/index.d.ts" + "~/types": [ + "src/types" ], - "#types": [ - "src/exported/global/@types/index.d.ts" + "~/constants/*": [ + "src/types/exported/constants/*" ], - "@*": [ + "~*": [ "src/*" ] }, @@ -43,8 +43,7 @@ "strictNullChecks": false, "target": "ESNext", "typeRoots": [ - "src/exported/global/@types", - "src/exported/api/@types", + "src/types", "node_modules/@types" ], "useDefineForClassFields": false