Skip to content

Conversation

@yamcodes
Copy link
Contributor

@yamcodes yamcodes commented Jun 8, 2025

Description

  • Refactor Comments into our Layered architecture by creating dedicated mappers, dto, interface, and controller just like article
  • separate mappers into atomic files

PR Checklist

  • Read the Developer's Guide in CONTRIBUTING.md
  • Use a concise title to represent the changes introduced in this PR
  • Provide a detailed description of the changes introduced in this PR, and, if necessary, some screenshots
  • Reference an issue or discussion where the feature or changes have been previously discussed
  • Add a failing test that passes with the changes introduced in this PR, or explain why it's not feasible
  • Add documentation for the feature or changes introduced in this PR to the docs; you can run them with bun docs

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated comments API with endpoints to create, retrieve, and delete comments on articles.
    • Added structured response formats for single and multiple comments.
  • Refactor

    • Separated comment-related routes from the articles API to a standalone comments controller.
    • Improved data mapping for articles and comments using dedicated mapper functions and centralized exports.
  • Bug Fixes

    • Corrected import paths for comments schema to ensure consistency.
  • Chores

    • Enhanced type safety and maintainability with new and updated interfaces for comments.
    • Updated documentation and response schemas for improved API clarity.

yamcodes added 30 commits April 17, 2025 19:09
…ethods

- Updated article response DTO to encapsulate article details within an 'article' object.
- Refactored articles service methods to improve type handling and ensure consistent article data mapping.
- Removed unused query parameters in article fetching logic for cleaner service calls.
- Enhanced error handling in article creation and update methods to ensure articles are found post-operation.
- Cleaned up comments and organized imports for better code readability.
- Introduced a new mapping function `toFeedResponse` for transforming article data into the feed response format.
- Updated the articles controller to utilize `toFeedResponse` for article data mapping.
- Modified DTO exports to include `article-feed-response.dto` and reorganized existing exports for clarity.
- Changed the author type in the article feed interface to `ProfileFeed` for better alignment with the new response structure.
…handling

- Replaced `articlesPlugin` with `articlesController` in the app module for improved structure.
- Updated article schema imports across various files to maintain consistency.
- Refactored `CommentsRepository` to use a new `CreateCommentDto` type for better clarity and type safety.
- Cleaned up unused imports and comments for enhanced code readability.
- Modified summary descriptions in the articles controller for clarity, changing 'Article Feed' to 'Feed Articles', 'Add Comment to Article' to 'Add Comments to an Article', and 'Get Comments from Article' to 'Get Comments from an Article'.
- Updated the tags plugin summary from 'List Tags' to 'Get Tags' for consistency.
- Adjusted user plugin summaries, changing 'Register' to 'Registeration', 'Login' to 'Authentication', and 'Current User' to 'Get Current User' for improved clarity.
- Moved the article creation endpoint to a new position within the articles controller for improved readability and structure.
- Ensured the endpoint retains its functionality, including user authentication and response formatting.
- Updated the endpoint's summary details to maintain consistency with other routes.
- Replaced `ListArticlesQueryDto` with `ArticleFeedQueryDto` in the articles controller to enhance query handling for the article feed.
- Added a detailed description for the feed articles endpoint, specifying additional query parameters.
- Removed the now obsolete `article-feed-response.dto.ts` file to streamline the DTO structure.
- Updated DTO exports in the index file to reflect the changes.
- Added a detailed description to the 'List Articles' endpoint, outlining the default behavior and available query parameters for filtering results.
- Clarified that authentication is optional and specified the ordering of returned articles.
yamcodes added 5 commits June 8, 2025 16:41
…entation

