From daae8123e87b54e5771f5388e5f4ed0420d73405 Mon Sep 17 00:00:00 2001 From: maxonchickdev Date: Tue, 5 May 2026 19:08:33 +0300 Subject: [PATCH 1/3] fix(root): remove dev branch from push triggers and update workspace paths for type checking --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a02a682..d53560d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,6 @@ on: push: branches: - main - - dev workflow_dispatch: workflow_call: @@ -47,9 +46,9 @@ jobs: - name: Typecheck workspaces run: | - npm run lint:types:check -w packages/shared --if-present - npm run lint:types:check -w apps/web --if-present - npm run lint:types:check -w apps/backend --if-present + npm run lint:types:check -w @nodejs-monorepo/shared --if-present + npm run lint:types:check -w @nodejs-monorepo/web --if-present + npm run lint:types:check -w @nodejs-monorepo/backend --if-present - name: Build workspaces run: | From ee088ef6dcffaaee95d3da96d649a5cf23808b1e Mon Sep 17 00:00:00 2001 From: maxonchickdev Date: Wed, 6 May 2026 20:33:27 +0300 Subject: [PATCH 2/3] refactor(root): rename constants and types for consistency and clarity --- .../common/constants/config-key.constant.ts | 2 +- .../common/constants/environments.constant.ts | 2 +- .../common/decorators/user-id.decorator.ts | 2 +- .../common/filters/catch-everything.filter.ts | 21 +++++++------- .../common/interceptors/logger.interceptor.ts | 13 ++++----- .../interceptors/timeout.interceptor.ts | 6 ++-- .../src/common/strategies/jwt.strategy.ts | 6 ++-- .../src/common/types/error-response.type.ts | 6 ++-- apps/backend/src/core/config/config.module.ts | 28 +++++++----------- .../src/core/config/registers/app.register.ts | 6 ++-- .../core/config/registers/cache.register.ts | 15 ++++++++++ .../config/registers/database.register.ts | 15 ++++++++++ .../config/registers/environment.register.ts | 10 +++---- .../src/core/config/registers/jwt.register.ts | 6 ++-- .../core/config/registers/prisma.register.ts | 18 ------------ .../config/registers/rate-limit.register.ts | 29 +++++++++---------- .../core/config/registers/redis.register.ts | 18 ------------ .../src/core/config/registers/s3.register.ts | 6 ++-- .../backend/src/core/config/types/app.type.ts | 4 +-- .../src/core/config/types/cache.type.ts | 5 ++++ .../src/core/config/types/database.type.ts | 5 ++++ .../src/core/config/types/environment.type.ts | 4 +-- .../backend/src/core/config/types/jwt.type.ts | 4 +-- .../src/core/config/types/prisma.type.ts | 5 ---- .../src/core/config/types/rate-limit.type.ts | 4 +-- .../src/core/config/types/redis.type.ts | 5 ---- apps/backend/src/core/config/types/s3.type.ts | 4 +-- .../src/core/database/database.module.ts | 10 +++++++ .../database.service.ts} | 10 +++---- .../health-checks/health-checks.module.ts | 4 +-- .../health-checks/health-checks.service.ts | 4 +-- apps/backend/src/core/jwt/jwt.module.ts | 8 ++--- apps/backend/src/core/prisma/prisma.module.ts | 10 ------- .../src/core/rate-limit/rate-limit.module.ts | 8 ++--- apps/backend/src/core/redis/redis.module.ts | 8 ++--- apps/backend/src/core/s3/s3.service.ts | 6 ++-- apps/backend/src/main.ts | 22 ++++++-------- .../src/modules/auth/auth.controller.ts | 4 +-- apps/backend/src/modules/auth/auth.module.ts | 4 +-- .../src/modules/auth/auth.repository.ts | 4 +-- apps/backend/src/modules/auth/auth.service.ts | 6 ++-- 41 files changed, 164 insertions(+), 193 deletions(-) create mode 100644 apps/backend/src/core/config/registers/cache.register.ts create mode 100644 apps/backend/src/core/config/registers/database.register.ts delete mode 100644 apps/backend/src/core/config/registers/prisma.register.ts delete mode 100644 apps/backend/src/core/config/registers/redis.register.ts create mode 100644 apps/backend/src/core/config/types/cache.type.ts create mode 100644 apps/backend/src/core/config/types/database.type.ts delete mode 100644 apps/backend/src/core/config/types/prisma.type.ts delete mode 100644 apps/backend/src/core/config/types/redis.type.ts create mode 100644 apps/backend/src/core/database/database.module.ts rename apps/backend/src/core/{prisma/prisma.service.ts => database/database.service.ts} (71%) delete mode 100644 apps/backend/src/core/prisma/prisma.module.ts diff --git a/apps/backend/src/common/constants/config-key.constant.ts b/apps/backend/src/common/constants/config-key.constant.ts index 0cdf669..61d7caa 100644 --- a/apps/backend/src/common/constants/config-key.constant.ts +++ b/apps/backend/src/common/constants/config-key.constant.ts @@ -1,4 +1,4 @@ -export const ConfigKeyConstant = { +export const CONFIG_KEY = { redis: "redis", app: "app", environment: "environment", diff --git a/apps/backend/src/common/constants/environments.constant.ts b/apps/backend/src/common/constants/environments.constant.ts index 96d3e41..3d80902 100644 --- a/apps/backend/src/common/constants/environments.constant.ts +++ b/apps/backend/src/common/constants/environments.constant.ts @@ -1,4 +1,4 @@ -export const EnvironmentsConstant = { +export const ENVIRONMENTS = { local: "local", staging: "staging", production: "production", diff --git a/apps/backend/src/common/decorators/user-id.decorator.ts b/apps/backend/src/common/decorators/user-id.decorator.ts index 491409c..84740f6 100644 --- a/apps/backend/src/common/decorators/user-id.decorator.ts +++ b/apps/backend/src/common/decorators/user-id.decorator.ts @@ -1,7 +1,7 @@ import { createParamDecorator, type ExecutionContext } from "@nestjs/common"; import type { Request } from "express"; -export const UserIdDecorator = createParamDecorator( +export const UserId = createParamDecorator( (_data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; diff --git a/apps/backend/src/common/filters/catch-everything.filter.ts b/apps/backend/src/common/filters/catch-everything.filter.ts index 8ca2ffd..309db2b 100644 --- a/apps/backend/src/common/filters/catch-everything.filter.ts +++ b/apps/backend/src/common/filters/catch-everything.filter.ts @@ -11,12 +11,12 @@ import { import { ConfigService } from "@nestjs/config"; import { HttpAdapterHost } from "@nestjs/core"; import type { Prisma } from "@prisma/generated/client.js"; -import type { EnvironmentType } from "../../core/config/types/environment.type.js"; -import { ConfigKeyConstant } from "../constants/config-key.constant.js"; -import { EnvironmentsConstant } from "../constants/environments.constant.js"; +import type { Environment } from "../../core/config/types/environment.type.js"; +import { CONFIG_KEY } from "../constants/config-key.constant.js"; +import { ENVIRONMENTS } from "../constants/environments.constant.js"; import type { - ErrorResponseBodyType, - HttpExceptionResponseType, + ErrorResponseBody, + HttpExceptionResponse, } from "../types/error-response.type.js"; const PRISMA_ERROR_MAP: Record = { @@ -40,12 +40,11 @@ export class CatchEverythingFilter implements ExceptionFilter { @Inject(HttpAdapterHost) private readonly httpAdapterHost: HttpAdapterHost, @Inject(ConfigService) readonly configService: ConfigService, ) { - const environmentConfig = configService.getOrThrow( - ConfigKeyConstant.environment, + const environmentConfig = configService.getOrThrow( + CONFIG_KEY.environment, ); - this.isProduction = - environmentConfig.nodeEnv === EnvironmentsConstant.production; + this.isProduction = environmentConfig.nodeEnv === ENVIRONMENTS.production; } catch(exception: unknown, host: ArgumentsHost): void { @@ -55,7 +54,7 @@ export class CatchEverythingFilter implements ExceptionFilter { const { statusCode, error, message } = this.normalizeException(exception); - const responseBody: ErrorResponseBodyType = { + const responseBody: ErrorResponseBody = { error, message, path: httpAdapter.getRequestUrl(request), @@ -99,7 +98,7 @@ export class CatchEverythingFilter implements ExceptionFilter { message: string | string[]; } { const statusCode = exception.getStatus(); - const response = exception.getResponse() as HttpExceptionResponseType; + const response = exception.getResponse() as HttpExceptionResponse; if (typeof response === "string") { return { diff --git a/apps/backend/src/common/interceptors/logger.interceptor.ts b/apps/backend/src/common/interceptors/logger.interceptor.ts index d637927..91f4a2d 100644 --- a/apps/backend/src/common/interceptors/logger.interceptor.ts +++ b/apps/backend/src/common/interceptors/logger.interceptor.ts @@ -10,9 +10,9 @@ import { import { ConfigService } from "@nestjs/config"; import type { Request, Response } from "express"; import { type Observable, tap } from "rxjs"; -import type { EnvironmentType } from "../../core/config/types/environment.type.js"; -import { ConfigKeyConstant } from "../constants/config-key.constant.js"; -import { EnvironmentsConstant } from "../constants/environments.constant.js"; +import type { Environment } from "../../core/config/types/environment.type.js"; +import { CONFIG_KEY } from "../constants/config-key.constant.js"; +import { ENVIRONMENTS } from "../constants/environments.constant.js"; type LoggerExpressionType = "incoming" | "error" | "success"; @@ -22,12 +22,11 @@ export class LoggingInterceptor implements NestInterceptor { private readonly isProduction: boolean; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const environmentConfig = configService.getOrThrow( - ConfigKeyConstant.environment, + const environmentConfig = configService.getOrThrow( + CONFIG_KEY.environment, ); - this.isProduction = - environmentConfig.nodeEnv === EnvironmentsConstant.production; + this.isProduction = environmentConfig.nodeEnv === ENVIRONMENTS.production; } intercept(context: ExecutionContext, next: CallHandler): Observable { diff --git a/apps/backend/src/common/interceptors/timeout.interceptor.ts b/apps/backend/src/common/interceptors/timeout.interceptor.ts index e1ac6a5..76a7714 100644 --- a/apps/backend/src/common/interceptors/timeout.interceptor.ts +++ b/apps/backend/src/common/interceptors/timeout.interceptor.ts @@ -14,15 +14,15 @@ import { throwError, timeout, } from "rxjs"; -import type { AppType } from "../../core/config/types/app.type.js"; -import { ConfigKeyConstant } from "../constants/config-key.constant.js"; +import type { App } from "../../core/config/types/app.type.js"; +import { CONFIG_KEY } from "../constants/config-key.constant.js"; @Injectable() export class TimeoutInterceptor implements NestInterceptor { private readonly appRequestTimeout: number; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const appConfig = configService.getOrThrow(ConfigKeyConstant.app); + const appConfig = configService.getOrThrow(CONFIG_KEY.app); this.appRequestTimeout = appConfig.appRequestTimeout; } diff --git a/apps/backend/src/common/strategies/jwt.strategy.ts b/apps/backend/src/common/strategies/jwt.strategy.ts index a12fdec..b464a99 100644 --- a/apps/backend/src/common/strategies/jwt.strategy.ts +++ b/apps/backend/src/common/strategies/jwt.strategy.ts @@ -2,9 +2,9 @@ import { Inject, Injectable, UnauthorizedException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { PassportStrategy } from "@nestjs/passport"; import { ExtractJwt, Strategy } from "passport-jwt"; -import type { JwtType } from "../../core/config/types/jwt.type.js"; +import type { Jwt } from "../../core/config/types/jwt.type.js"; import { AuthRepository } from "../../modules/auth/auth.repository.js"; -import { ConfigKeyConstant } from "../constants/config-key.constant.js"; +import { CONFIG_KEY } from "../constants/config-key.constant.js"; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy, "jwt") { @@ -12,7 +12,7 @@ export class JwtStrategy extends PassportStrategy(Strategy, "jwt") { @Inject(AuthRepository) private readonly authRepository: AuthRepository, @Inject(ConfigService) readonly configService: ConfigService, ) { - const jwtConfig = configService.getOrThrow(ConfigKeyConstant.jwt); + const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); super({ ignoreExpiration: false, diff --git a/apps/backend/src/common/types/error-response.type.ts b/apps/backend/src/common/types/error-response.type.ts index 5b6ea6f..db2d08e 100644 --- a/apps/backend/src/common/types/error-response.type.ts +++ b/apps/backend/src/common/types/error-response.type.ts @@ -1,4 +1,4 @@ -type ErrorResponseBodyType = { +type ErrorResponseBody = { statusCode: number; error: string; message: string | string[]; @@ -6,8 +6,8 @@ type ErrorResponseBodyType = { timestamp?: string; }; -type HttpExceptionResponseType = +type HttpExceptionResponse = | string | { message?: string | string[]; error?: string; statusCode?: number }; -export type { ErrorResponseBodyType, HttpExceptionResponseType }; +export type { ErrorResponseBody, HttpExceptionResponse }; diff --git a/apps/backend/src/core/config/config.module.ts b/apps/backend/src/core/config/config.module.ts index badf07e..adc3fc9 100644 --- a/apps/backend/src/core/config/config.module.ts +++ b/apps/backend/src/core/config/config.module.ts @@ -4,14 +4,14 @@ import { resolve } from "node:path"; import { Module } from "@nestjs/common"; import { ConfigModule as CoreConfigModule } from "@nestjs/config"; import Joi from "joi"; -import { EnvironmentsConstant } from "../../common/constants/environments.constant"; -import { appRegister } from "./registers/app.register"; -import { environmentRegister } from "./registers/environment.register"; -import { jwtRegister } from "./registers/jwt.register"; -import { prismaRegister } from "./registers/prisma.register"; -import { rateLimitRegister } from "./registers/rate-limit.register"; -import { redisRegister } from "./registers/redis.register"; -import { s3Register } from "./registers/s3.register"; +import { ENVIRONMENTS } from "../../common/constants/environments.constant"; +import { app } from "./registers/app.register"; +import { cache } from "./registers/cache.register"; +import { database } from "./registers/database.register"; +import { environment } from "./registers/environment.register"; +import { jwt } from "./registers/jwt.register"; +import { rateLimit } from "./registers/rate-limit.register"; +import { s3 } from "./registers/s3.register"; @Module({ imports: [ @@ -21,17 +21,9 @@ import { s3Register } from "./registers/s3.register"; resolve(process.cwd(), "../../.env"), ], isGlobal: false, - load: [ - redisRegister, - appRegister, - prismaRegister, - environmentRegister, - jwtRegister, - rateLimitRegister, - s3Register, - ], + load: [cache, app, database, environment, jwt, rateLimit, s3], validationSchema: Joi.object({ - NODE_ENV: Joi.string().default(EnvironmentsConstant.local), + NODE_ENV: Joi.string().default(ENVIRONMENTS.local), APP_PORT: Joi.number().port().positive().required(), APP_REQUEST_TIMEOUT: Joi.number().positive().required(), diff --git a/apps/backend/src/core/config/registers/app.register.ts b/apps/backend/src/core/config/registers/app.register.ts index 79208f1..3575d1f 100644 --- a/apps/backend/src/core/config/registers/app.register.ts +++ b/apps/backend/src/core/config/registers/app.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant.js"; -import type { AppType } from "../types/app.type.js"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant.js"; +import type { App } from "../types/app.type.js"; -export const appRegister = registerAs(ConfigKeyConstant.app, (): AppType => { +export const app = registerAs(CONFIG_KEY.app, (): App => { const appDescription = process.env.APP_DESCRIPTION; const appName = process.env.APP_NAME; const appPort = Number(process.env.APP_PORT); diff --git a/apps/backend/src/core/config/registers/cache.register.ts b/apps/backend/src/core/config/registers/cache.register.ts new file mode 100644 index 0000000..4047280 --- /dev/null +++ b/apps/backend/src/core/config/registers/cache.register.ts @@ -0,0 +1,15 @@ +import { registerAs } from "@nestjs/config"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { Cache } from "../types/cache.type"; + +export const cache = registerAs(CONFIG_KEY.redis, (): Cache => { + const redisUrl = process.env.REDIS_URL; + + if (!redisUrl) { + throw new Error("Missing some env"); + } + + return { + redisUrl, + }; +}); diff --git a/apps/backend/src/core/config/registers/database.register.ts b/apps/backend/src/core/config/registers/database.register.ts new file mode 100644 index 0000000..7fa13c8 --- /dev/null +++ b/apps/backend/src/core/config/registers/database.register.ts @@ -0,0 +1,15 @@ +import { registerAs } from "@nestjs/config"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { Database } from "../types/database.type"; + +export const database = registerAs(CONFIG_KEY.prisma, (): Database => { + const postgresUrl = process.env.POSTGRES_URL; + + if (!postgresUrl) { + throw new Error("Missing some envs"); + } + + return { + postgresUrl, + }; +}); diff --git a/apps/backend/src/core/config/registers/environment.register.ts b/apps/backend/src/core/config/registers/environment.register.ts index 2730876..7605a8d 100644 --- a/apps/backend/src/core/config/registers/environment.register.ts +++ b/apps/backend/src/core/config/registers/environment.register.ts @@ -1,10 +1,10 @@ import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { EnvironmentType } from "../types/environment.type"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { Environment } from "../types/environment.type"; -export const environmentRegister = registerAs( - ConfigKeyConstant.environment, - (): EnvironmentType => { +export const environment = registerAs( + CONFIG_KEY.environment, + (): Environment => { const nodeEnv = process.env.NODE_ENV; if (!nodeEnv) { diff --git a/apps/backend/src/core/config/registers/jwt.register.ts b/apps/backend/src/core/config/registers/jwt.register.ts index b144012..d60a98f 100644 --- a/apps/backend/src/core/config/registers/jwt.register.ts +++ b/apps/backend/src/core/config/registers/jwt.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { JwtType } from "../types/jwt.type"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { Jwt } from "../types/jwt.type"; -export const jwtRegister = registerAs(ConfigKeyConstant.jwt, (): JwtType => { +export const jwt = registerAs(CONFIG_KEY.jwt, (): Jwt => { const expiresIn = Number(process.env.JWT_EXPIRES_IN); const secret = process.env.JWT_SECRET; diff --git a/apps/backend/src/core/config/registers/prisma.register.ts b/apps/backend/src/core/config/registers/prisma.register.ts deleted file mode 100644 index ed245d2..0000000 --- a/apps/backend/src/core/config/registers/prisma.register.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { PrismaType } from "../types/prisma.type"; - -export const prismaRegister = registerAs( - ConfigKeyConstant.prisma, - (): PrismaType => { - const postgresUrl = process.env.POSTGRES_URL; - - if (!postgresUrl) { - throw new Error("Missing some envs"); - } - - return { - postgresUrl, - }; - }, -); diff --git a/apps/backend/src/core/config/registers/rate-limit.register.ts b/apps/backend/src/core/config/registers/rate-limit.register.ts index 8bc878b..16fd8b0 100644 --- a/apps/backend/src/core/config/registers/rate-limit.register.ts +++ b/apps/backend/src/core/config/registers/rate-limit.register.ts @@ -1,20 +1,17 @@ import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { RateLimitType } from "../types/rate-limit.type"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { RateLimit } from "../types/rate-limit.type"; -export const rateLimitRegister = registerAs( - ConfigKeyConstant.rateLimit, - (): RateLimitType => { - const limit = Number(process.env.THROTTLE_LIMIT); - const ttl = Number(process.env.THROTTLE_TTL); +export const rateLimit = registerAs(CONFIG_KEY.rateLimit, (): RateLimit => { + const limit = Number(process.env.THROTTLE_LIMIT); + const ttl = Number(process.env.THROTTLE_TTL); - if (!limit || !ttl) { - throw new Error("Missing some envs"); - } + if (!limit || !ttl) { + throw new Error("Missing some envs"); + } - return { - limit, - ttl, - }; - }, -); + return { + limit, + ttl, + }; +}); diff --git a/apps/backend/src/core/config/registers/redis.register.ts b/apps/backend/src/core/config/registers/redis.register.ts deleted file mode 100644 index 2b5ffb8..0000000 --- a/apps/backend/src/core/config/registers/redis.register.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { RedisType } from "../types/redis.type"; - -export const redisRegister = registerAs( - ConfigKeyConstant.redis, - (): RedisType => { - const redisUrl = process.env.REDIS_URL; - - if (!redisUrl) { - throw new Error("Missing some env"); - } - - return { - redisUrl, - }; - }, -); diff --git a/apps/backend/src/core/config/registers/s3.register.ts b/apps/backend/src/core/config/registers/s3.register.ts index c6780d9..0cc7561 100644 --- a/apps/backend/src/core/config/registers/s3.register.ts +++ b/apps/backend/src/core/config/registers/s3.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../../common/constants/config-key.constant"; -import type { S3Type } from "../types/s3.type"; +import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; +import type { S3 } from "../types/s3.type"; -export const s3Register = registerAs(ConfigKeyConstant.s3, (): S3Type => { +export const s3 = registerAs(CONFIG_KEY.s3, (): S3 => { const awsRegion = process.env.AWS_REGION; const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; diff --git a/apps/backend/src/core/config/types/app.type.ts b/apps/backend/src/core/config/types/app.type.ts index 53581db..e0ac290 100644 --- a/apps/backend/src/core/config/types/app.type.ts +++ b/apps/backend/src/core/config/types/app.type.ts @@ -1,4 +1,4 @@ -type AppType = { +type App = { appPort: number; appRequestTimeout: number; appName: string; @@ -9,4 +9,4 @@ type AppType = { appCorsOrigin: string; }; -export type { AppType }; +export type { App }; diff --git a/apps/backend/src/core/config/types/cache.type.ts b/apps/backend/src/core/config/types/cache.type.ts new file mode 100644 index 0000000..dfbff07 --- /dev/null +++ b/apps/backend/src/core/config/types/cache.type.ts @@ -0,0 +1,5 @@ +type Cache = { + redisUrl: string; +}; + +export type { Cache }; diff --git a/apps/backend/src/core/config/types/database.type.ts b/apps/backend/src/core/config/types/database.type.ts new file mode 100644 index 0000000..0aa15a0 --- /dev/null +++ b/apps/backend/src/core/config/types/database.type.ts @@ -0,0 +1,5 @@ +type Database = { + postgresUrl: string; +}; + +export type { Database }; diff --git a/apps/backend/src/core/config/types/environment.type.ts b/apps/backend/src/core/config/types/environment.type.ts index 615061c..8e69ea4 100644 --- a/apps/backend/src/core/config/types/environment.type.ts +++ b/apps/backend/src/core/config/types/environment.type.ts @@ -1,5 +1,5 @@ -type EnvironmentType = { +type Environment = { nodeEnv: string; }; -export type { EnvironmentType }; +export type { Environment }; diff --git a/apps/backend/src/core/config/types/jwt.type.ts b/apps/backend/src/core/config/types/jwt.type.ts index 34cd279..15af51f 100644 --- a/apps/backend/src/core/config/types/jwt.type.ts +++ b/apps/backend/src/core/config/types/jwt.type.ts @@ -1,6 +1,6 @@ -type JwtType = { +type Jwt = { secret: string; expiresIn: number; }; -export type { JwtType }; +export type { Jwt }; diff --git a/apps/backend/src/core/config/types/prisma.type.ts b/apps/backend/src/core/config/types/prisma.type.ts deleted file mode 100644 index 8bdbaba..0000000 --- a/apps/backend/src/core/config/types/prisma.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type PrismaType = { - postgresUrl: string; -}; - -export type { PrismaType }; diff --git a/apps/backend/src/core/config/types/rate-limit.type.ts b/apps/backend/src/core/config/types/rate-limit.type.ts index e3c055e..dfc5dff 100644 --- a/apps/backend/src/core/config/types/rate-limit.type.ts +++ b/apps/backend/src/core/config/types/rate-limit.type.ts @@ -1,6 +1,6 @@ -type RateLimitType = { +type RateLimit = { ttl: number; limit: number; }; -export type { RateLimitType }; +export type { RateLimit }; diff --git a/apps/backend/src/core/config/types/redis.type.ts b/apps/backend/src/core/config/types/redis.type.ts deleted file mode 100644 index 9112226..0000000 --- a/apps/backend/src/core/config/types/redis.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type RedisType = { - redisUrl: string; -}; - -export type { RedisType }; diff --git a/apps/backend/src/core/config/types/s3.type.ts b/apps/backend/src/core/config/types/s3.type.ts index 0ab8544..6685103 100644 --- a/apps/backend/src/core/config/types/s3.type.ts +++ b/apps/backend/src/core/config/types/s3.type.ts @@ -1,8 +1,8 @@ -type S3Type = { +type S3 = { awsRegion: string; awsAccessKeyId: string; awsSecretAccessKey: string; awsS3BucketName: string; }; -export type { S3Type }; +export type { S3 }; diff --git a/apps/backend/src/core/database/database.module.ts b/apps/backend/src/core/database/database.module.ts new file mode 100644 index 0000000..d0ad629 --- /dev/null +++ b/apps/backend/src/core/database/database.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { ConfigModule } from "../config/config.module.js"; +import { DatabaseService } from "./database.service.js"; + +@Module({ + imports: [ConfigModule], + exports: [DatabaseService], + providers: [DatabaseService], +}) +export class DatabaseModule {} diff --git a/apps/backend/src/core/prisma/prisma.service.ts b/apps/backend/src/core/database/database.service.ts similarity index 71% rename from apps/backend/src/core/prisma/prisma.service.ts rename to apps/backend/src/core/database/database.service.ts index d5d1321..f495d8a 100644 --- a/apps/backend/src/core/prisma/prisma.service.ts +++ b/apps/backend/src/core/database/database.service.ts @@ -7,18 +7,16 @@ import { import { ConfigService } from "@nestjs/config"; import { PrismaPg } from "@prisma/adapter-pg"; import { PrismaClient } from "../../../prisma/generated/client.js"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant.js"; -import type { PrismaType } from "../config/types/prisma.type.js"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; +import type { Database } from "../config/types/database.type.js"; @Injectable() -export class PrismaService +export class DatabaseService extends PrismaClient implements OnModuleInit, OnModuleDestroy { constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const prismaConfig = configService.getOrThrow( - ConfigKeyConstant.prisma, - ); + const prismaConfig = configService.getOrThrow(CONFIG_KEY.prisma); const adapter: PrismaPg = new PrismaPg({ connectionString: prismaConfig.postgresUrl, diff --git a/apps/backend/src/core/health-checks/health-checks.module.ts b/apps/backend/src/core/health-checks/health-checks.module.ts index 384871e..109ed0f 100644 --- a/apps/backend/src/core/health-checks/health-checks.module.ts +++ b/apps/backend/src/core/health-checks/health-checks.module.ts @@ -1,13 +1,13 @@ import { Module } from "@nestjs/common"; import { TerminusModule } from "@nestjs/terminus"; -import { PrismaModule } from "../prisma/prisma.module.js"; +import { DatabaseModule } from "../database/database.module.js"; import { RedisModule } from "../redis/redis.module.js"; import { HealthChecksController } from "./health-checks.controller.js"; import { HealthChecksService } from "./health-checks.service.js"; @Module({ controllers: [HealthChecksController], - imports: [TerminusModule, PrismaModule, RedisModule], + imports: [TerminusModule, DatabaseModule, RedisModule], providers: [HealthChecksService], }) export class HealthChecksModule {} diff --git a/apps/backend/src/core/health-checks/health-checks.service.ts b/apps/backend/src/core/health-checks/health-checks.service.ts index bf71d2d..244ac6d 100644 --- a/apps/backend/src/core/health-checks/health-checks.service.ts +++ b/apps/backend/src/core/health-checks/health-checks.service.ts @@ -9,7 +9,7 @@ import { } from "@nestjs/terminus"; import { InjectRedis } from "@nestjs-modules/ioredis"; import type { Redis } from "ioredis"; -import { PrismaService } from "../prisma/prisma.service.js"; +import { DatabaseService } from "../database/database.service.js"; @Injectable() export class HealthChecksService { @@ -19,7 +19,7 @@ export class HealthChecksService { private readonly healthCheckService: HealthCheckService, @Inject(PrismaHealthIndicator) private readonly prismaHealthIndicator: PrismaHealthIndicator, - @Inject(PrismaService) private readonly prismaService: PrismaService, + @Inject(DatabaseService) private readonly prismaService: DatabaseService, @Inject(HealthIndicatorService) readonly healthIndicatorService: HealthIndicatorService, ) {} diff --git a/apps/backend/src/core/jwt/jwt.module.ts b/apps/backend/src/core/jwt/jwt.module.ts index 5bcbf02..4bdb37b 100644 --- a/apps/backend/src/core/jwt/jwt.module.ts +++ b/apps/backend/src/core/jwt/jwt.module.ts @@ -1,8 +1,8 @@ import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { JwtModule as CoreJwtModule, type JwtModuleOptions } from "@nestjs/jwt"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant.js"; -import type { JwtType } from "../config/types/jwt.type.js"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; +import type { Jwt } from "../config/types/jwt.type.js"; @Module({ imports: [ @@ -10,9 +10,7 @@ import type { JwtType } from "../config/types/jwt.type.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService): JwtModuleOptions => { - const jwtConfig = configService.getOrThrow( - ConfigKeyConstant.jwt, - ); + const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); return { secret: jwtConfig.secret, diff --git a/apps/backend/src/core/prisma/prisma.module.ts b/apps/backend/src/core/prisma/prisma.module.ts deleted file mode 100644 index 47e347c..0000000 --- a/apps/backend/src/core/prisma/prisma.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from "@nestjs/common"; -import { ConfigModule } from "../config/config.module.js"; -import { PrismaService } from "./prisma.service.js"; - -@Module({ - imports: [ConfigModule], - exports: [PrismaService], - providers: [PrismaService], -}) -export class PrismaModule {} diff --git a/apps/backend/src/core/rate-limit/rate-limit.module.ts b/apps/backend/src/core/rate-limit/rate-limit.module.ts index a6204e4..ef5ac6d 100644 --- a/apps/backend/src/core/rate-limit/rate-limit.module.ts +++ b/apps/backend/src/core/rate-limit/rate-limit.module.ts @@ -2,8 +2,8 @@ import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { APP_GUARD } from "@nestjs/core"; import { seconds, ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant.js"; -import type { RateLimitType } from "../config/types/rate-limit.type.js"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; +import type { RateLimit } from "../config/types/rate-limit.type.js"; @Module({ imports: [ @@ -11,8 +11,8 @@ import type { RateLimitType } from "../config/types/rate-limit.type.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const rateLimitConfig = configService.getOrThrow( - ConfigKeyConstant.rateLimit, + const rateLimitConfig = configService.getOrThrow( + CONFIG_KEY.rateLimit, ); return { diff --git a/apps/backend/src/core/redis/redis.module.ts b/apps/backend/src/core/redis/redis.module.ts index 5a85d85..d2fe9d0 100644 --- a/apps/backend/src/core/redis/redis.module.ts +++ b/apps/backend/src/core/redis/redis.module.ts @@ -1,8 +1,8 @@ import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { RedisModule as CoreRedisModule } from "@nestjs-modules/ioredis"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant.js"; -import type { RedisType } from "../config/types/redis.type.js"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; +import type { Cache } from "../config/types/cache.type.js"; import { RedisService } from "./redis.service.js"; @Module({ @@ -12,9 +12,7 @@ import { RedisService } from "./redis.service.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const redisConfig = configService.getOrThrow( - ConfigKeyConstant.redis, - ); + const redisConfig = configService.getOrThrow(CONFIG_KEY.redis); return { options: { diff --git a/apps/backend/src/core/s3/s3.service.ts b/apps/backend/src/core/s3/s3.service.ts index 798093f..34c0c3b 100644 --- a/apps/backend/src/core/s3/s3.service.ts +++ b/apps/backend/src/core/s3/s3.service.ts @@ -8,8 +8,8 @@ import { // import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { Inject, Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant"; -import type { S3Type } from "../config/types/s3.type"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant"; +import type { S3 } from "../config/types/s3.type"; @Injectable() export class S3Service { @@ -18,7 +18,7 @@ export class S3Service { private readonly region: string; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const s3Config = configService.getOrThrow(ConfigKeyConstant.s3); + const s3Config = configService.getOrThrow(CONFIG_KEY.s3); this.s3Client = new S3Client({ credentials: { diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts index 205f46f..f084684 100644 --- a/apps/backend/src/main.ts +++ b/apps/backend/src/main.ts @@ -10,13 +10,13 @@ import type { NestExpressApplication } from "@nestjs/platform-express"; import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; import helmet from "helmet"; import { AppModule } from "./app.module.js"; -import { ConfigKeyConstant } from "./common/constants/config-key.constant.js"; -import { EnvironmentsConstant } from "./common/constants/environments.constant.js"; +import { CONFIG_KEY } from "./common/constants/config-key.constant.js"; +import { ENVIRONMENTS } from "./common/constants/environments.constant.js"; import { CatchEverythingFilter } from "./common/filters/catch-everything.filter.js"; import { LoggingInterceptor } from "./common/interceptors/logger.interceptor.js"; import { TimeoutInterceptor } from "./common/interceptors/timeout.interceptor.js"; -import type { AppType } from "./core/config/types/app.type.js"; -import type { EnvironmentType } from "./core/config/types/environment.type.js"; +import type { App } from "./core/config/types/app.type.js"; +import type { Environment } from "./core/config/types/environment.type.js"; const logger: Logger = new Logger("Bootstrap"); @@ -25,14 +25,13 @@ const logger: Logger = new Logger("Bootstrap"); const configService = app.get(ConfigService); - const environmentConfig = configService.getOrThrow( - ConfigKeyConstant.environment, + const environmentConfig = configService.getOrThrow( + CONFIG_KEY.environment, ); - const isProduction = - environmentConfig.nodeEnv === EnvironmentsConstant.production; + const isProduction = environmentConfig.nodeEnv === ENVIRONMENTS.production; - const appConfig = configService.getOrThrow(ConfigKeyConstant.app); + const appConfig = configService.getOrThrow(CONFIG_KEY.app); app.enableVersioning({ defaultVersion: "1", @@ -47,10 +46,7 @@ const logger: Logger = new Logger("Bootstrap"); .setTitle(appConfig.appName) .setDescription(appConfig.appDescription) .setVersion("1.0") - .addServer( - `http://localhost:${appConfig.appPort}`, - EnvironmentsConstant.local, - ) + .addServer(`http://localhost:${appConfig.appPort}`, ENVIRONMENTS.local) .addBearerAuth( { bearerFormat: "JWT", diff --git a/apps/backend/src/modules/auth/auth.controller.ts b/apps/backend/src/modules/auth/auth.controller.ts index b4ab0d0..65fd59f 100644 --- a/apps/backend/src/modules/auth/auth.controller.ts +++ b/apps/backend/src/modules/auth/auth.controller.ts @@ -16,7 +16,7 @@ import { ApiTags, ApiUnauthorizedResponse, } from "@nestjs/swagger"; -import { UserIdDecorator } from "../../common/decorators/user-id.decorator.js"; +import { UserId } from "../../common/decorators/user-id.decorator.js"; import { LocalGuard } from "../../common/guards/local.guard.js"; import { AuthService } from "./auth.service.js"; import { SignInDto } from "./dtos/sign-in.dto.js"; @@ -48,7 +48,7 @@ export class AuthController { @ApiBody({ type: SignInDto, }) - public signIn(@UserIdDecorator() userId: number): AuthRdo { + public signIn(@UserId() userId: number): AuthRdo { return this.authService.signIn(userId); } diff --git a/apps/backend/src/modules/auth/auth.module.ts b/apps/backend/src/modules/auth/auth.module.ts index e0185ae..028dee0 100644 --- a/apps/backend/src/modules/auth/auth.module.ts +++ b/apps/backend/src/modules/auth/auth.module.ts @@ -3,8 +3,8 @@ import { PassportModule } from "@nestjs/passport"; import { JwtStrategy } from "../../common/strategies/jwt.strategy.js"; import { LocalStrategy } from "../../common/strategies/local.strategy.js"; import { ConfigModule } from "../../core/config/config.module.js"; +import { DatabaseModule } from "../../core/database/database.module.js"; import { JwtModule } from "../../core/jwt/jwt.module.js"; -import { PrismaModule } from "../../core/prisma/prisma.module.js"; import { AuthController } from "./auth.controller.js"; import { AuthRepository } from "./auth.repository.js"; import { AuthService } from "./auth.service.js"; @@ -12,7 +12,7 @@ import { AuthService } from "./auth.service.js"; @Module({ controllers: [AuthController], exports: [AuthService, AuthRepository], - imports: [JwtModule, PassportModule, PrismaModule, ConfigModule], + imports: [JwtModule, PassportModule, DatabaseModule, ConfigModule], providers: [AuthService, AuthRepository, JwtStrategy, LocalStrategy], }) export class AuthModule {} diff --git a/apps/backend/src/modules/auth/auth.repository.ts b/apps/backend/src/modules/auth/auth.repository.ts index a373173..efe845f 100644 --- a/apps/backend/src/modules/auth/auth.repository.ts +++ b/apps/backend/src/modules/auth/auth.repository.ts @@ -1,12 +1,12 @@ import { Inject, Injectable } from "@nestjs/common"; -import { PrismaService } from "../../core/prisma/prisma.service.js"; +import { DatabaseService } from "../../core/database/database.service.js"; import type { SignUpDto } from "./dtos/sign-up.dto.js"; import type { UserRdo } from "./rdos/user.rdo.js"; @Injectable() export class AuthRepository { constructor( - @Inject(PrismaService) private readonly prismaService: PrismaService, + @Inject(DatabaseService) private readonly prismaService: DatabaseService, ) {} public async create(signUpDto: SignUpDto): Promise { diff --git a/apps/backend/src/modules/auth/auth.service.ts b/apps/backend/src/modules/auth/auth.service.ts index 00ffe1c..d1f51a2 100644 --- a/apps/backend/src/modules/auth/auth.service.ts +++ b/apps/backend/src/modules/auth/auth.service.ts @@ -2,9 +2,9 @@ import { ConflictException, Inject, Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; import { genSalt, hash } from "bcrypt"; -import { ConfigKeyConstant } from "../../common/constants/config-key.constant.js"; +import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; import type { AuthPayload } from "../../common/types/auth-payload.type.js"; -import type { JwtType } from "../../core/config/types/jwt.type.js"; +import type { Jwt } from "../../core/config/types/jwt.type.js"; import { AuthRepository } from "./auth.repository.js"; import type { SignUpDto } from "./dtos/sign-up.dto.js"; import { AuthRdo } from "./rdos/auth.rdo.js"; @@ -18,7 +18,7 @@ export class AuthService { @Inject(AuthRepository) private readonly authRepository: AuthRepository, @Inject(ConfigService) readonly configService: ConfigService, ) { - const jwtConfig = configService.getOrThrow(ConfigKeyConstant.jwt); + const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); this.jwtSecret = jwtConfig.secret; } From 40184bf1d7e2e4720335748befda4f4b09fb2c12 Mon Sep 17 00:00:00 2001 From: maxonchickdev Date: Wed, 6 May 2026 20:56:29 +0300 Subject: [PATCH 3/3] refactor(root): rename types and update imports for consistency across the application --- README.md | 144 ------------------ .../common/filters/catch-everything.filter.ts | 12 +- .../common/interceptors/logger.interceptor.ts | 4 +- .../interceptors/timeout.interceptor.ts | 4 +- .../src/common/strategies/jwt.strategy.ts | 4 +- .../src/common/types/auth-payload.type.ts | 4 +- .../src/common/types/error-response.type.ts | 6 +- apps/backend/src/core/config/config.module.ts | 24 ++- .../src/core/config/registers/app.register.ts | 4 +- .../core/config/registers/cache.register.ts | 23 +-- .../config/registers/database.register.ts | 23 +-- .../config/registers/environment.register.ts | 6 +- .../src/core/config/registers/jwt.register.ts | 4 +- .../config/registers/rate-limit.register.ts | 27 ++-- .../src/core/config/registers/s3.register.ts | 4 +- .../{app.type.ts => app.register.type.ts} | 4 +- .../core/config/types/cache.register.type.ts | 5 + .../src/core/config/types/cache.type.ts | 5 - .../config/types/database.register.type.ts | 5 + .../src/core/config/types/database.type.ts | 5 - .../config/types/environment.register.type.ts | 5 + .../src/core/config/types/environment.type.ts | 5 - .../core/config/types/jwt.register.type.ts | 6 + .../backend/src/core/config/types/jwt.type.ts | 6 - .../config/types/rate-limit.register.type.ts | 6 + .../src/core/config/types/rate-limit.type.ts | 6 - .../types/{s3.type.ts => s3.register.type.ts} | 4 +- .../src/core/database/database.service.ts | 6 +- apps/backend/src/core/jwt/jwt.module.ts | 6 +- .../src/core/rate-limit/rate-limit.module.ts | 4 +- apps/backend/src/core/redis/redis.module.ts | 6 +- apps/backend/src/core/s3/s3.service.ts | 4 +- apps/backend/src/main.ts | 8 +- apps/backend/src/modules/auth/auth.service.ts | 17 ++- 34 files changed, 144 insertions(+), 262 deletions(-) rename apps/backend/src/core/config/types/{app.type.ts => app.register.type.ts} (77%) create mode 100644 apps/backend/src/core/config/types/cache.register.type.ts delete mode 100644 apps/backend/src/core/config/types/cache.type.ts create mode 100644 apps/backend/src/core/config/types/database.register.type.ts delete mode 100644 apps/backend/src/core/config/types/database.type.ts create mode 100644 apps/backend/src/core/config/types/environment.register.type.ts delete mode 100644 apps/backend/src/core/config/types/environment.type.ts create mode 100644 apps/backend/src/core/config/types/jwt.register.type.ts delete mode 100644 apps/backend/src/core/config/types/jwt.type.ts create mode 100644 apps/backend/src/core/config/types/rate-limit.register.type.ts delete mode 100644 apps/backend/src/core/config/types/rate-limit.type.ts rename apps/backend/src/core/config/types/{s3.type.ts => s3.register.type.ts} (65%) diff --git a/README.md b/README.md index 39d7a13..35f1a43 100644 --- a/README.md +++ b/README.md @@ -1,145 +1 @@ # NodeJS Monorepo - -npm workspaces monorepo: deployable apps under `apps/`, reusable libraries under `packages/`. This document is the **source of truth** for naming and layout; tooling (Biome, **ls-lint**, Knip) should stay aligned with it. - -## Workspace layout - -| Path | npm `name` | Role | -|------|------------|------| -| `apps/backend` | `@nodejs-monorepo/backend` | NestJS API, Prisma, feature modules | -| `apps/web` | `@nodejs-monorepo/web` | Vite + React SPA | -| `packages/shared` | `@nodejs-monorepo/shared` | Types and other cross-app, runtime-safe code | - -**Rules** - -- Every workspace package uses the **`@nodejs-monorepo/*`** scope (`package.json` → `name`). -- New runnable deployables → **`apps//`** (short role name, **`kebab-case`**), e.g. `admin`, `worker-notifications`. -- New libraries → **`packages//`** (capability-oriented, **`kebab-case`**), e.g. `eslint-config`, `ui`. - -Imports across boundaries use package names only, never deep relative hops between apps: - -```ts -import type { SignInType } from "@nodejs-monorepo/shared"; -``` - ---- - -## Filesystem naming (repository-wide) - -| What | Convention | Enforcement | -|------|------------|-------------| -| **Directories** under workspace `src/` | **`kebab-case`** | `health-checks/`, `sign-in/`, `rate-limit/` | -| **Files** `.ts` / `.tsx` under `apps/*/src` and `packages/*/src` | **`kebab-case`** stem | `auth.service.ts`, `sign-up.dto.ts`, `sign-in.route.tsx`, `config-key.constant.ts` | -| **Root / tooling filenames** | Ecosystem defaults | `biome.json`, `docker-compose.yml`, `Dockerfile.backend`, `commitlint.config.ts` | - -**`ls-lint`** (`.ls-lint.yml`) applies **`kebab-case`** to **`.dir`**, **`.ts`**, and **`.tsx`** under: - -- `apps/*/src` -- `packages/*/src` - -Ignored paths include **`node_modules`**, **`dist`**, **`.git`**, and **`**/prisma/migrations/**`** (Prisma timestamp folder names). - -**React:** file names stay **`kebab-case`** (same as Nest modules). Exported route/component **identifiers** are **`PascalCase`** (e.g. `SignInRoute` in `sign-in.route.tsx`). Do not use **`PascalCase.tsx`** filenames in `src/`—that diverges from backend and breaks a single filesystem rule. - -**Tests:** co-locate **`*.spec.ts`** / **`*.test.ts`** next to the module under test, or use **`__tests__/`**—pick one style per package and keep it consistent. - ---- - -## TypeScript symbols (all packages) - -| Kind | Style | Examples in this repo | -|------|--------|------------------------| -| **Classes** (Nest providers, DTOs, RDOs, guards, entities) | **`PascalCase`** | `AuthService`, `SignInDto`, `AuthRdo` | -| **Types / interfaces** | **`PascalCase`** | `AuthPayload`, `SignInType`, `EnvironmentType` | -| **Functions, methods, variables, properties** | **`camelCase`** | `signUp`, `configService`, `accessToken` | -| **Booleans** | **`is` / `has` / `can` / `should`** prefix | `isEnabled`, `hasSession` | -| **Enum type** | **`PascalCase`** | `OrderStatus` | -| **Enum members** | **`PascalCase`** preferred (matches typical TS + Swagger usage) | `Pending`, `Active` — if you introduce **`UPPER_SNAKE`** members, keep them consistent within that enum | - -**Constants** - -- **Fixed key maps / grouped config tokens** → export as a **`PascalCase`** object whose name ends with **`Constant`**, in **`*.constant.ts`**. Example: `ConfigKeyConstant`, `EnvironmentsConstant` in `config-key.constant.ts`, `environments.constant.ts`. -- **Primitive literals** (timeouts, magic numbers shared across files) → **`UPPER_SNAKE`** when it improves scanability, or **`camelCase`** `as const` objects for grouped defaults—prefer one approach per file. - -**Barrel files** in a feature folder use a **short plural topic** matching siblings: **`dtos.ts`**, **`rdos.ts`**, **`types.ts`**, **`constants.ts`**, **`guards.ts`**, **`strategies.ts`**, **`interceptors.ts`**, **`filters.ts`**, **`decorators.ts`**. Re-export **named** exports explicitly; keep barrels **shallow** (avoid `index.ts` chains that obscure bundle entry points). - -**Helpers (“utils”)** → only for **generic, domain-agnostic** pure functions (formatting, small assertions). **Feature rules** belong under **`modules//`** next to that feature’s service/repository—not in a dumping ground called `helpers.ts`. - ---- - -## Backend (`apps/backend`) - -### Folders under `src/` - -| Folder | Purpose | -|--------|---------| -| **`modules/`** | Vertical features: **`modules//`** (e.g. `auth/`). One Nest **`*.module.ts`** per feature slice when it’s a bounded context. | -| **`core/`** | Infrastructure wired as Nest modules: Prisma, Redis, JWT, S3, rate limiting, config, health checks, registrations under **`core/config/registers/`**. | -| **`common/`** | Cross-feature primitives: decorators, guards, strategies, interceptors, filters, shared types, constants. | - -### File suffixes (Nest + this repo) - -| Pattern | Role | -|---------|------| -| **`.module.ts`** | Nest module | -| **`.controller.ts`** | HTTP controller | -| **`.service.ts`** | Injectable application service | -| **`.repository.ts`** | Data access | -| **`.dto.ts`** | Request / input DTO (validation, Swagger) | -| **`.rdo.ts`** | Response DTO (**RDO**—serialized API output) | -| **`.guard.ts`** | Auth / policy guard | -| **`.strategy.ts`** | Passport strategy | -| **`.interceptor.ts`** | Interceptor | -| **`.filter.ts`** | Exception filter | -| **`.decorator.ts`** | Custom decorator | -| **`.type.ts`** | Shared TS-only types (not tied to a single class file) | -| **`.register.ts`** | Joi/env registration helpers in **`core/config/registers/`** | -| **`prisma/schema.prisma`**, **`prisma/migrations/`** | Schema and migrations (**migration folder names** = Prisma default: timestamp + **`snake_case`** slug) | -| **`prisma/seeders/`** | Seed scripts (**`kebab-case`** `.ts` files when you add more than `seeder.ts`) | - -### ESM note - -Production build uses **`"type": "module"`** with relative imports that often include **`.js`** extensions targeting emitted files (see Nest/tsconfig). Match existing import style when adding files. - ---- - -## Shared package (`packages/shared`) - -| Topic | Rule | -|-------|------| -| **Purpose** | Code safe for **both** backend and frontend (no Node-only APIs, no Nest/DOM leakage unless split entry points). | -| **Layout** | **`src/types//`** (e.g. `types/auth/`), **`src/index.ts`** as the package entry barrel. | -| **Type names** | **`PascalCase`** (`SignInType`, `SignUpType`). | -| **Files** | **`kebab-case`**, multi-word segments joined with hyphens (`sign-in.type.ts`). | - ---- - -## Web app (`apps/web`) - -| Area | Convention | -|------|------------| -| **Routes** | **`src/routes//.route.tsx`** mirroring URL segments (`kebab-case` dirs + file stem). | -| **Exported route component** | **`PascalCase`** symbol matching the page (`SignInRoute`). | -| **Entry** | `src/main.tsx`, Vite **`index.html`** (entries also referenced in **`knip.config.ts`**). | -| **Future UI** | Optional **`src/components/`** with **`kebab-case.tsx`** files (e.g. `primary-button.tsx`) exporting **`PascalCase`** components, **or** one folder per component **`primary-button/index.tsx`**—choose one pattern for the whole app. | - ---- - -## Tooling (naming-adjacent) - -| Tool | Role | -|------|------| -| **Biome** | Formatter + linter (root / per-package `biome.json`). | -| **ls-lint** | **`kebab-case`** dirs and **`.ts` / `.tsx`** under workspace `src/` trees (see above). | -| **Knip** | Unused exports/deps; entry globs in **`knip.config.ts`**. | - ---- - -## Checklist for new code - -1. Workspace **`name`**: `@nodejs-monorepo/`; disk folder **`kebab-case`** under `apps/` or `packages/`. -2. Under **`apps/*/src`** or **`packages/*/src`**: directories and **`*.ts` / `*.tsx`** → **`kebab-case`**; React exports **`PascalCase`**. -3. Nest artifacts → suffix table above; **DTO** vs **RDO** filenames explicit. -4. Cross-app contracts → **`packages/shared`** with **`PascalCase`** types. -5. Grouped env/config keys → **`SomethingConstant`** in **`*.constant.ts`**. -6. Run **`npm run lint:filesystem:check`** before pushing when you add files or folders. diff --git a/apps/backend/src/common/filters/catch-everything.filter.ts b/apps/backend/src/common/filters/catch-everything.filter.ts index 309db2b..a7dd8e0 100644 --- a/apps/backend/src/common/filters/catch-everything.filter.ts +++ b/apps/backend/src/common/filters/catch-everything.filter.ts @@ -11,12 +11,12 @@ import { import { ConfigService } from "@nestjs/config"; import { HttpAdapterHost } from "@nestjs/core"; import type { Prisma } from "@prisma/generated/client.js"; -import type { Environment } from "../../core/config/types/environment.type.js"; +import type { EnvironmentRegisterType } from "../../core/config/types/environment.register.type.js"; import { CONFIG_KEY } from "../constants/config-key.constant.js"; import { ENVIRONMENTS } from "../constants/environments.constant.js"; import type { - ErrorResponseBody, - HttpExceptionResponse, + ErrorResponseBodyType, + HttpExceptionResponseType, } from "../types/error-response.type.js"; const PRISMA_ERROR_MAP: Record = { @@ -40,7 +40,7 @@ export class CatchEverythingFilter implements ExceptionFilter { @Inject(HttpAdapterHost) private readonly httpAdapterHost: HttpAdapterHost, @Inject(ConfigService) readonly configService: ConfigService, ) { - const environmentConfig = configService.getOrThrow( + const environmentConfig = configService.getOrThrow( CONFIG_KEY.environment, ); @@ -54,7 +54,7 @@ export class CatchEverythingFilter implements ExceptionFilter { const { statusCode, error, message } = this.normalizeException(exception); - const responseBody: ErrorResponseBody = { + const responseBody: ErrorResponseBodyType = { error, message, path: httpAdapter.getRequestUrl(request), @@ -98,7 +98,7 @@ export class CatchEverythingFilter implements ExceptionFilter { message: string | string[]; } { const statusCode = exception.getStatus(); - const response = exception.getResponse() as HttpExceptionResponse; + const response = exception.getResponse() as HttpExceptionResponseType; if (typeof response === "string") { return { diff --git a/apps/backend/src/common/interceptors/logger.interceptor.ts b/apps/backend/src/common/interceptors/logger.interceptor.ts index 91f4a2d..f2a16be 100644 --- a/apps/backend/src/common/interceptors/logger.interceptor.ts +++ b/apps/backend/src/common/interceptors/logger.interceptor.ts @@ -10,7 +10,7 @@ import { import { ConfigService } from "@nestjs/config"; import type { Request, Response } from "express"; import { type Observable, tap } from "rxjs"; -import type { Environment } from "../../core/config/types/environment.type.js"; +import type { EnvironmentRegisterType } from "../../core/config/types/environment.register.type.js"; import { CONFIG_KEY } from "../constants/config-key.constant.js"; import { ENVIRONMENTS } from "../constants/environments.constant.js"; @@ -22,7 +22,7 @@ export class LoggingInterceptor implements NestInterceptor { private readonly isProduction: boolean; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const environmentConfig = configService.getOrThrow( + const environmentConfig = configService.getOrThrow( CONFIG_KEY.environment, ); diff --git a/apps/backend/src/common/interceptors/timeout.interceptor.ts b/apps/backend/src/common/interceptors/timeout.interceptor.ts index 76a7714..7b3651a 100644 --- a/apps/backend/src/common/interceptors/timeout.interceptor.ts +++ b/apps/backend/src/common/interceptors/timeout.interceptor.ts @@ -14,7 +14,7 @@ import { throwError, timeout, } from "rxjs"; -import type { App } from "../../core/config/types/app.type.js"; +import type { AppRegisterType } from "../../core/config/types/app.register.type.js"; import { CONFIG_KEY } from "../constants/config-key.constant.js"; @Injectable() @@ -22,7 +22,7 @@ export class TimeoutInterceptor implements NestInterceptor { private readonly appRequestTimeout: number; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const appConfig = configService.getOrThrow(CONFIG_KEY.app); + const appConfig = configService.getOrThrow(CONFIG_KEY.app); this.appRequestTimeout = appConfig.appRequestTimeout; } diff --git a/apps/backend/src/common/strategies/jwt.strategy.ts b/apps/backend/src/common/strategies/jwt.strategy.ts index b464a99..3e9c999 100644 --- a/apps/backend/src/common/strategies/jwt.strategy.ts +++ b/apps/backend/src/common/strategies/jwt.strategy.ts @@ -2,7 +2,7 @@ import { Inject, Injectable, UnauthorizedException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { PassportStrategy } from "@nestjs/passport"; import { ExtractJwt, Strategy } from "passport-jwt"; -import type { Jwt } from "../../core/config/types/jwt.type.js"; +import type { JwtRegisterType } from "../../core/config/types/jwt.register.type.js"; import { AuthRepository } from "../../modules/auth/auth.repository.js"; import { CONFIG_KEY } from "../constants/config-key.constant.js"; @@ -12,7 +12,7 @@ export class JwtStrategy extends PassportStrategy(Strategy, "jwt") { @Inject(AuthRepository) private readonly authRepository: AuthRepository, @Inject(ConfigService) readonly configService: ConfigService, ) { - const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); + const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); super({ ignoreExpiration: false, diff --git a/apps/backend/src/common/types/auth-payload.type.ts b/apps/backend/src/common/types/auth-payload.type.ts index 6d016be..684bbea 100644 --- a/apps/backend/src/common/types/auth-payload.type.ts +++ b/apps/backend/src/common/types/auth-payload.type.ts @@ -1,5 +1,5 @@ -type AuthPayload = { +type AuthPayloadType = { userId: number; }; -export type { AuthPayload }; +export type { AuthPayloadType }; diff --git a/apps/backend/src/common/types/error-response.type.ts b/apps/backend/src/common/types/error-response.type.ts index db2d08e..5b6ea6f 100644 --- a/apps/backend/src/common/types/error-response.type.ts +++ b/apps/backend/src/common/types/error-response.type.ts @@ -1,4 +1,4 @@ -type ErrorResponseBody = { +type ErrorResponseBodyType = { statusCode: number; error: string; message: string | string[]; @@ -6,8 +6,8 @@ type ErrorResponseBody = { timestamp?: string; }; -type HttpExceptionResponse = +type HttpExceptionResponseType = | string | { message?: string | string[]; error?: string; statusCode?: number }; -export type { ErrorResponseBody, HttpExceptionResponse }; +export type { ErrorResponseBodyType, HttpExceptionResponseType }; diff --git a/apps/backend/src/core/config/config.module.ts b/apps/backend/src/core/config/config.module.ts index adc3fc9..2914fbd 100644 --- a/apps/backend/src/core/config/config.module.ts +++ b/apps/backend/src/core/config/config.module.ts @@ -5,13 +5,13 @@ import { Module } from "@nestjs/common"; import { ConfigModule as CoreConfigModule } from "@nestjs/config"; import Joi from "joi"; import { ENVIRONMENTS } from "../../common/constants/environments.constant"; -import { app } from "./registers/app.register"; -import { cache } from "./registers/cache.register"; -import { database } from "./registers/database.register"; -import { environment } from "./registers/environment.register"; -import { jwt } from "./registers/jwt.register"; -import { rateLimit } from "./registers/rate-limit.register"; -import { s3 } from "./registers/s3.register"; +import { appRegister } from "./registers/app.register"; +import { cacheRegister } from "./registers/cache.register"; +import { databaseRegister } from "./registers/database.register"; +import { environmentRegister } from "./registers/environment.register"; +import { jwtRegister } from "./registers/jwt.register"; +import { rateLimitRegister } from "./registers/rate-limit.register"; +import { s3Register } from "./registers/s3.register"; @Module({ imports: [ @@ -21,7 +21,15 @@ import { s3 } from "./registers/s3.register"; resolve(process.cwd(), "../../.env"), ], isGlobal: false, - load: [cache, app, database, environment, jwt, rateLimit, s3], + load: [ + cacheRegister, + appRegister, + databaseRegister, + environmentRegister, + jwtRegister, + rateLimitRegister, + s3Register, + ], validationSchema: Joi.object({ NODE_ENV: Joi.string().default(ENVIRONMENTS.local), diff --git a/apps/backend/src/core/config/registers/app.register.ts b/apps/backend/src/core/config/registers/app.register.ts index 3575d1f..9f9d45d 100644 --- a/apps/backend/src/core/config/registers/app.register.ts +++ b/apps/backend/src/core/config/registers/app.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant.js"; -import type { App } from "../types/app.type.js"; +import type { AppRegisterType } from "../types/app.register.type.js"; -export const app = registerAs(CONFIG_KEY.app, (): App => { +export const appRegister = registerAs(CONFIG_KEY.app, (): AppRegisterType => { const appDescription = process.env.APP_DESCRIPTION; const appName = process.env.APP_NAME; const appPort = Number(process.env.APP_PORT); diff --git a/apps/backend/src/core/config/registers/cache.register.ts b/apps/backend/src/core/config/registers/cache.register.ts index 4047280..0f7c700 100644 --- a/apps/backend/src/core/config/registers/cache.register.ts +++ b/apps/backend/src/core/config/registers/cache.register.ts @@ -1,15 +1,18 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { Cache } from "../types/cache.type"; +import type { CacheRegisterType } from "../types/cache.register.type"; -export const cache = registerAs(CONFIG_KEY.redis, (): Cache => { - const redisUrl = process.env.REDIS_URL; +export const cacheRegister = registerAs( + CONFIG_KEY.redis, + (): CacheRegisterType => { + const redisUrl = process.env.REDIS_URL; - if (!redisUrl) { - throw new Error("Missing some env"); - } + if (!redisUrl) { + throw new Error("Missing some env"); + } - return { - redisUrl, - }; -}); + return { + redisUrl, + }; + }, +); diff --git a/apps/backend/src/core/config/registers/database.register.ts b/apps/backend/src/core/config/registers/database.register.ts index 7fa13c8..c92b0c7 100644 --- a/apps/backend/src/core/config/registers/database.register.ts +++ b/apps/backend/src/core/config/registers/database.register.ts @@ -1,15 +1,18 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { Database } from "../types/database.type"; +import type { DatabaseRegisterType } from "../types/database.register.type"; -export const database = registerAs(CONFIG_KEY.prisma, (): Database => { - const postgresUrl = process.env.POSTGRES_URL; +export const databaseRegister = registerAs( + CONFIG_KEY.prisma, + (): DatabaseRegisterType => { + const postgresUrl = process.env.POSTGRES_URL; - if (!postgresUrl) { - throw new Error("Missing some envs"); - } + if (!postgresUrl) { + throw new Error("Missing some envs"); + } - return { - postgresUrl, - }; -}); + return { + postgresUrl, + }; + }, +); diff --git a/apps/backend/src/core/config/registers/environment.register.ts b/apps/backend/src/core/config/registers/environment.register.ts index 7605a8d..a6f133a 100644 --- a/apps/backend/src/core/config/registers/environment.register.ts +++ b/apps/backend/src/core/config/registers/environment.register.ts @@ -1,10 +1,10 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { Environment } from "../types/environment.type"; +import type { EnvironmentRegisterType } from "../types/environment.register.type"; -export const environment = registerAs( +export const environmentRegister = registerAs( CONFIG_KEY.environment, - (): Environment => { + (): EnvironmentRegisterType => { const nodeEnv = process.env.NODE_ENV; if (!nodeEnv) { diff --git a/apps/backend/src/core/config/registers/jwt.register.ts b/apps/backend/src/core/config/registers/jwt.register.ts index d60a98f..007ff1e 100644 --- a/apps/backend/src/core/config/registers/jwt.register.ts +++ b/apps/backend/src/core/config/registers/jwt.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { Jwt } from "../types/jwt.type"; +import type { JwtRegisterType } from "../types/jwt.register.type"; -export const jwt = registerAs(CONFIG_KEY.jwt, (): Jwt => { +export const jwtRegister = registerAs(CONFIG_KEY.jwt, (): JwtRegisterType => { const expiresIn = Number(process.env.JWT_EXPIRES_IN); const secret = process.env.JWT_SECRET; diff --git a/apps/backend/src/core/config/registers/rate-limit.register.ts b/apps/backend/src/core/config/registers/rate-limit.register.ts index 16fd8b0..9ead23c 100644 --- a/apps/backend/src/core/config/registers/rate-limit.register.ts +++ b/apps/backend/src/core/config/registers/rate-limit.register.ts @@ -1,17 +1,20 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { RateLimit } from "../types/rate-limit.type"; +import type { RateLimitRegisterType } from "../types/rate-limit.register.type"; -export const rateLimit = registerAs(CONFIG_KEY.rateLimit, (): RateLimit => { - const limit = Number(process.env.THROTTLE_LIMIT); - const ttl = Number(process.env.THROTTLE_TTL); +export const rateLimitRegister = registerAs( + CONFIG_KEY.rateLimit, + (): RateLimitRegisterType => { + const limit = Number(process.env.THROTTLE_LIMIT); + const ttl = Number(process.env.THROTTLE_TTL); - if (!limit || !ttl) { - throw new Error("Missing some envs"); - } + if (!limit || !ttl) { + throw new Error("Missing some envs"); + } - return { - limit, - ttl, - }; -}); + return { + limit, + ttl, + }; + }, +); diff --git a/apps/backend/src/core/config/registers/s3.register.ts b/apps/backend/src/core/config/registers/s3.register.ts index 0cc7561..13beb58 100644 --- a/apps/backend/src/core/config/registers/s3.register.ts +++ b/apps/backend/src/core/config/registers/s3.register.ts @@ -1,8 +1,8 @@ import { registerAs } from "@nestjs/config"; import { CONFIG_KEY } from "../../../common/constants/config-key.constant"; -import type { S3 } from "../types/s3.type"; +import type { S3RegisterType } from "../types/s3.register.type"; -export const s3 = registerAs(CONFIG_KEY.s3, (): S3 => { +export const s3Register = registerAs(CONFIG_KEY.s3, (): S3RegisterType => { const awsRegion = process.env.AWS_REGION; const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; diff --git a/apps/backend/src/core/config/types/app.type.ts b/apps/backend/src/core/config/types/app.register.type.ts similarity index 77% rename from apps/backend/src/core/config/types/app.type.ts rename to apps/backend/src/core/config/types/app.register.type.ts index e0ac290..a5e622b 100644 --- a/apps/backend/src/core/config/types/app.type.ts +++ b/apps/backend/src/core/config/types/app.register.type.ts @@ -1,4 +1,4 @@ -type App = { +type AppRegisterType = { appPort: number; appRequestTimeout: number; appName: string; @@ -9,4 +9,4 @@ type App = { appCorsOrigin: string; }; -export type { App }; +export type { AppRegisterType }; diff --git a/apps/backend/src/core/config/types/cache.register.type.ts b/apps/backend/src/core/config/types/cache.register.type.ts new file mode 100644 index 0000000..efe3037 --- /dev/null +++ b/apps/backend/src/core/config/types/cache.register.type.ts @@ -0,0 +1,5 @@ +type CacheRegisterType = { + redisUrl: string; +}; + +export type { CacheRegisterType }; diff --git a/apps/backend/src/core/config/types/cache.type.ts b/apps/backend/src/core/config/types/cache.type.ts deleted file mode 100644 index dfbff07..0000000 --- a/apps/backend/src/core/config/types/cache.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type Cache = { - redisUrl: string; -}; - -export type { Cache }; diff --git a/apps/backend/src/core/config/types/database.register.type.ts b/apps/backend/src/core/config/types/database.register.type.ts new file mode 100644 index 0000000..acf12b5 --- /dev/null +++ b/apps/backend/src/core/config/types/database.register.type.ts @@ -0,0 +1,5 @@ +type DatabaseRegisterType = { + postgresUrl: string; +}; + +export type { DatabaseRegisterType }; diff --git a/apps/backend/src/core/config/types/database.type.ts b/apps/backend/src/core/config/types/database.type.ts deleted file mode 100644 index 0aa15a0..0000000 --- a/apps/backend/src/core/config/types/database.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type Database = { - postgresUrl: string; -}; - -export type { Database }; diff --git a/apps/backend/src/core/config/types/environment.register.type.ts b/apps/backend/src/core/config/types/environment.register.type.ts new file mode 100644 index 0000000..56be19d --- /dev/null +++ b/apps/backend/src/core/config/types/environment.register.type.ts @@ -0,0 +1,5 @@ +type EnvironmentRegisterType = { + nodeEnv: string; +}; + +export type { EnvironmentRegisterType }; diff --git a/apps/backend/src/core/config/types/environment.type.ts b/apps/backend/src/core/config/types/environment.type.ts deleted file mode 100644 index 8e69ea4..0000000 --- a/apps/backend/src/core/config/types/environment.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type Environment = { - nodeEnv: string; -}; - -export type { Environment }; diff --git a/apps/backend/src/core/config/types/jwt.register.type.ts b/apps/backend/src/core/config/types/jwt.register.type.ts new file mode 100644 index 0000000..bba5346 --- /dev/null +++ b/apps/backend/src/core/config/types/jwt.register.type.ts @@ -0,0 +1,6 @@ +type JwtRegisterType = { + secret: string; + expiresIn: number; +}; + +export type { JwtRegisterType }; diff --git a/apps/backend/src/core/config/types/jwt.type.ts b/apps/backend/src/core/config/types/jwt.type.ts deleted file mode 100644 index 15af51f..0000000 --- a/apps/backend/src/core/config/types/jwt.type.ts +++ /dev/null @@ -1,6 +0,0 @@ -type Jwt = { - secret: string; - expiresIn: number; -}; - -export type { Jwt }; diff --git a/apps/backend/src/core/config/types/rate-limit.register.type.ts b/apps/backend/src/core/config/types/rate-limit.register.type.ts new file mode 100644 index 0000000..4a52385 --- /dev/null +++ b/apps/backend/src/core/config/types/rate-limit.register.type.ts @@ -0,0 +1,6 @@ +type RateLimitRegisterType = { + ttl: number; + limit: number; +}; + +export type { RateLimitRegisterType }; diff --git a/apps/backend/src/core/config/types/rate-limit.type.ts b/apps/backend/src/core/config/types/rate-limit.type.ts deleted file mode 100644 index dfc5dff..0000000 --- a/apps/backend/src/core/config/types/rate-limit.type.ts +++ /dev/null @@ -1,6 +0,0 @@ -type RateLimit = { - ttl: number; - limit: number; -}; - -export type { RateLimit }; diff --git a/apps/backend/src/core/config/types/s3.type.ts b/apps/backend/src/core/config/types/s3.register.type.ts similarity index 65% rename from apps/backend/src/core/config/types/s3.type.ts rename to apps/backend/src/core/config/types/s3.register.type.ts index 6685103..cf22f49 100644 --- a/apps/backend/src/core/config/types/s3.type.ts +++ b/apps/backend/src/core/config/types/s3.register.type.ts @@ -1,8 +1,8 @@ -type S3 = { +type S3RegisterType = { awsRegion: string; awsAccessKeyId: string; awsSecretAccessKey: string; awsS3BucketName: string; }; -export type { S3 }; +export type { S3RegisterType }; diff --git a/apps/backend/src/core/database/database.service.ts b/apps/backend/src/core/database/database.service.ts index f495d8a..a001697 100644 --- a/apps/backend/src/core/database/database.service.ts +++ b/apps/backend/src/core/database/database.service.ts @@ -8,7 +8,7 @@ import { ConfigService } from "@nestjs/config"; import { PrismaPg } from "@prisma/adapter-pg"; import { PrismaClient } from "../../../prisma/generated/client.js"; import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; -import type { Database } from "../config/types/database.type.js"; +import type { DatabaseRegisterType } from "../config/types/database.register.type.js"; @Injectable() export class DatabaseService @@ -16,7 +16,9 @@ export class DatabaseService implements OnModuleInit, OnModuleDestroy { constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const prismaConfig = configService.getOrThrow(CONFIG_KEY.prisma); + const prismaConfig = configService.getOrThrow( + CONFIG_KEY.prisma, + ); const adapter: PrismaPg = new PrismaPg({ connectionString: prismaConfig.postgresUrl, diff --git a/apps/backend/src/core/jwt/jwt.module.ts b/apps/backend/src/core/jwt/jwt.module.ts index 4bdb37b..30ea61b 100644 --- a/apps/backend/src/core/jwt/jwt.module.ts +++ b/apps/backend/src/core/jwt/jwt.module.ts @@ -2,7 +2,7 @@ import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { JwtModule as CoreJwtModule, type JwtModuleOptions } from "@nestjs/jwt"; import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; -import type { Jwt } from "../config/types/jwt.type.js"; +import type { JwtRegisterType } from "../config/types/jwt.register.type.js"; @Module({ imports: [ @@ -10,7 +10,9 @@ import type { Jwt } from "../config/types/jwt.type.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService): JwtModuleOptions => { - const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); + const jwtConfig = configService.getOrThrow( + CONFIG_KEY.jwt, + ); return { secret: jwtConfig.secret, diff --git a/apps/backend/src/core/rate-limit/rate-limit.module.ts b/apps/backend/src/core/rate-limit/rate-limit.module.ts index ef5ac6d..76e1405 100644 --- a/apps/backend/src/core/rate-limit/rate-limit.module.ts +++ b/apps/backend/src/core/rate-limit/rate-limit.module.ts @@ -3,7 +3,7 @@ import { ConfigModule, ConfigService } from "@nestjs/config"; import { APP_GUARD } from "@nestjs/core"; import { seconds, ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler"; import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; -import type { RateLimit } from "../config/types/rate-limit.type.js"; +import type { RateLimitRegisterType } from "../config/types/rate-limit.register.type.js"; @Module({ imports: [ @@ -11,7 +11,7 @@ import type { RateLimit } from "../config/types/rate-limit.type.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const rateLimitConfig = configService.getOrThrow( + const rateLimitConfig = configService.getOrThrow( CONFIG_KEY.rateLimit, ); diff --git a/apps/backend/src/core/redis/redis.module.ts b/apps/backend/src/core/redis/redis.module.ts index d2fe9d0..b94423f 100644 --- a/apps/backend/src/core/redis/redis.module.ts +++ b/apps/backend/src/core/redis/redis.module.ts @@ -2,7 +2,7 @@ import { Module } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { RedisModule as CoreRedisModule } from "@nestjs-modules/ioredis"; import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; -import type { Cache } from "../config/types/cache.type.js"; +import type { CacheRegisterType } from "../config/types/cache.register.type.js"; import { RedisService } from "./redis.service.js"; @Module({ @@ -12,7 +12,9 @@ import { RedisService } from "./redis.service.js"; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const redisConfig = configService.getOrThrow(CONFIG_KEY.redis); + const redisConfig = configService.getOrThrow( + CONFIG_KEY.redis, + ); return { options: { diff --git a/apps/backend/src/core/s3/s3.service.ts b/apps/backend/src/core/s3/s3.service.ts index 34c0c3b..5ed7cb8 100644 --- a/apps/backend/src/core/s3/s3.service.ts +++ b/apps/backend/src/core/s3/s3.service.ts @@ -9,7 +9,7 @@ import { import { Inject, Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { CONFIG_KEY } from "../../common/constants/config-key.constant"; -import type { S3 } from "../config/types/s3.type"; +import type { S3RegisterType } from "../config/types/s3.register.type"; @Injectable() export class S3Service { @@ -18,7 +18,7 @@ export class S3Service { private readonly region: string; constructor(@Inject(ConfigService) readonly configService: ConfigService) { - const s3Config = configService.getOrThrow(CONFIG_KEY.s3); + const s3Config = configService.getOrThrow(CONFIG_KEY.s3); this.s3Client = new S3Client({ credentials: { diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts index f084684..9f3e878 100644 --- a/apps/backend/src/main.ts +++ b/apps/backend/src/main.ts @@ -15,8 +15,8 @@ import { ENVIRONMENTS } from "./common/constants/environments.constant.js"; import { CatchEverythingFilter } from "./common/filters/catch-everything.filter.js"; import { LoggingInterceptor } from "./common/interceptors/logger.interceptor.js"; import { TimeoutInterceptor } from "./common/interceptors/timeout.interceptor.js"; -import type { App } from "./core/config/types/app.type.js"; -import type { Environment } from "./core/config/types/environment.type.js"; +import type { AppRegisterType } from "./core/config/types/app.register.type.js"; +import type { EnvironmentRegisterType } from "./core/config/types/environment.register.type.js"; const logger: Logger = new Logger("Bootstrap"); @@ -25,13 +25,13 @@ const logger: Logger = new Logger("Bootstrap"); const configService = app.get(ConfigService); - const environmentConfig = configService.getOrThrow( + const environmentConfig = configService.getOrThrow( CONFIG_KEY.environment, ); const isProduction = environmentConfig.nodeEnv === ENVIRONMENTS.production; - const appConfig = configService.getOrThrow(CONFIG_KEY.app); + const appConfig = configService.getOrThrow(CONFIG_KEY.app); app.enableVersioning({ defaultVersion: "1", diff --git a/apps/backend/src/modules/auth/auth.service.ts b/apps/backend/src/modules/auth/auth.service.ts index d1f51a2..528b0d4 100644 --- a/apps/backend/src/modules/auth/auth.service.ts +++ b/apps/backend/src/modules/auth/auth.service.ts @@ -3,8 +3,8 @@ import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; import { genSalt, hash } from "bcrypt"; import { CONFIG_KEY } from "../../common/constants/config-key.constant.js"; -import type { AuthPayload } from "../../common/types/auth-payload.type.js"; -import type { Jwt } from "../../core/config/types/jwt.type.js"; +import type { AuthPayloadType } from "../../common/types/auth-payload.type.js"; +import type { JwtRegisterType } from "../../core/config/types/jwt.register.type.js"; import { AuthRepository } from "./auth.repository.js"; import type { SignUpDto } from "./dtos/sign-up.dto.js"; import { AuthRdo } from "./rdos/auth.rdo.js"; @@ -18,7 +18,7 @@ export class AuthService { @Inject(AuthRepository) private readonly authRepository: AuthRepository, @Inject(ConfigService) readonly configService: ConfigService, ) { - const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); + const jwtConfig = configService.getOrThrow(CONFIG_KEY.jwt); this.jwtSecret = jwtConfig.secret; } @@ -48,10 +48,13 @@ export class AuthService { return new AuthRdo(token); } - public async validateToken(token: string): Promise { - const authPayload = await this.jwtService.verifyAsync(token, { - secret: this.jwtSecret, - }); + public async validateToken(token: string): Promise { + const authPayload = await this.jwtService.verifyAsync( + token, + { + secret: this.jwtSecret, + }, + ); return { userId: authPayload.userId,