-
Notifications
You must be signed in to change notification settings - Fork 71
Feat/delete unused shared folders #139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/delete unused shared folders #139
Conversation
WalkthroughThis change completes the migration to a modular architecture by deleting obsolete shared folders, introducing stub controllers for all major modules, updating import paths, and standardizing code formatting. It adds a new integration test to verify system boot and module structure, and ensures all references to legacy folders are removed. Minor stylistic and formatting changes are applied throughout the codebase. Changes
Sequence Diagram(s)sequenceDiagram
participant TestRunner as Integration Test
participant App as Application Entry (index.ts)
participant Modules as Modular Directories
participant FS as File System
TestRunner->>App: Import main application (index.ts)
App->>Modules: Resolve module imports
App->>FS: Check for required module directories
App->>FS: Ensure legacy folders are deleted
FS-->>App: Directory existence/absence confirmed
App-->>TestRunner: Startup/import success or error
TestRunner->>TestRunner: Validate boot and modular structure
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 24
🔭 Outside diff range comments (5)
src/modules/wallet/repositories/HorizonWalletRepository.ts (1)
40-52: Broaden error typing – avoid assumingerror.responseshape
errorcoming fromstellar-sdkis not guaranteed to exposeresponse.status; accessing it unsafely may throw a secondary error and mask the root cause.- } catch (error: any) { + } catch (error: unknown) { + // Type guard for axios-like errors + if ( + typeof error === "object" && + error !== null && + "response" in error && + (error as any).response?.status === 404 + ) { + return WalletVerification.createValid(address.value, false, "0", "0"); + } + + const message = + error instanceof Error ? error.message : "Unknown error occurred"; + return WalletVerification.createInvalid( + address.value, + `Wallet verification failed: ${message}` + ); + } + + // Old path retained for reference - // Handle different types of errors - if (error.response && error.response.status === 404) { - // Account not found - this is valid, just means account doesn't exist yet - return WalletVerification.createValid(address.value, false, "0", "0"); - } - - // Other errors indicate invalid wallet or network issues - return WalletVerification.createInvalid( - address.value, - `Wallet verification failed: ${error.message}` - ); - } + }src/modules/auth/use-cases/email-verification.usecase.ts (1)
13-21: Hard-coded host makes deployment-time configuration impossible
The verification link is frozen tohttp://localhost:3000, preventing it from working in staging / prod.- const verificationLink = `http://localhost:3000/auth/verify-email?token=${token}`; + const verificationLink = `${process.env.FRONTEND_BASE_URL}/auth/verify-email?token=${token}`;Expose
FRONTEND_BASE_URL(or similar) via env vars / config service so the same code runs in every environment.src/modules/auth/utils/email.utils.ts (1)
16-24: Harden transporter configuration
parseInt(process.env.EMAIL_PORT)may returnNaNwhen the variable is mis-configured, andprocess.env.EMAIL_HOSTcan beundefined, both silently propagating to nodemailer.- host: process.env.EMAIL_HOST, - port: parseInt(process.env.EMAIL_PORT || "587"), - secure: process.env.EMAIL_SECURE === "true", + host: process.env.EMAIL_HOST ?? "localhost", + port: (() => { + const port = Number(process.env.EMAIL_PORT); + return Number.isFinite(port) ? port : 587; + })(), + secure: process.env.EMAIL_SECURE === "true",Fail fast (or at least log) when mandatory env vars are missing to avoid silent misconfiguration.
src/middlewares/auth.middleware.ts (1)
36-43: Hard-coded fallback JWT secret weakens securityRelying on a default
"default_secret"whenprocess.env.JWT_SECRETis absent silently downgrades security and makes it easy to boot the app with a predictable secret in non-dev environments.-const secret = process.env.JWT_SECRET || "default_secret"; +const secret = process.env.JWT_SECRET; +if (!secret) { + // Fail fast – running without a JWT secret is unsafe. + return res + .status(500) + .json({ message: "JWT secret misconfiguration" }); +}Fail-fast behaviour prevents the service from unknowingly running with an insecure secret.
src/modules/auth/use-cases/verify-email.usecase.ts (1)
10-53: Catch block swallows domain errorsRe-throwing a generic
"Invalid or expired verification token"masks genuine infrastructure errors (DB outage, etc.) and loses the"Verification token has expired"message you purposely throw above.Either remove the
try/catchcompletely or preserve the original error when it is already meaningful:- try { - ... - } catch (error) { - throw new Error("Invalid or expired verification token"); - } + try { + ... + } catch (error) { + if (error instanceof Error && error.message) { + throw error; // keep original domain/infrastructure reason + } + throw new Error("Invalid or expired verification token"); + }
🧹 Nitpick comments (49)
src/modules/messaging/domain/entities/message.entity.ts (1)
1-35: Minor idiomatic TypeScript improvement – leverage parameter propertiesPurely optional, but using parameter properties trims boilerplate and keeps the entity class concise:
-export class Message { - id: string; - content: string; - sentAt: Date; - readAt: Date | null; - senderId: string; - receiverId: string; - volunteerId: string; - - constructor( - id: string, - content: string, - sentAt: Date, - readAt: Date | null, - senderId: string, - receiverId: string, - volunteerId: string - ) { - this.id = id; - this.content = content; - this.sentAt = sentAt; - this.readAt = readAt; - this.senderId = senderId; - this.receiverId = receiverId; - this.volunteerId = volunteerId; - } +export class Message { + constructor( + public readonly id: string, + public content: string, + public readonly sentAt: Date, + public readAt: Date | null, + public readonly senderId: string, + public readonly receiverId: string, + public readonly volunteerId: string, + ) {}This keeps the functionality identical while reducing ~20 lines.
Feel free to keep current style if you prefer explicit assignments.src/modules/volunteer/application/errors/index.ts (1)
1-7: String-delimiter switch is fine; consider star-export for brevityCurrent explicit re-export works, but a wildcard keeps the barrel file maintenance-free:
-export { - VolunteerRegistrationError, - VolunteerPositionFullError, - VolunteerAlreadyRegisteredError, - VolunteerNotFoundError, -} from "./volunteer-registration.errors"; +export * from "./volunteer-registration.errors";Purely stylistic – choose whichever aligns with your conventions.
src/config/soroban.config.ts (1)
10-13: Avoid throwing at import-time – defer env validation to bootstrapThrowing here breaks unit tests or scripts that merely import the module without needing Soroban, and it prevents stubbing the config in test environments. Prefer exporting a validation helper or performing the check during application bootstrap.
// Validate required environment variables -if (!sorobanConfig.serverSecret) { - throw new Error("SOROBAN_SERVER_SECRET environment variable is required"); -} +export function assertSorobanEnv(): void { + if (!sorobanConfig.serverSecret) { + throw new Error("SOROBAN_SERVER_SECRET environment variable is required"); + } +}Call
assertSorobanEnv()inside the actual startup path instead of at module load.src/modules/user/domain/entities/user-volunteer.entity.ts (1)
22-24:joinedAtis set manually despite@CreateDateColumn
@CreateDateColumn()will populate the column automatically on insert. Manually assigningjoinedAt = new Date()is redundant and can cause discrepancies if the entity instance is reused or not persisted immediately.- userVolunteer.joinedAt = new Date();Let TypeORM handle the timestamp for consistency.
src/modules/shared/domain/entities/base.entity.ts (1)
25-35:equalsimplementation is brittle and expensiveSerialising with
JSON.stringify:
- Ignores non-enumerable properties and ordering differences.
- Becomes O(n) for each comparison, impacting performance on large aggregates.
If identity equality is sufficient, compare primary keys; otherwise leverage a deep-equal helper.
- return JSON.stringify(this.props) === JSON.stringify(entity.props); + // Fast path: entity identity or primary key + // Fallback: deep comparison via util.inspect or a lightweight deep-equal libConsider revisiting this design; it affects every domain entity.
src/modules/wallet/domain/value-objects/StellarAddress.ts (1)
8-8: Consider surfacing the caught validation error for easier debuggingThe empty
catchblocks intentionally swallow the specific@stellar/stellar-sdkparsing error. In production this makes sense, but during debugging it can be useful to log or re-wrap the original reason (e.g., checksum failure vs. invalid length).- } catch { - return false; + } catch (e) { + // Optional: keep silent in production, but enable trace in non-prod + if (process.env.NODE_ENV !== "production") { + console.debug("Stellar address validation error:", e); + } + return false; }Also applies to: 12-12, 35-35
src/modules/shared/__tests__/domain/entities/test-item.entity.test.ts (1)
1-1: Prefer path aliases in tests to avoid brittle relative imports
../../../domain/entities/test-item.entityis hard to maintain if the folder depth changes.
Since the project already uses TS, consider a@modules/*path alias (configured intsconfig.jsonand Jest) for cleaner test imports.-import { TestItem } from "../../../domain/entities/test-item.entity"; +import { TestItem } from "@modules/shared/domain/entities/test-item.entity";src/modules/wallet/repositories/HorizonWalletRepository.ts (2)
17-19:networkPassphraseis calculated but never usedThe field adds cognitive overhead and may get out-of-sync with future network selection. Remove it until it is actually required.
- // Set network passphrase based on configuration - this.networkPassphrase = - horizonConfig.network === "mainnet" ? Networks.PUBLIC : Networks.TESTNET;
82-87: Add explicit return type forextractNativeBalanceHelps callers & IDEs know it is a string.
- private extractNativeBalance(balances: any[]): string { + private extractNativeBalance(balances: Horizon.BalanceLine[]): string {src/modules/project/domain/entities/project.entity.ts (1)
45-55: Introduce domain-specific exceptions instead ofErrorThrowing raw
Errorobjects couples the domain layer to generic JS/TS errors and makes HTTP→domain mappings harder.
Consider defining aProjectDomainError(or re-using a sharedDomainError) and throwing that fromactivate,complete, andcancel. It keeps invariants explicit and lets consumers handle failures in a type-safe way.-throw new Error("Only draft projects can be activated"); +throw new ProjectDomainError("Only draft projects can be activated");Same adjustment for the other two guards.
This is purely an API-surface change—behaviour stays intact while improving maintainability and testability.Also applies to: 59-62
src/modules/wallet/services/WalletService.ts (1)
43-48: Avoid swallowing verification errors silently
catch {}hides the underlying cause and complicates debugging.
At minimum, log the error (or forward it to an injected logger) before returningfalse.- } catch { - return false; + } catch (err) { + // TODO: replace console with your structured logger + console.warn("Wallet validation failed:", err); + return false; }src/modules/nft/use-cases/createNFT.ts (1)
2-2: Alias may blur intent—consider keeping explicit names
import { NFTDomain as NFT } …hides the “domain” context, potentially confusing future readers when the sameNFTname appears in persistence or API layers. Prefer either:import { NFTDomain } from "../domain/entities/nft.entity"; // … const nft = new NFTDomain(/* … */);or rename the underlying class to
NFTat source to avoid aliasing.src/repository/IPhotoRepository.ts (1)
1-1: Interface sits outside the module it belongs to
IPhotoRepositorynow imports the Photo entity from thephotomodule, creating an inward dependency. For cleaner boundaries move this interface undersrc/modules/photo/repositoriesso the module is self-contained.src/modules/project/use-cases/UpdateProjectUseCase.ts (1)
11-13: Throw a domain-specific error instead of genericErrorA plain
Errormakes upstream handling ambiguous.
Introduce a typedProjectNotFoundError(or reuse an existingNotFoundError) to improve error semantics and HTTP mapping.- if (!project) { - throw new Error("Project not found"); + if (!project) { + throw new ProjectNotFoundError(id); }src/modules/project/index.ts (1)
1-4: Remove (or enable) the commented Prisma export to prevent stale referencesLine 3 is a lingering comment from the previous setup. Leaving dead code around the public barrel can mislead newcomers and tooling that parses comments. Either:
- Delete the line, or
- Re-export the actual implementation once the repository becomes active again.
No functional impact, just tidying.
src/modules/wallet/dto/WalletVerificationRequestDto.ts (1)
1-9: Extract regex & message into shared constants for reuseThe long regex and verbose error message are duplicated across tests and use-cases. Exporting them from a
wallet.constants.ts(or similar) avoids divergence if the regex ever changes.src/modules/auth/utils/email.utils.ts (1)
37-39: Preserve original error contextRethrowing a new
Errordiscards the stack and root cause, complicating debugging. Wrap or append the original error instead.- throw new Error("Error sending email"); + throw new Error(`Error sending email: ${(error as Error).message}`);src/config/horizon.config.ts (2)
11-14: Redundant URL validation – safe to drop
horizonConfig.urlcan never be falsy, because the fallback literal is used wheneverprocess.env.HORIZON_URLisundefinedor an empty string ('' || fallback→fallback).
The guard therefore cannot be triggered and just adds noise.-// Validate required environment variables -if (!horizonConfig.url) { - throw new Error("HORIZON_URL environment variable is required"); -}
17-22: Make network check case-insensitiveOperators may export
STELLAR_NETWORK=TestNetorMAINNET. Normalising once avoids surprising boot-time errors.-const validNetworks = ["testnet", "mainnet"]; -if (!validNetworks.includes(horizonConfig.network)) { +const validNetworks = ["testnet", "mainnet"]; +const network = horizonConfig.network.toLowerCase(); +if (!validNetworks.includes(network)) { throw new Error( `STELLAR_NETWORK must be one of: ${validNetworks.join(", ")}` ); } + +horizonConfig.network = network; // keep downstream usage consistentsrc/modules/volunteer/domain/entities/volunteer.entity.ts (1)
50-75:update()silently ignoresprojectIdchangesDomain events such as moving a volunteer to another project appear unsupported.
If this is intentional, add a comment; otherwise include the field with the same validation as increate().- if (props.projectId !== undefined) { - if (!props.projectId.trim()) { - throw new Error("Project ID is required"); - } - this.projectId = props.projectId; - }src/modules/messaging/routes/messaging.routes.ts (1)
8-12: Share a single PrismaClient instead of instantiating per-moduleCreating a new
PrismaClienthere (and in every route file that follows the same pattern) can exhaust the database connection pool and slows cold-start time in serverless environments. Prefer injecting a singleton that is initialised once at app bootstrap or expose a centralgetPrisma()helper.src/modules/user/domain/interfaces/IUserRepository.ts (1)
14-18: Return typeanyhides contract guarantees
setVerificationTokencurrently returnsPromise<any>. Prefer a precise type (void, the updatedIUser, or a DTO) so callers don’t rely on opaque values and static analysis remains useful.src/modules/metrics/controllers/MetricsController.ts (1)
20-22: Replaceconsole.errorwith centralized logger & avoid duplicating hard-coded messagesDirect
console.errorcalls scatter log formatting & make log aggregation harder.
Consider injecting the project-level logger (e.g.src/utils/logger.ts) and centralising the error messages in an i18n/constant file so that all controllers share the same wording.-import { Request, Response } from "express"; +import { Request, Response } from "express"; +import { logger } from "@/utils/logger"; ... - console.error("Error al obtener métricas globales:", error); + logger.error("metrics:getGlobalMetrics failed", error); ... - console.error("Error al obtener métricas del proyecto:", error); + logger.error("metrics:getProjectMetrics failed", error); ... - console.error("Error al obtener métricas de la organización:", error); + logger.error("metrics:getOrganizationMetrics failed", error);This both standardises output and future-proofs for observability pipelines.
Also applies to: 46-50, 75-80
src/modules/nft/domain/entities/nft.entity.ts (1)
38-45: Use domain-specific error instead of genericErrorinmintThrowing
new Error("NFT is already minted")couples domain logic to generic JS errors, obscuring intent upstream. Define a customNFTAlreadyMintedError(or reuse a sharedDomainError) so callers can catch it explicitly.- if (this.isMinted) { - throw new Error("NFT is already minted"); - } + if (this.isMinted) { + throw new NFTAlreadyMintedError(this.id); + }This improves type–safety and keeps invariants explicit.
src/modules/messaging/services/MessagingService.ts (1)
55-63: Surface domain-specific errors for authorisation & state checksAll guards throw bare
Errorinstances with user-facing strings. Prefer custom errors (UnauthorizedError,DomainValidationError, etc.) to:
- Distinguish expected vs. unexpected failures.
- Map cleanly to HTTP status codes at the middleware layer.
- Avoid exposing internal wording to clients.
Adopting this pattern now will save defensive string matching later.
Also applies to: 88-93
src/modules/wallet/use-cases/VerifyWalletUseCase.ts (1)
21-25: Wrap unknown error types explicitly & re-throw domain error
catch (error: any)silently assumeserror.messageexists. Narrow the type & normalise:} catch (unknownErr) { const err = unknownErr instanceof Error ? unknownErr : new Error(String(unknownErr)); return WalletVerificationResponseDto.createError( dto.walletAddress, err.message ?? "Wallet verification failed", ); }Prevents “cannot read property message of undefined” edge cases.
src/modules/nft/repositories/nft.repository.ts (1)
18-26: Prefer leveraging Prisma return types instead ofas unknown ascastsCasting the result of Prisma operations twice bypasses compile-time safety.
Instead, let Prisma infer types or usePrisma.NFTGetPayload. Example:import { Prisma, PrismaClient } from "@prisma/client"; type PrismaNFT = Prisma.NFTGetPayload<{}> ... const newNFT = await this.prisma.nFT.create({ data: { ... } });Eliminates unsafe casts and keeps types in sync with schema.
Also applies to: 37-40, 83-88
src/middlewares/auth.middleware.ts (1)
53-53: Avoid double-export – pick named OR defaultThe middleware is already exported as the constant
optionalAuthMiddleware. Re-exporting it as default offers no benefit and encourages mixed import styles.-export default optionalAuthMiddleware; +// Prefer single export style to keep imports consistent: +// export { optionalAuthMiddleware };src/modules/wallet/domain/entities/WalletVerification.ts (1)
14-16: Consider numeric domain types for balance & sequence
balanceandsequencerepresent numeric values but are stored as strings, pushing parsing/validation responsibilities downstream and risking runtime mistakes.If precision is required, introduce value objects (e.g.,
BigNumber) or at least opaque types to retain numeric semantics while preserving precision.src/modules/wallet/__tests__/VerifyWalletUseCase.test.ts (2)
86-90: Prefer rejecting withErrorinstances, not plain strings
mockRejectedValue(new Error(errorMessage))is the right pattern (as used above). For the unknown error test further below a plain string is supplied – consider being consistent and always reject withErrorto avoidinstanceof Errorguard failures inside the use-case.
104-111: String rejection can hide stack tracesHere a raw string is injected (
mockRejectedValue("Unknown error")). UsingError("Unknown error")preserves stack information and is closer to real‐world failures.-mockWalletRepository.verifyWallet.mockRejectedValue("Unknown error"); +mockWalletRepository.verifyWallet.mockRejectedValue( + new Error("Unknown error") +);src/modules/user/repositories/PrismaUserRepository.ts (2)
1-6: One PrismaClient per process, not per module importInstantiating
new PrismaClient()at module top-level causes every repository (or test run with isolated modules) to create a new DB connection pool. Prefer a shared singleton or leverage theglobalThiscaching pattern recommended in Prisma docs to avoid exhausting DB connections in serverless / test environments.
48-60: Return updated record or boolean for easier testing / chaining
setVerificationTokenperforms an update but resolves tovoid. Returning the updated row (or at least a boolean) would let callers assert success without an extra read. Prisma supportsreturningwithselect:- ): Promise<void> { - await prisma.user.update({ + ): Promise<{ id: string } | null> { + return prisma.user.update({ where: { id: userId }, data: { verificationToken: token, verificationTokenExpires: expires, }, }); }src/modules/photo/domain/entities/photo.entity.ts (1)
20-22:metadatashould be typed asRecord<string, unknown>Using
anydefeats type-safety. Consider:- metadata?: Record<string, any>; + metadata?: Record<string, unknown>;src/examples/sorobanExample.ts (1)
1-10: Dead-code example exports a no-op – consider removal or explicit deprecationThe function is now a stub that only logs. Shipping disabled examples can confuse consumers (they import it expecting behaviour). Either:
- Remove the file until the service is restored, or
- Mark the export as deprecated and throw to prevent accidental use.
-async function sorobanExample() { - console.log("Soroban example disabled due to service migration"); +/** + * @deprecated SorobanService has been removed during migration. + * This function is left as a placeholder and will throw if invoked. + */ +async function sorobanExample(): Promise<never> { + throw new Error( + "sorobanExample is disabled – SorobanService is being migrated." + ); }src/repository/IUserRepository.ts (1)
4-9: Bulky parameter list – favour a cohesive DTOPassing four primitives encourages parameter order bugs. Define a lightweight
CreateUserDTO(or reuse an entity) and accept a single argument:createUser(dto: CreateUserDTO): Promise<User>;This scales better if more fields are added later.
src/modules/wallet/__tests__/WalletAuthIntegration.test.ts (1)
4-6: Mock path should match the fixed importAfter adjusting the
WalletServiceimport above, keep the mock path in sync; otherwise Jest will mock a different module instance than the one actually imported.src/middlewares/traceId.middleware.ts (2)
32-34: Return type annotation missing
getTraceIdreturnsstring, but whenreq.traceIdis absent you return the literal"NO-TRACE-ID", which is fine yet may pollute logs.
Consider returningundefinedand letting the caller decide on a fallback, or move the sentinel constant to aconstfor easier filtering.
40-51: Minor: avoid spreading large objects in hot path
createTraceContextuses the spread operator onadditionalContext, causing a shallow copy allocation on every request.
For middleware executed per request this can add measurable GC pressure under load. UseObject.assignwith predefined keys for a cheaper path.src/middlewares/errorHandler.ts (1)
27-39: Remove unused errorInfo object.The
errorInfoobject is created but no longer used after the logger refactor. The same information is now passed directly to the logger call.- // Log error information - const errorInfo: ErrorLogInfo = { - timestamp: new Date().toISOString(), - path: req.path, - method: req.method, - error: err.message, - }; - - // In development, include more details - if (process.env.NODE_ENV === "development") { - errorInfo.stack = err.stack; - errorInfo.requestBody = req.body; - errorInfo.requestQuery = req.query; - }You can also remove the
ErrorLogInfointerface (lines 10-18) if it's no longer needed elsewhere.src/modules/metrics/services/MetricsService.ts (1)
41-66: Repeated try/catch boilerplate around Redis operationsEvery get/set replicates identical error-handling code.
Consider extracting helper methodssafeGetandsafeSetto encapsulate the try/catch and keep the service logic focused.src/middleware/authMiddleware.ts (1)
89-94:req.traceIdmay be undefined
req.traceIdis referenced in the 500 handler but is not guaranteed to exist unless an upstream middleware adds it.
Add a type-guard or fallback to avoidundefinedproperties leaking into JSON.- ...(req.traceId && { traceId: req.traceId }), + ...(typeof (req as any).traceId === "string" && { + traceId: (req as any).traceId, + }),src/modules/nft/presentation/controllers/NFTController.stub.ts (2)
3-7: Track the TODO in an issue.The TODO comment indicates this stub needs proper implementation. Consider creating a GitHub issue to track the implementation of the proper NFT controller using the new modular architecture.
Would you like me to help create an issue template for tracking the NFT controller implementation?
38-38: Consider consistency in export patterns.This controller exports an instantiated object, while the UserController stub exports the class directly. Consider standardizing the export pattern across all stub controllers for consistency.
-export default new NFTController(); +export default NFTController;Or alternatively, update other stub controllers to match this pattern if instantiated exports are preferred.
src/modules/user/presentation/controllers/UserController.stub.ts (2)
3-7: Track the TODO in an issue.Similar to the NFT controller, this TODO should be tracked in a GitHub issue for implementing the proper user controller with the new modular architecture.
8-8: Export pattern inconsistency with other stubs.This controller exports the class directly, while the NFT controller exports an instantiated object. Consider standardizing the export pattern across all stub controllers.
Refer to the NFT controller comment - choose one pattern and apply consistently across all stub controllers.
src/modules/user/presentation/controllers/userVolunteer.controller.stub.ts (1)
38-38: Inconsistent export pattern with other stub controllers.This file exports a singleton instance (
new UserVolunteerController()), while other stub controllers in the PR export the class directly. Consider standardizing the export pattern across all stub controllers.-export default new UserVolunteerController(); +export default UserVolunteerController;src/modules/organization/presentation/controllers/OrganizationController.stub.ts (1)
8-50: Add explicit return type annotations and consider response format consistency.The stub controller implementation is appropriate for the migration phase. However, consider these improvements:
- Add explicit return type annotations for better type safety
- The response format should be consistent across all endpoints
-class OrganizationController { +class OrganizationController { - async createOrganization(req: Request, res: Response) { + async createOrganization(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } - async getAllOrganizations(req: Request, res: Response) { + async getAllOrganizations(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } - async getOrganizationById(req: Request, res: Response) { + async getOrganizationById(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } - async getOrganizationByEmail(req: Request, res: Response) { + async getOrganizationByEmail(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } - async updateOrganization(req: Request, res: Response) { + async updateOrganization(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } - async deleteOrganization(req: Request, res: Response) { + async deleteOrganization(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Organization service temporarily disabled during migration", error: "Service migration in progress" }); } }src/modules/auth/presentation/controllers/Auth.controller.stub.ts (1)
8-50: Add explicit return type annotations for consistency.The stub controller implementation follows the same pattern as the OrganizationController stub, which is good for consistency. However, it has the same missing return type annotations.
class AuthController { - async register(req: Request, res: Response) { + async register(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } - async login(req: Request, res: Response) { + async login(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } - async resendVerificationEmail(req: Request, res: Response) { + async resendVerificationEmail(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } - async verifyEmail(req: Request, res: Response) { + async verifyEmail(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } - async verifyWallet(req: Request, res: Response) { + async verifyWallet(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } - async validateWalletFormat(req: Request, res: Response) { + async validateWalletFormat(req: Request, res: Response): Promise<void> { res.status(501).json({ message: "Auth service temporarily disabled during migration", error: "Service migration in progress" }); } }
| // Note: TypeORM entities are now managed through Prisma schema | ||
| // This file is kept for backward compatibility but not actively used | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The “deprecated” data-source still boots and opens a DB connection
The comment says the file is “kept for backward compatibility but not actively used”, yet AppDataSource.initialize() still executes and tries to connect on every app start.
Besides wasting resources, this will crash the app if the legacy DB is no longer reachable.
Consider guarding the initialisation behind an env flag or removing it entirely.
-AppDataSource.initialize()
- .then(() => {
- console.log("Database connected successfully ✅");
- })
- .catch((error) => console.error("Database connection failed ❌", error));
+if (process.env.ENABLE_TYPEORM === "true") {
+ AppDataSource.initialize()
+ .then(() => console.log("TypeORM datasource initialised"))
+ .catch((err) => console.error("TypeORM init failed", err));
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Note: TypeORM entities are now managed through Prisma schema | |
| // This file is kept for backward compatibility but not actively used | |
| // Note: TypeORM entities are now managed through Prisma schema | |
| // This file is kept for backward compatibility but not actively used | |
| if (process.env.ENABLE_TYPEORM === "true") { | |
| AppDataSource.initialize() | |
| .then(() => console.log("TypeORM datasource initialised")) | |
| .catch((err) => console.error("TypeORM init failed", err)); | |
| } |
🤖 Prompt for AI Agents
In src/config/data-source.ts around lines 3 to 5, the deprecated data-source
still initializes and opens a database connection on every app start, which
wastes resources and risks crashing if the legacy DB is unreachable. To fix
this, wrap the AppDataSource.initialize() call in a conditional that checks an
environment variable flag to enable or disable this initialization, or remove
the initialization code entirely if backward compatibility is no longer needed.
| private static swaggerDocument = YAML.parse( | ||
| fs.readFileSync("./openapi.yaml", "utf8") | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Path resolution may break once compiled – resolve file location explicitly
After transpilation the compiled file lives in dist/config, so "./openapi.yaml" is no longer adjacent.
Resolve from the project root (or use process.cwd()), otherwise Swagger will fail to load outside the monorepo root.
-import fs from "fs";
+import fs from "fs";
+import path from "path";
- private static swaggerDocument = YAML.parse(
- fs.readFileSync("./openapi.yaml", "utf8")
- );
+ private static swaggerDocument = YAML.parse(
+ fs.readFileSync(
+ path.resolve(process.cwd(), "openapi.yaml"),
+ "utf8"
+ )
+ );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private static swaggerDocument = YAML.parse( | |
| fs.readFileSync("./openapi.yaml", "utf8") | |
| ); | |
| import fs from "fs"; | |
| import path from "path"; | |
| private static swaggerDocument = YAML.parse( | |
| fs.readFileSync( | |
| path.resolve(process.cwd(), "openapi.yaml"), | |
| "utf8" | |
| ) | |
| ); |
🤖 Prompt for AI Agents
In src/config/swagger.config.ts around lines 7 to 9, the relative path
"./openapi.yaml" will break after compilation because the compiled file moves to
dist/config. Fix this by resolving the file path explicitly from the project
root using an absolute path, for example by combining process.cwd() with the
filename, to ensure the YAML file is correctly located regardless of the current
working directory.
| const logsDir = path.join(process.cwd(), "logs"); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Create the logs directory if it is missing
logsDir is declared but the directory is never created.
In fresh environments (e.g., CI containers, new servers) every file transport will fail silently because Winston cannot open the target files.
+import fs from "fs";
...
const logsDir = path.join(process.cwd(), "logs");
+if (!fs.existsSync(logsDir)) {
+ fs.mkdirSync(logsDir, { recursive: true });
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const logsDir = path.join(process.cwd(), "logs"); | |
| import fs from "fs"; | |
| import path from "path"; | |
| // … other imports … | |
| const logsDir = path.join(process.cwd(), "logs"); | |
| if (!fs.existsSync(logsDir)) { | |
| fs.mkdirSync(logsDir, { recursive: true }); | |
| } | |
| // … rest of your Winston configuration … |
🤖 Prompt for AI Agents
In src/config/winston.config.ts around lines 17 to 18, the logs directory path
is defined but the directory itself is not created, which causes file transports
to fail silently in new environments. Add code to check if the logs directory
exists and create it if missing before any logging operations occur. Use
appropriate Node.js filesystem methods to synchronously or asynchronously ensure
the directory is present.
| if (!user) throw new Error("User not found"); | ||
| if (user.isVerified) throw new Error("User is already verified"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use domain-specific error classes instead of generic Error
Throwing plain Error objects makes it hard for the HTTP layer to translate the failure into the correct status code (404 vs 400, etc.) and leaks internal stack-traces.
- if (!user) throw new Error("User not found");
- if (user.isVerified) throw new Error("User is already verified");
+ if (!user) throw new NotFoundError("User not found");
+ if (user.isVerified) throw new BadRequestError("User is already verified");(You’ll need to import / define NotFoundError and BadRequestError, or reuse the project’s existing error hierarchy.)
🤖 Prompt for AI Agents
In src/modules/auth/use-cases/email-verification.usecase.ts around lines 10 to
11, replace the generic Error throws with domain-specific error classes like
NotFoundError for "User not found" and BadRequestError for "User is already
verified". Import or define these error classes according to the project's
existing error hierarchy to enable proper HTTP status code mapping and avoid
leaking internal stack traces.
| import { sendVerificationEmail } from '../utils/email.utils'; | ||
| import { IUserRepository } from "../../../repository/IUserRepository"; | ||
| import { randomBytes } from "crypto"; | ||
| // import { sendVerificationEmail } from "../utils/email.utils"; // Function not found, commented out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Missing email utility function.
The email verification functionality has been disabled due to a missing sendVerificationEmail function. Ensure this critical functionality is restored after the modular migration is complete.
🏁 Script executed:
#!/bin/bash
# Search for email utility functions in the codebase
echo "Searching for email-related utilities:"
rg -i "sendVerificationEmail|email.*util" --type ts
echo -e "\nSearching for other email sending functionality:"
rg -i "email|smtp|nodemailer|sendgrid" --type ts | head -20Length of output: 8096
🏁 Script executed:
#!/bin/bash
# List all email.utils.ts files in the src directory
echo "Finding email.utils.ts files:"
find src -type f -name "email.utils.ts"
# Display content of the global utils/email.utils.ts
echo -e "\n----- src/utils/email.utils.ts -----"
sed -n '1,200p' src/utils/email.utils.ts
# Display content of the use-case under review
echo -e "\n----- src/modules/auth/use-cases/resend-email-verification.usecase.ts -----"
sed -n '1,200p' src/modules/auth/use-cases/resend-email-verification.usecase.tsLength of output: 2313
🏁 Script executed:
#!/bin/bash
# Display content of the auth-specific email utility
echo "----- src/modules/auth/utils/email.utils.ts -----"
sed -n '1,200p' src/modules/auth/utils/email.utils.ts
# List all 'resend' use-case files in auth module
echo -e "\nListing resend-related use-case files:"
find src/modules/auth/use-cases -maxdepth 1 -type f -name "*resend*.ts"
# Show the original resend-verification-email use-case
echo -e "\n----- src/modules/auth/use-cases/resend-verification-email.usecase.ts -----"
sed -n '1,200p' src/modules/auth/use-cases/resend-verification-email.usecase.tsLength of output: 3502
🏁 Script executed:
#!/bin/bash
# Inspect the stub controller to see which use-case it references
echo "----- src/modules/auth/presentation/controllers/Auth.controller.stub.ts -----"
sed -n '1,200p' src/modules/auth/presentation/controllers/Auth.controller.stub.ts
# Search for any imports of the stub use-case in controllers
echo -e "\nSearching for stub use-case references in controllers:"
rg -n "resend-email-verification.usecase" -A2 -B2 src/modules/auth/presentation/controllersLength of output: 2010
Resolve duplicate stub and restore email sending functionality
The file src/modules/auth/use-cases/resend-email-verification.usecase.ts appears to be a temporary stub that duplicates the existing ResendVerificationEmailUseCase in resend-verification-email.usecase.ts:
- It comments out a non‐existent
sendVerificationEmailimport instead of using the auth‐specificsendEmailutil. - It only logs the verification link rather than actually sending an email.
- Its name (
resend-email-verification.usecase.ts) is swapped vs. the working file (resend-verification-email.usecase.ts), causing confusion.
To fix:
- Remove or rename this stub file (to avoid two “resend” use‐cases).
- If this is the intended implementation, update it to mirror the real use‐case:
- Import the correct function:
import { sendEmail } from "../utils/email.utils";
- Replace the
console.logwith:await sendEmail({ to: user.email, subject: "Email Verification", html: ` <h1>Email Verification</h1> <p>Please verify by clicking:</p> <a href="${process.env.BASE_URL}/api/auth/verify-email?token=${token}"> Verify Email </a> <p>This link expires in 1 hour.</p> `, });
- Use
process.env.BASE_URL(not hardcoded localhost) for the verification link.
- Import the correct function:
- Ensure method signature and DTO usage align with the other use‐case (
execute(dto)).
These changes will remove duplication and re-enable the critical email‐verification flow.
🤖 Prompt for AI Agents
In src/modules/auth/use-cases/resend-email-verification.usecase.ts at line 3,
the file is a duplicate stub with a commented-out non-existent import and only
logs the verification link instead of sending an email. To fix, either remove or
rename this stub to avoid duplication, or update it to match the real use-case
by importing the correct sendEmail function from "../utils/email.utils",
replacing the console.log with an await sendEmail call that sends the
verification email using process.env.BASE_URL for the link, and ensure the
method signature and DTO usage align with the existing
resend-verification-email.usecase.ts implementation.
| import AuthService from "../../../services/AuthService"; | ||
| import { WalletService } from "../services/WalletService"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broken import after shared-folder purge
AuthService is still imported from src/services/AuthService, but the src/services folder was deleted in this PR.
Verify the new location (very likely src/modules/auth/services/AuthService) and update the path, otherwise all wallet tests will fail at runtime.
-import AuthService from "../../../services/AuthService";
+import AuthService from "../../../modules/auth/services/AuthService"; // adjust to the real path📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import AuthService from "../../../services/AuthService"; | |
| import { WalletService } from "../services/WalletService"; | |
| import AuthService from "../../../modules/auth/services/AuthService"; // adjust to the real path | |
| import { WalletService } from "../services/WalletService"; |
🤖 Prompt for AI Agents
In src/modules/wallet/__tests__/WalletAuthIntegration.test.ts at lines 1 to 2,
the import path for AuthService is broken because the src/services folder was
deleted. Update the import path for AuthService to the new location, likely
src/modules/auth/services/AuthService, to ensure the wallet tests run correctly
without runtime errors.
| mockWalletService = new WalletService() as jest.Mocked<WalletService>; | ||
| authService = new AuthService(); | ||
|
|
||
| // Replace the wallet service instance | ||
| (authService as any).walletService = mockWalletService; | ||
|
|
||
| jest.clearAllMocks(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
jest.clearAllMocks() order
jest.clearAllMocks() is executed after you create mockWalletService and re-wire authService.
That immediately wipes the constructor/method spies you are about to configure inside each test.
Call clearAllMocks first to avoid subtle “mock was not called” assertion flakes.
- beforeEach(() => {
- mockWalletService = new WalletService() as jest.Mocked<WalletService>;
- authService = new AuthService();
-
- // Replace the wallet service instance
- (authService as any).walletService = mockWalletService;
-
- jest.clearAllMocks();
- });
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ mockWalletService = new WalletService() as jest.Mocked<WalletService>;
+ authService = new AuthService();
+ (authService as any).walletService = mockWalletService;
+ });🤖 Prompt for AI Agents
In src/modules/wallet/__tests__/WalletAuthIntegration.test.ts around lines 29 to
37, the call to jest.clearAllMocks() is placed after creating mockWalletService
and re-wiring authService, which clears the spies you need for your tests. Move
jest.clearAllMocks() to the very beginning of the beforeEach block to ensure all
mocks are cleared before setting up new instances and spies, preventing flaky
test assertions.
| } catch (error: any) { | ||
| return WalletVerificationResponseDto.createError( | ||
| dto.walletAddress, | ||
| error.message || 'Invalid wallet address format' | ||
| error.message || "Invalid wallet address format" | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Prefer unknown in catch and guard the error type
Using any defeats TypeScript’s type-safety and may hide real issues.
Guard the caught value first, then derive the message.
- } catch (error: any) {
- return WalletVerificationResponseDto.createError(
- dto.walletAddress,
- error.message || "Invalid wallet address format"
- );
+ } catch (error: unknown) {
+ const message =
+ error instanceof Error ? error.message : "Invalid wallet address format";
+ return WalletVerificationResponseDto.createError(dto.walletAddress, message);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (error: any) { | |
| return WalletVerificationResponseDto.createError( | |
| dto.walletAddress, | |
| error.message || 'Invalid wallet address format' | |
| error.message || "Invalid wallet address format" | |
| ); | |
| } catch (error: unknown) { | |
| const message = | |
| error instanceof Error ? error.message : "Invalid wallet address format"; | |
| return WalletVerificationResponseDto.createError(dto.walletAddress, message); | |
| } |
🤖 Prompt for AI Agents
In src/modules/wallet/use-cases/ValidateWalletFormatUseCase.ts around lines 21
to 25, change the catch clause to catch the error as unknown instead of any.
Then add a type guard to check if the caught error is an instance of Error
before accessing its message property. Use a fallback message if the error is
not an Error instance. This preserves type safety and prevents runtime issues.
| async create(data: Partial<Photo>): Promise<Photo> { | ||
| const photo = new Photo(data); | ||
| photo.validate(); | ||
| const created = await prisma.photo.create({ | ||
| const photo = Photo.create({ | ||
| url: data.url!, | ||
| userId: data.userId!, | ||
| uploadedAt: new Date(), | ||
| metadata: data.metadata || {}, | ||
| }); | ||
| const created = (await prisma.photo.create({ | ||
| data: { | ||
| url: data.url!, | ||
| userId: data.userId!, | ||
| uploadedAt: data.uploadedAt || new Date(), | ||
| metadata: data.metadata || {} | ||
| } | ||
| }) as unknown as PrismaPhoto; | ||
| return new Photo(created); | ||
| url: photo.url, | ||
| userId: photo.userId, | ||
| metadata: photo.metadata || {}, | ||
| }, | ||
| })) as unknown as PrismaPhoto; | ||
| return Photo.create({ | ||
| id: created.id, | ||
| url: created.url, | ||
| userId: created.userId, | ||
| uploadedAt: created.uploadedAt, | ||
| metadata: created.metadata | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential issue with non-null assertion operators.
The create method uses non-null assertion operators (!) for required fields without proper validation. This could lead to runtime errors if the data is missing.
Consider adding validation before using non-null assertions:
async create(data: Partial<Photo>): Promise<Photo> {
+ if (!data.url || !data.userId) {
+ throw new Error('Required fields url and userId must be provided');
+ }
+
const photo = Photo.create({
- url: data.url!,
- userId: data.userId!,
+ url: data.url,
+ userId: data.userId,
uploadedAt: new Date(),
metadata: data.metadata || {},
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async create(data: Partial<Photo>): Promise<Photo> { | |
| const photo = new Photo(data); | |
| photo.validate(); | |
| const created = await prisma.photo.create({ | |
| const photo = Photo.create({ | |
| url: data.url!, | |
| userId: data.userId!, | |
| uploadedAt: new Date(), | |
| metadata: data.metadata || {}, | |
| }); | |
| const created = (await prisma.photo.create({ | |
| data: { | |
| url: data.url!, | |
| userId: data.userId!, | |
| uploadedAt: data.uploadedAt || new Date(), | |
| metadata: data.metadata || {} | |
| } | |
| }) as unknown as PrismaPhoto; | |
| return new Photo(created); | |
| url: photo.url, | |
| userId: photo.userId, | |
| metadata: photo.metadata || {}, | |
| }, | |
| })) as unknown as PrismaPhoto; | |
| return Photo.create({ | |
| id: created.id, | |
| url: created.url, | |
| userId: created.userId, | |
| uploadedAt: created.uploadedAt, | |
| metadata: created.metadata | |
| }); | |
| } | |
| async create(data: Partial<Photo>): Promise<Photo> { | |
| if (!data.url || !data.userId) { | |
| throw new Error('Required fields url and userId must be provided'); | |
| } | |
| const photo = Photo.create({ | |
| url: data.url, | |
| userId: data.userId, | |
| uploadedAt: new Date(), | |
| metadata: data.metadata || {}, | |
| }); | |
| const created = (await prisma.photo.create({ | |
| data: { | |
| url: photo.url, | |
| userId: photo.userId, | |
| metadata: photo.metadata || {}, | |
| }, | |
| })) as unknown as PrismaPhoto; | |
| return Photo.create({ | |
| id: created.id, | |
| url: created.url, | |
| userId: created.userId, | |
| uploadedAt: created.uploadedAt, | |
| metadata: created.metadata | |
| }); | |
| } |
🤖 Prompt for AI Agents
In src/repository/PhotoRepository.ts between lines 42 and 63, the create method
uses non-null assertion operators on data.url and data.userId without validating
their presence, which risks runtime errors. Add explicit validation checks to
ensure data.url and data.userId are defined before using them, and throw a clear
error or handle the case appropriately if they are missing, instead of relying
on non-null assertions.
| async createUser( | ||
| name: string, | ||
| email: string, | ||
| password: string, | ||
| wallet: string | ||
| ): Promise<User> { | ||
| const user = this.create({ name, email, password, wallet }); | ||
| return await this.save(user); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plain-text password persisted
createUser writes the raw password field directly to the database.
Store a salted+hashed value instead to prevent credential disclosure if the DB is compromised.
-const user = this.create({ name, email, password, wallet });
+const hashedPassword = await bcrypt.hash(password, 12);
+const user = this.create({ name, email, password: hashedPassword, wallet });(remember to inject bcrypt and adjust imports).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async createUser( | |
| name: string, | |
| email: string, | |
| password: string, | |
| wallet: string | |
| ): Promise<User> { | |
| const user = this.create({ name, email, password, wallet }); | |
| return await this.save(user); | |
| } | |
| async createUser( | |
| name: string, | |
| email: string, | |
| password: string, | |
| wallet: string | |
| ): Promise<User> { | |
| const hashedPassword = await bcrypt.hash(password, 12); | |
| const user = this.create({ name, email, password: hashedPassword, wallet }); | |
| return await this.save(user); | |
| } |
🤖 Prompt for AI Agents
In src/repository/user.repository.ts around lines 13 to 21, the createUser
method currently saves the raw password directly to the database, which is
insecure. To fix this, import bcrypt and use it to generate a salted hash of the
password before creating the user entity. Replace the plain password with the
hashed password in the create call, ensuring only the hashed password is stored.
Villarley
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
🚀 Volunchain Pull Request
Mark with an
xall the checkboxes that apply (like[x])📌 Type of Change
📝 Changes description
src/controllerssrc/servicessrc/entitiessrc/errorssrc/dtossrc/useCase⏰ Time spent breakdown
⏳ Total: ~3h 30min
🌌 Comments
Thank you for contributing to Volunchain, we are glad that you have chosen us as your project of choice and we hope that you continue to contribute to this great project, so that together we can make our mark at the top!
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests
Chores