- Added commentsController to the app module for managing comments functionality.
- Updated commentsController to include detailed descriptions for API endpoints, clarifying authentication requirements for adding, retrieving, and deleting comments.
- Updated CommentsRepository and CommentsService to use NewCommentRow interface instead of deprecated CommentToCreate type.
- Introduced a new mapper function, toNewCommentRow, to streamline the transformation of comment data.
- Enhanced the interfaces index to export the new comment row interface for better organization.
- Removed the comments.mapper file and consolidated mapping functions into a new index file for better organization.
- Updated commentsController to utilize the new toCommentsResponse function for improved response handling.
- Adjusted imports in comments.service.ts to reflect the new structure, enhancing maintainability.
- Streamlined the import statements in articles.controller.ts and articles.service.ts to utilize a centralized mappers index file, enhancing code organization and maintainability.
- Introduced a new toDomain mapper function to streamline the transformation of comment data in CommentsService.
- Updated the comments.service.ts to utilize the new toDomain function for improved code clarity and maintainability.
- Adjusted the mappers index file to include the new toDomain export, ensuring better organization of mapping functions.
@yamcodes yamcodes requested a review from aruaycodes June 8, 2025 12:08
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 8, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This change refactors the comments feature by extracting all comment-related logic, routes, services, and mappers from the articles module into a dedicated comments module and controller. The articles controller and module no longer handle comments. New DTOs, mappers, and interfaces for comments are introduced and restructured.

Changes

Files/Groups Change Summary
src/app.module.ts Added commentsController import and integrated it into the API route group.
src/articles/articles.controller.ts, src/articles/articles.module.ts Removed all comment-related routes, imports, and service instantiation from articles module.
src/articles/articles.schema.ts, src/database.providers.ts Fixed import paths for comments schema.
src/articles/articles.service.ts Consolidated article mapper imports to use new index file.
src/articles/mappers/articles.mapper.ts Deleted monolithic article mappers file.
src/articles/mappers/index.ts New index file re-exporting all article mapper modules.
src/articles/mappers/to-*.mapper.ts (6 files) Added modularized article mapper functions for domain, response, feed, and creation mapping.
src/comments/comments.controller.ts Added new comments controller with grouped routes for comment CRUD operations.
src/comments/comments.module.ts Added comments module setup with service instantiation and app state.
src/comments/comments.repository.ts Updated schema import path and switched to using NewCommentRow type for creation.
src/comments/comments.schema.ts Added explicit ORM relations for comments to articles and users.
src/comments/comments.service.ts Refactored to use new comment mappers for data transformation.
src/comments/dto/comment-author.dto.ts, src/comments/schema/comment-relations.schema.ts, src/comments/schema/index.ts Deleted redundant DTO and schema relation/index files.
src/comments/dto/comment-response.dto.ts Inlined author property schema instead of importing CommentAuthorDto.
src/comments/dto/comments-response.dto.ts Added CommentsResponseDto for returning arrays of comments.
src/comments/dto/index.ts Updated DTO barrel file exports.
src/comments/interfaces/comment-row.interface.ts, src/comments/interfaces/new-comment-row.interface.ts Added interfaces for comment row and new comment row structures.
src/comments/interfaces/index.ts Updated to re-export new comment interfaces.
src/comments/mappers/index.ts New index file re-exporting all comment mapper modules.
src/comments/mappers/to-comment-response.mapper.ts, src/comments/mappers/to-comments-response.mapper.ts, src/comments/mappers/to-domain.mapper.ts, src/comments/mappers/to-new-comment-row.mapper.ts Added modularized comment mappers for domain, response, and creation mapping.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API (commentsController)
    participant AuthService
    participant CommentsService
    participant ProfilesService
    participant Database

    Client->>API (commentsController): POST /articles/:slug/comments (with auth)
    API->>AuthService: Validate user from header
    API->>CommentsService: createComment(slug, comment, userId)
    CommentsService->>Database: Insert new comment row
    CommentsService->>ProfilesService: Get author profile
    CommentsService->>API: Return created comment (mapped)
    API->>Client: Respond with CommentResponseDto

    Client->>API (commentsController): GET /articles/:slug/comments (optional auth)
    API->>CommentsService: getComments(slug, [userId])
    CommentsService->>Database: Query comments for article
    CommentsService->>ProfilesService: Get authors' profiles
    CommentsService->>API: Return comments (mapped)
    API->>Client: Respond with CommentsResponseDto

    Client->>API (commentsController): DELETE /articles/:slug/comments/:id (with auth)
    API->>AuthService: Validate user from header
    API->>CommentsService: deleteComment(slug, commentId, userId)
    CommentsService->>Database: Delete comment if authorized
    API->>Client: Respond with 204 No Content
Loading

Possibly related PRs

  • Implement comments feature for articles #134: This PR originally implemented the comments feature within the articles module, including comments routes, services, repository, and schema definitions. The current PR directly restructures and extracts this functionality into a separate comments module.

Suggested labels

enhancement

Poem

In the warren of code, a rabbit hopped,
Refactoring comments, the old paths dropped.
Now comments live in a home of their own,
With mappers and DTOs neatly sewn.
Modular, clean, and easy to see—
Hooray for code that hops with glee! 🐇✨


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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@yamcodes yamcodes changed the title Layered phase2 comments Layered Phase 2 - Comments Jun 8, 2025
@yamcodes yamcodes added this to the Layered Architecture milestone Jun 8, 2025
@yamcodes yamcodes added the refactor Code changes that do not alter end functionality, or fix a bug. label Jun 8, 2025
@yamcodes yamcodes self-assigned this Jun 8, 2025
@yamcodes yamcodes linked an issue Jun 8, 2025 that may be closed by this pull request
@yamcodes
Copy link
Contributor Author

yamcodes commented Jun 8, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 8, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (2)
src/comments/comments.repository.ts (1)

60-75: 🛠️ Refactor suggestion

Architectural concern: Article query in comments repository.

The findBySlug method queries the articles table, which violates the separation of concerns principle. A comments repository should not be responsible for article-related operations.

Consider one of these approaches:

  1. Move this method to the articles repository where it belongs
  2. Remove it if it's no longer needed after the refactoring
  3. If comments need article data, inject the articles repository as a dependency
-  async findBySlug(slug: string): Promise<ArticleRow | null> {
-    const result = await this.db.query.articles.findFirst({
-      where: eq(articles.slug, slug),
-      with: {
-        author: {
-          with: {
-            followers: true,
-          },
-        },
-        favoritedBy: true,
-        tags: true,
-      },
-    });
-
-    return result ?? null;
-  }
src/comments/comments.schema.ts (1)

9-14: ⚠️ Potential issue

Use integer() instead of serial() for foreign key columns.

Foreign key columns should use integer() rather than serial(). Serial creates auto-incrementing columns, which is inappropriate for foreign keys that should reference existing primary keys.

-  articleId: serial('article_id')
+  articleId: integer('article_id')
     .notNull()
     .references(() => articles.id, { onDelete: 'cascade' }),
-  authorId: serial('author_id')
+  authorId: integer('author_id')
     .notNull()
     .references(() => users.id, { onDelete: 'cascade' }),
🧹 Nitpick comments (8)
src/articles/mappers/to-new-article-row.mapper.ts (1)

1-13: Mapper implementation solid, but cover slug edge cases with tests
The toNewArticleRow function correctly maps CreateArticleInput to NewArticleRow and generates slugs via slugify. Consider adding unit tests for edge cases (e.g., special characters, duplicate titles) to validate slug behavior.

src/comments/interfaces/comment-row.interface.ts (1)

1-8: Ensure CommentRow aligns with persisted record shape
Verify that CommentRow accurately represents the stored comment schema (types and field names). If the comment structure grows, consider extracting shared fields into a base interface to reduce duplication.

src/articles/mappers/to-feed-domain.mapper.ts (1)

3-15: Consider simplifying the mapper implementation.

The current implementation explicitly maps each property, but since ArticleFeedRow and IArticleFeed have identical structures, this could be simplified.

-export function toFeedDomain(article: ArticleFeedRow): IArticleFeed {
-  return {
-    slug: article.slug,
-    title: article.title,
-    description: article.description,
-    tagList: article.tagList,
-    createdAt: article.createdAt,
-    updatedAt: article.updatedAt,
-    favorited: article.favorited,
-    favoritesCount: article.favoritesCount,
-    author: article.author,
-  };
-}
+export function toFeedDomain(article: ArticleFeedRow): IArticleFeed {
+  return { ...article };
+}

This approach is more concise and automatically adapts if properties are added to both types. However, the explicit mapping provides better clarity about the transformation, so both approaches are valid depending on team preferences.

src/comments/mappers/to-comments-response.mapper.ts (1)

4-6: Consider defining a dedicated interface for better type clarity.

The current return type using ReturnType<typeof toCommentResponse>['comment'][] is verbose and reduces readability. Consider defining a dedicated interface for the response.

+import type { CommentsResponseDto } from '../dto/comments-response.dto';
+
-export function toCommentsResponse(comments: IComment[]): {
-  comments: ReturnType<typeof toCommentResponse>['comment'][];
-} {
+export function toCommentsResponse(comments: IComment[]): CommentsResponseDto {
src/comments/mappers/to-new-comment-row.mapper.ts (1)

3-7: Consider simplifying the body parameter structure.

The current parameter body: { body: string } followed by accessing body.body creates unnecessary nesting. If this structure isn't required by the calling context, consider simplifying.

-export function toNewCommentRow(
-  body: { body: string },
-  articleId: number,
-  authorId: number,
-): NewCommentRow {
+export function toNewCommentRow(
+  body: string,
+  articleId: number,
+  authorId: number,
+): NewCommentRow {
   return {
-    body: body.body,
+    body,
     articleId,
     authorId,
   };
 }

However, if the nested structure aligns with your DTO design, the current implementation is correct.

src/comments/comments.module.ts (1)

9-22: Consider adding explicit return type for better type safety.

The setupComments function would benefit from an explicit return type annotation to improve type safety and developer experience.

-export const setupComments = () => {
+export const setupComments = (): Elysia<'', { commentsService: CommentsService; authService: AuthService }> => {
src/comments/mappers/to-domain.mapper.ts (1)

4-8: Consider extracting the author type if used elsewhere.

The ToCommentsDomainAuthor type is well-defined but consider moving it to a shared interfaces file if this pattern is used in other mappers.

src/comments/comments.controller.ts (1)

47-53: Consider simplifying the userId null handling.

The null-to-undefined conversion may be unnecessary depending on how commentsService.getComments handles null values. Consider checking if the service can accept null directly to simplify the code.

-          const userId = await store.authService.getOptionalUserIdFromHeader(
-            request.headers,
-          );
-          const comments = await store.commentsService.getComments(
-            params.slug,
-            userId === null ? undefined : userId,
-          );
+          const userId = await store.authService.getOptionalUserIdFromHeader(
+            request.headers,
+          );
+          const comments = await store.commentsService.getComments(
+            params.slug,
+            userId,
+          );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 239e7c4 and 64ab5be.

📒 Files selected for processing (33)
  • src/app.module.ts (2 hunks)
  • src/articles/articles.controller.ts (1 hunks)
  • src/articles/articles.module.ts (0 hunks)
  • src/articles/articles.schema.ts (1 hunks)
  • src/articles/articles.service.ts (1 hunks)
  • src/articles/mappers/articles.mapper.ts (0 hunks)
  • src/articles/mappers/index.ts (1 hunks)
  • src/articles/mappers/to-create-article-input.mapper.ts (1 hunks)
  • src/articles/mappers/to-domain.mapper.ts (1 hunks)
  • src/articles/mappers/to-feed-domain.mapper.ts (1 hunks)
  • src/articles/mappers/to-feed-response.mapper.ts (1 hunks)
  • src/articles/mappers/to-new-article-row.mapper.ts (1 hunks)
  • src/articles/mappers/to-response.mapper.ts (1 hunks)
  • src/comments/comments.controller.ts (1 hunks)
  • src/comments/comments.module.ts (1 hunks)
  • src/comments/comments.repository.ts (1 hunks)
  • src/comments/comments.schema.ts (2 hunks)
  • src/comments/comments.service.ts (3 hunks)
  • src/comments/dto/comment-author.dto.ts (0 hunks)
  • src/comments/dto/comment-response.dto.ts (1 hunks)
  • src/comments/dto/comments-response.dto.ts (1 hunks)
  • src/comments/dto/index.ts (1 hunks)
  • src/comments/interfaces/comment-row.interface.ts (1 hunks)
  • src/comments/interfaces/index.ts (1 hunks)
  • src/comments/interfaces/new-comment-row.interface.ts (1 hunks)
  • src/comments/mappers/index.ts (1 hunks)
  • src/comments/mappers/to-comment-response.mapper.ts (1 hunks)
  • src/comments/mappers/to-comments-response.mapper.ts (1 hunks)
  • src/comments/mappers/to-domain.mapper.ts (1 hunks)
  • src/comments/mappers/to-new-comment-row.mapper.ts (1 hunks)
  • src/comments/schema/comment-relations.schema.ts (0 hunks)
  • src/comments/schema/index.ts (0 hunks)
  • src/database.providers.ts (1 hunks)
💤 Files with no reviewable changes (5)
  • src/comments/schema/index.ts
  • src/articles/articles.module.ts
  • src/comments/schema/comment-relations.schema.ts
  • src/comments/dto/comment-author.dto.ts
  • src/articles/mappers/articles.mapper.ts
🧰 Additional context used
🧬 Code Graph Analysis (15)
src/app.module.ts (1)
src/comments/comments.controller.ts (1)
  • commentsController (10-90)
src/articles/mappers/to-new-article-row.mapper.ts (3)
src/articles/interfaces/create-article-input.interface.ts (1)
  • CreateArticleInput (1-6)
src/articles/interfaces/new-article-row.interface.ts (1)
  • NewArticleRow (4-4)
src/utils/slugify.ts (1)
  • slugify (26-39)
src/articles/mappers/to-feed-response.mapper.ts (1)
src/articles/interfaces/article-feed.interface.ts (1)
  • IArticleFeed (3-13)
src/articles/mappers/to-feed-domain.mapper.ts (2)
src/articles/interfaces/article-feed-row.interface.ts (1)
  • ArticleFeedRow (3-13)
src/articles/interfaces/article-feed.interface.ts (1)
  • IArticleFeed (3-13)
src/comments/mappers/to-comments-response.mapper.ts (2)
src/comments/interfaces/comment.interface.ts (1)
  • IComment (1-12)
src/comments/mappers/to-comment-response.mapper.ts (1)
  • toCommentResponse (4-17)
src/articles/mappers/to-response.mapper.ts (1)
src/articles/interfaces/article.interface.ts (1)
  • IArticle (3-21)
src/comments/comments.repository.ts (2)
src/database.providers.ts (2)
  • db (13-21)
  • Database (22-22)
src/comments/interfaces/new-comment-row.interface.ts (1)
  • NewCommentRow (1-5)
src/comments/comments.schema.ts (2)
src/articles/articles.schema.ts (1)
  • articles (14-25)
src/users/users.model.ts (1)
  • users (12-23)
src/comments/mappers/to-new-comment-row.mapper.ts (1)
src/comments/interfaces/new-comment-row.interface.ts (1)
  • NewCommentRow (1-5)
src/comments/mappers/to-comment-response.mapper.ts (1)
src/comments/interfaces/comment.interface.ts (1)
  • IComment (1-12)
src/comments/comments.module.ts (6)
src/comments/comments.repository.ts (1)
  • CommentsRepository (8-82)
src/database.providers.ts (1)
  • db (13-21)
src/profiles/profiles.repository.ts (1)
  • ProfilesRepository (5-76)
src/profiles/profiles.service.ts (1)
  • ProfilesService (6-90)
src/comments/comments.service.ts (1)
  • CommentsService (8-110)
src/auth/auth.service.ts (1)
  • AuthService (8-104)
src/articles/mappers/to-create-article-input.mapper.ts (1)
src/articles/interfaces/create-article-input.interface.ts (1)
  • CreateArticleInput (1-6)
src/comments/mappers/to-domain.mapper.ts (2)
src/comments/interfaces/comment-row.interface.ts (1)
  • CommentRow (1-8)
src/comments/interfaces/comment.interface.ts (1)
  • IComment (1-12)
src/articles/mappers/to-domain.mapper.ts (2)
src/articles/interfaces/article-row.interface.ts (1)
  • ArticleRow (8-13)
src/articles/interfaces/article.interface.ts (1)
  • IArticle (3-21)
src/comments/comments.controller.ts (6)
src/comments/comments.module.ts (1)
  • setupComments (9-22)
src/comments/mappers/to-comment-response.mapper.ts (1)
  • toCommentResponse (4-17)
src/comments/dto/comment-response.dto.ts (2)
  • CommentResponseDto (3-16)
  • CommentResponseDto (18-18)
src/comments/comments.schema.ts (1)
  • comments (6-17)
src/comments/mappers/to-comments-response.mapper.ts (1)
  • toCommentsResponse (4-8)
src/comments/dto/comments-response.dto.ts (2)
  • CommentsResponseDto (4-6)
  • CommentsResponseDto (7-7)
🔇 Additional comments (30)
src/articles/articles.schema.ts (1)

2-2: Correct import path for comments schema

This change updates the import to match the new comments module structure and ensures the comments table is referenced correctly in article relations.

src/database.providers.ts (1)

2-2: Align comments schema import in database provider

The import has been updated to reflect the relocated comments schema (@comments/comments.schema), keeping the database schema registration consistent.

src/app.module.ts (2)

14-14: Register comments controller in app module

Adding the commentsController import wires in the new comments routes alongside other feature controllers. Ensure the path and named export match the controller file.


64-64: Mount comments controller in API group

Inserting .use(commentsController) under /api integrates comment endpoints with the existing middleware chain. Ordering with related controllers is consistent.

src/articles/articles.service.ts (1)

13-13: Consolidate mapper imports via index

Switching to the barrel import (./mappers) improves modularity and matches the new file structure. Verify that index.ts in the mappers folder exports all referenced functions.

src/comments/interfaces/index.ts (1)

2-3: Export new comment row interfaces

Re-exporting comment-row.interface and new-comment-row.interface alongside comment.interface centralizes type definitions for the comments module.

src/comments/dto/index.ts (1)

3-3: Expose consolidated CommentsResponseDto in DTO barrel
Adding comments-response.dto aligns with the new response schema consolidation. Ensure that all imports of CommentsResponseDto use this barrel export in controllers and services.

src/comments/interfaces/new-comment-row.interface.ts (1)

1-5: Validate NewCommentRow against database schema
Confirm that NewCommentRow matches the database insert model (e.g., using InferInsertModel<typeof comments>) to avoid mismatches during persistence.

src/comments/dto/comments-response.dto.ts (1)

1-7: CommentsResponseDto schema looks correct
Defining comments: Type.Array(CommentResponseDto.properties.comment) ensures consistency with individual comment DTOs.

src/comments/mappers/to-comment-response.mapper.ts (1)

4-17: Well-structured mapper implementation.

The mapper correctly transforms domain objects to API response format, including proper date serialization to ISO strings. The wrapping of the result in a comment property follows common REST API conventions.

src/comments/comments.repository.ts (2)

5-6: Import and type changes look good.

The migration from absolute to relative imports and the updated type from CreateCommentDto to NewCommentRow aligns well with the refactoring objectives.


11-11: Parameter type update is consistent with refactoring.

The change from CreateCommentDto to NewCommentRow maintains consistency with the new interface structure defined in the comments module.

src/articles/articles.controller.ts (2)

11-11: Clean separation of concerns achieved.

The updated imports reflect the new modular mapper structure and the removal of comment-related functionality. This aligns well with the refactoring objectives to separate article and comment concerns.


13-218: Articles controller now properly focused.

The removal of comment-related routes successfully separates article and comment concerns. The controller now handles only article operations, which improves maintainability and follows single responsibility principle.

src/comments/mappers/to-comments-response.mapper.ts (1)

7-7: LGTM! Clean and efficient implementation.

The mapping logic correctly transforms the array and extracts the nested comment property from each mapped result.

src/comments/comments.schema.ts (1)

19-30: LGTM! Proper relational mappings defined.

The comment relations are correctly defined with appropriate one-to-one relationships to articles and users, including descriptive relation names.

src/articles/mappers/to-create-article-input.mapper.ts (1)

4-13: LGTM! Clean mapper with proper null handling.

The implementation correctly maps the DTO structure to the input interface and provides a sensible default for the optional tagList field.

src/comments/mappers/index.ts (1)

1-4: LGTM! Clean modular architecture.

The index file properly consolidates mapper exports, creating a single entry point for comment mappers. This modular approach aligns well with the layered architecture goals and improves maintainability.

src/articles/mappers/to-response.mapper.ts (1)

4-25: Well-structured mapper function.

The toResponse function correctly transforms the domain model to DTO format. The author profile extraction is clean, and the date-to-ISO string conversion is appropriate for API responses. Good separation of concerns and type safety.

src/articles/mappers/index.ts (1)

1-6: Excellent modularization approach.

The index file creates a clean entry point for all article mappers, replacing the monolithic structure. This approach is consistent with the comments mappers architecture and improves maintainability through better separation of concerns.

src/comments/dto/comment-response.dto.ts (1)

9-14: Good simplification of DTO structure.

The inline author definition eliminates the external CommentAuthorDto dependency while maintaining the same API contract. All necessary fields are properly typed, and this approach simplifies the overall DTO architecture.

src/comments/comments.module.ts (1)

10-17: Well-structured dependency injection setup.

The manual dependency injection pattern is clean and follows good practices. The service instantiation order correctly handles dependencies.

src/comments/mappers/to-domain.mapper.ts (1)

17-34: Excellent mapper implementation with clear documentation.

The function signature is type-safe, the JSDoc is comprehensive, and the mapping logic correctly transforms all required fields from the database row to the domain model.

src/articles/mappers/to-feed-response.mapper.ts (1)

4-23: Clean and well-implemented mapper function.

The function correctly handles date conversion to ISO strings for API responses and properly uses the nullish coalescing operator for the articlesCount fallback. The mapping logic is straightforward and type-safe.

src/comments/comments.service.ts (3)

5-6: Good import organization for the new mappers and interfaces.

The import statements are clean and well-organized, bringing in the necessary types and mapper functions for the refactored service.


25-41: Excellent use of mapper functions in createComment.

The refactoring successfully replaces manual object construction with the toNewCommentRow and toDomain mappers, making the code more maintainable and consistent. The comment about the author always being the current user is helpful context.


64-76: Clean refactoring with toDomain mapper in getComments.

The use of the toDomain mapper in the map operation is well-implemented. The author object construction inline is appropriate here since it's extracting specific fields from the joined comment data.

src/articles/mappers/to-domain.mapper.ts (1)

1-34: LGTM! Well-implemented domain mapper.

The mapper function correctly transforms ArticleRow to IArticle with appropriate handling of optional fields and computed properties. The use of find() for checking relationships and nullish coalescing for tagList demonstrates good defensive programming practices.

src/comments/comments.controller.ts (2)

69-69: Good practice using parseInt with radix.

The explicit radix parameter in Number.parseInt(params.id, 10) is excellent practice for preventing potential issues with number parsing.


30-30: Proper authentication implementation.

The controller correctly applies authentication middleware to routes that modify data (POST/DELETE) while leaving the read-only GET route with optional authentication. This follows REST security best practices.

Also applies to: 74-74

yamcodes added 7 commits June 8, 2025 17:14
- Updated import statements in articles.schema.ts, articles.service.ts, article-row.interface.ts, article.interface.ts, and to-new-article-row.mapper.ts to use absolute paths for better consistency and maintainability.
- Enhanced code organization by ensuring uniformity in import paths throughout the articles module.
…ration

- Integrated ArticlesService and TagsService into CommentsService for improved comment handling related to articles and tags.
- Removed the deprecated findBySlug method from CommentsRepository, streamlining the repository's functionality.
- Updated setupComments function to instantiate and utilize the new services, enhancing modularity and maintainability.
- Modified the deleteComment method to accept the comment ID as a string instead of parsing it to a number, simplifying the parameter handling.
- Updated the parameter validation in commentsController to enforce numeric type for the comment ID, enhancing data integrity and validation consistency.
- Introduced a separate count query to improve performance when filtering articles by tags and favorited status.
- Consolidated filtering conditions for tags and authors into reusable variables, enhancing code readability and maintainability.
- Updated the base query to utilize the new count query for accurate article counts based on applied filters.
- Replaced the use of find with some in the toDomain mapper for articles and profiles, improving performance and readability.
- Updated favorited and following properties to utilize more efficient array methods, enhancing code clarity.
- Changed articleId and authorId fields in comments schema from serial to integer type for improved data integrity and consistency.
- Updated import statements to include the integer type from drizzle-orm/pg-core, enhancing schema definition clarity.
Base automatically changed from layered-phase1-articles to layered June 14, 2025 06:25
Copy link
Collaborator

@aruaycodes aruaycodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly, the code was so well-written, that I should use it as a bible when i do my own project.

@yamcodes yamcodes merged commit b9e6ea7 into layered Jun 20, 2025
1 check passed
@yamcodes yamcodes deleted the layered-phase2-comments branch June 20, 2025 13:18
@yamcodes yamcodes mentioned this pull request Jun 20, 2025
6 tasks
@coderabbitai coderabbitai bot mentioned this pull request Jun 20, 2025
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code changes that do not alter end functionality, or fix a bug.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Layered Phase 2 - comments

3 participants