Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: get active or archived notification by id #398

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

kshitij-k-osmosys
Copy link
Contributor

@kshitij-k-osmosys kshitij-k-osmosys commented Feb 26, 2025

API PR Checklist

Pre-requisites

  • I have gone through the Contributing guidelines for Submitting a Pull Request (PR) and ensured that this is not a duplicate PR.
  • I have performed unit testing for the new feature added or updated to ensure the new features added are working as expected.
  • I have added/updated test cases to the test suite as applicable.
  • I have performed preliminary testing using the test suite to ensure that any existing features are not impacted and any new features are working as expected as a whole.
  • I have added/updated the required api docs as applicable.
  • I have added/updated the .env.example file with the required values as applicable.

PR Details

PR details have been updated as per the given format (see below)

  • PR title adheres to the format specified in guidelines (e.g., feat: add admin login endpoint)
  • Description has been added
  • Related changes have been added (optional)
  • Screenshots have been added (optional)
  • Query request and response examples have been added (as applicable, in case added or updated)
  • Documentation changes have been listed (as applicable)
  • Test suite/unit testing output is added (as applicable)
  • Pending actions have been added (optional)
  • Any other additional notes have been added (optional)

Additional Information

  • Appropriate label(s) have been added (ready for review should be added if the PR is ready to be reviewed)
  • Assignee(s) and reviewer(s) have been added (optional)

Note: Reviewer should ensure that the checklist and description have been populated and followed correctly, and the PR should be merged only after resolving all conversations and verifying that CI checks pass.


Description:

Create GraphQL endpoint to get active or archived notification by notificationId

Related changes:

  • Use existing notification service function to get notification
  • Create new archivedNotification service function to get entry by notificationId
  • Create new resolver
  • Create new response dto for fetching single notification
  • Create constructor in the dto for returning data like notification using Archive and Active notification entity as base

Screenshots:

image

Query request and response:

Request

curl --location 'localhost:3000/graphql' \
--header 'Authorization: Bearer mysecuretoken' \
--header 'Content-Type: application/json' \
--data '{"query":"query {\r\n  notification(\r\n    notificationId: 150\r\n  ) {\r\n      applicationId\r\n      channelType\r\n      createdBy\r\n      createdOn\r\n      data\r\n      deliveryStatus\r\n      id\r\n      providerId\r\n      result\r\n      status\r\n      updatedBy\r\n      updatedOn\r\n    }\r\n}","variables":{}}'

Documentation changes:

  • Add postman API
  • Update API docs
  • Add testcases for new API

Summary by CodeRabbit

  • New Features

    • Introduced a new API endpoint that lets users retrieve a single notification—whether active or archived—using its unique identifier.
    • Added a GraphQL query to fetch comprehensive notification details, ensuring consistency in response structure.
    • Enhanced the service to manage archived notifications more effectively.
    • Updated API documentation to include instructions for the new notification retrieval functionality.
    • Added new tests to validate the response structure for the notification retrieval requests.
  • Refactor

    • Streamlined internal integrations to support seamless retrieval from both active and archived notification records.

Copy link

coderabbitai bot commented Feb 26, 2025

Walkthrough

This pull request expands the notification functionality by adding a new API call to fetch a notification based on its ID using GraphQL. It updates the archived notifications module to export additional components, introduces a new service method for retrieving archived notifications, and implements a GraphQL query in the notifications resolver. A new DTO is added to standardize the response, and updates in the notifications module include new imports and comments to guide future entity modifications.

Changes

File(s) Change Summary
apps/api/OsmoX-API.postman_collection.json Added the "Fetch Active or Archived Notification by Id" API call using a POST method and GraphQL query to retrieve notification details.
apps/api/src/modules/archived-notifications/archived-notifications.module.ts
apps/api/src/modules/archived-notifications/archived-notifications.service.ts
Updated module exports to include TypeOrmModule and added a new method getArchivedNotificationFromNotificationId to retrieve archived notifications based on notification ID.
apps/api/src/modules/notifications/{dtos/single-notification.response.dto.ts,<br>entities/notification.entity.ts,notifications.module.ts,notifications.resolver.ts,notifications.service.ts} Introduced the SingleNotificationResponse DTO, added a new GraphQL query find in the resolver, implemented findActiveOrArchivedNotificationById in the service, updated module imports/providers, and included comments for future entity updates.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant R as NotificationsResolver
    participant NS as NotificationsService
    participant AS as ArchivedNotificationsService

    C->>R: Query notification(notificationId)
    R->>NS: findActiveOrArchivedNotificationById(notificationId)
    NS->>NS: getNotificationById(notificationId)
    alt Active notification found
        NS-->>R: Return SingleNotificationResponse (active)
    else No active notification
        NS->>AS: getArchivedNotificationFromNotificationId(notificationId)
        alt Archived notification found
            AS-->>NS: Return archived notification
            NS-->>R: Return SingleNotificationResponse (archived)
        else Notification not found
            NS-->>R: Throw NotFoundException
        end
    end
    R-->>C: Return notification response
Loading

Suggested reviewers

  • xixas

Poem

Hop, hop, through the code I bound,
With changes sprouting all around,
I nip at bugs with swift delight,
Fetching IDs by day and night.
In archived fields and active streams,
My code garden sparkles like moonbeams!
— A joyful rabbit from CodeRabbit Inc.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

Copy link

@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: 1

🧹 Nitpick comments (4)
apps/api/src/modules/notifications/notifications.module.ts (1)

105-105: Consider adding the service to exports array if needed elsewhere

If other modules need to use ArchivedNotificationsService through the NotificationsModule, consider adding it to the exports array as well.

apps/api/src/modules/notifications/dtos/single-notification.response.dto.ts (2)

79-96: Constructor logic could be more robust with type guards.

The current implementation relies on type casting and optional chaining for handling different entity types. Consider using type guards for more explicit type checking.

 constructor(notificationEntry: Notification | ArchivedNotification) {
-  this.id =
-    (notificationEntry as Notification).id ||
-    (notificationEntry as ArchivedNotification).notificationId;
+  // Using type guard for more robust type checking
+  this.id = 'id' in notificationEntry 
+    ? notificationEntry.id 
+    : notificationEntry.notificationId;
   this.providerId = notificationEntry.providerId;
   this.channelType = notificationEntry.channelType;
   this.data = notificationEntry.data;
   this.deliveryStatus = notificationEntry.deliveryStatus;
   this.result = notificationEntry.result;
   this.createdOn = notificationEntry.createdOn;
   this.updatedOn = notificationEntry.updatedOn;
   this.createdBy = notificationEntry.createdBy;
   this.updatedBy = notificationEntry.updatedBy;
   this.status = notificationEntry.status;
   this.applicationId = notificationEntry.applicationId;
   this.retryCount = notificationEntry.retryCount;
 }

1-97: Consider adding JSDoc comments for better documentation.

Adding JSDoc comments to the class and constructor would improve code documentation, making it easier for other developers to understand the purpose and usage of this DTO.

+/**
+ * Response DTO for returning notification data from either active or archived notifications.
+ * This class standardizes the response format for notification queries.
+ */
@ObjectType()
export class SingleNotificationResponse {
  // ... existing properties ...

+  /**
+   * Initializes a SingleNotificationResponse instance from either a Notification or ArchivedNotification entity.
+   * @param notificationEntry - The notification entity (active or archived)
+   */
  constructor(notificationEntry: Notification | ArchivedNotification) {
    // ... existing implementation ...
  }
}
apps/api/src/modules/notifications/notifications.service.ts (1)

260-262: Add a ticket reference to the TODO comment.

This TODO comment suggests updating the getNotificationById function but doesn't provide a timeline or ticket reference, which could lead to it being forgotten.

- // TODO: Update function to return single notification instead of array and make it asynchronous
- // It is possible this was done so that we do not get null value as response so need to check first
+ // TODO: [TICKET-XXX] Update function to return single notification instead of array and make it asynchronous
+ // It is possible this was done so that we do not get null value as response so need to check first
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 011bd2d and c8faf7b.

📒 Files selected for processing (8)
  • apps/api/OsmoX-API.postman_collection.json (1 hunks)
  • apps/api/src/modules/archived-notifications/archived-notifications.module.ts (1 hunks)
  • apps/api/src/modules/archived-notifications/archived-notifications.service.ts (1 hunks)
  • apps/api/src/modules/notifications/dtos/single-notification.response.dto.ts (1 hunks)
  • apps/api/src/modules/notifications/entities/notification.entity.ts (1 hunks)
  • apps/api/src/modules/notifications/notifications.module.ts (3 hunks)
  • apps/api/src/modules/notifications/notifications.resolver.ts (2 hunks)
  • apps/api/src/modules/notifications/notifications.service.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
apps/api/src/modules/notifications/notifications.service.ts (1)
Learnt from: kshitij-k-osmosys
PR: OsmosysSoftware/osmo-x#360
File: apps/api/src/modules/notifications/notifications.service.ts:0-0
Timestamp: 2024-11-20T06:08:32.855Z
Learning: The `findNotificationsToArchive` function has been removed from `notifications.service.ts`, and archiving tasks now use `QueryRunner` directly in `archived-notifications.service.ts`.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build
🔇 Additional comments (9)
apps/api/src/modules/notifications/entities/notification.entity.ts (1)

100-101: Good documentation of planned technical debt

The TODO comment clearly documents the planned modifications for the relations between entities, which will help future developers understand the technical debt and necessary changes.

apps/api/src/modules/notifications/notifications.resolver.ts (2)

8-8: LGTM: Appropriate import for the new functionality

The import for SingleNotificationResponse is correctly added to support the new notification query.


24-27: Well-implemented query method to fetch notifications by ID

The new GraphQL query method follows NestJS best practices:

  • Properly decorated with @query
  • Accepts a notificationId parameter
  • Returns the appropriate response type
  • Delegates to the service layer for implementation

This implementation fulfills the PR objective of creating a GraphQL endpoint for retrieving notifications by ID.

apps/api/OsmoX-API.postman_collection.json (1)

699-744: Good API test case for the new endpoint

The Postman collection entry is well-structured with:

  • Clear naming and description
  • Proper authorization headers
  • A sample GraphQL query with all necessary fields
  • Example notification ID for testing

This will help with testing and serve as documentation for API consumers.

apps/api/src/modules/notifications/notifications.module.ts (3)

47-48: LGTM: Required imports for archived notifications functionality

The imports for ArchivedNotificationsModule and ArchivedNotificationsService are correctly added to support the new feature.


89-89: Proper module integration

ArchivedNotificationsModule is correctly included in the imports array, following NestJS module patterns.


105-105: Proper service registration

ArchivedNotificationsService is correctly added to the providers array, making it available for dependency injection in the notifications module.

apps/api/src/modules/archived-notifications/archived-notifications.service.ts (1)

137-148: Method implementation looks good.

The new getArchivedNotificationFromNotificationId method is well-implemented, following the service's existing patterns for repository queries and logging.

apps/api/src/modules/archived-notifications/archived-notifications.module.ts (1)

16-16: Good addition to module exports.

Exporting the TypeOrmModule alongside the service is beneficial as it allows other modules to access repository functionality related to ArchivedNotification entities.

Comment on lines 272 to 295
async findActiveOrArchivedNotificationById(
notificatonId: number,
): Promise<SingleNotificationResponse> {
try {
const activeEntry = (await this.getNotificationById(notificatonId))[0];

if (activeEntry) {
return new SingleNotificationResponse(activeEntry);
}

const archivedEntry =
await this.archivedNotificationsService.getArchivedNotificationFromNotificationId(
notificatonId,
);

if (archivedEntry) {
return new SingleNotificationResponse(archivedEntry);
}

throw new NotFoundException(`Notification with ID ${notificatonId} not found in any table`);
} catch (error) {
return error;
}
}
Copy link

@coderabbitai coderabbitai bot Feb 26, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo and improve error handling in the new method.

The method has a typo in the parameter name (notificatonId missing an 'i') and the error handling returns the error object instead of throwing it properly.

 async findActiveOrArchivedNotificationById(
-  notificatonId: number,
+  notificationId: number,
 ): Promise<SingleNotificationResponse> {
   try {
-    const activeEntry = (await this.getNotificationById(notificatonId))[0];
+    const activeEntry = (await this.getNotificationById(notificationId))[0];

     if (activeEntry) {
       return new SingleNotificationResponse(activeEntry);
     }

     const archivedEntry =
       await this.archivedNotificationsService.getArchivedNotificationFromNotificationId(
-        notificatonId,
+        notificationId,
       );

     if (archivedEntry) {
       return new SingleNotificationResponse(archivedEntry);
     }

-    throw new NotFoundException(`Notification with ID ${notificatonId} not found in any table`);
+    throw new NotFoundException(`Notification with ID ${notificationId} not found in any table`);
   } catch (error) {
-    return error;
+    // Log the error for debugging purposes
+    this.logger.error(`Error finding notification: ${error.message}`, error.stack);
+    // Re-throw the error to be handled by the calling method
+    throw error;
   }
 }
📝 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.

Suggested change
async findActiveOrArchivedNotificationById(
notificatonId: number,
): Promise<SingleNotificationResponse> {
try {
const activeEntry = (await this.getNotificationById(notificatonId))[0];
if (activeEntry) {
return new SingleNotificationResponse(activeEntry);
}
const archivedEntry =
await this.archivedNotificationsService.getArchivedNotificationFromNotificationId(
notificatonId,
);
if (archivedEntry) {
return new SingleNotificationResponse(archivedEntry);
}
throw new NotFoundException(`Notification with ID ${notificatonId} not found in any table`);
} catch (error) {
return error;
}
}
async findActiveOrArchivedNotificationById(
notificationId: number,
): Promise<SingleNotificationResponse> {
try {
const activeEntry = (await this.getNotificationById(notificationId))[0];
if (activeEntry) {
return new SingleNotificationResponse(activeEntry);
}
const archivedEntry =
await this.archivedNotificationsService.getArchivedNotificationFromNotificationId(
notificationId,
);
if (archivedEntry) {
return new SingleNotificationResponse(archivedEntry);
}
throw new NotFoundException(`Notification with ID ${notificationId} not found in any table`);
} catch (error) {
// Log the error for debugging purposes
this.logger.error(`Error finding notification: ${error.message}`, error.stack);
// Re-throw the error to be handled by the calling method
throw error;
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed ee2a2cd

Copy link

Choose a reason for hiding this comment

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

@kshitij-k-osmosys Thank you for fixing the typo and improving the error handling in the method! This will make the code more maintainable and help with debugging future issues.

(\ /)
(•ᴗ•)
/ >🎉


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Copy link

@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

🧹 Nitpick comments (1)
apps/api/docs/api-documentation.md (1)

333-407: New Section for "Fetch active or archived Notification by Id"

The new section is well-structured and clearly documents the GraphQL endpoint for fetching a single notification by ID. It includes all the necessary details such as the required parameter (notificationId), endpoint URL, HTTP method, GraphQL query, a sample cURL command, and a complete JSON sample response. This mirrors the style of the other documented endpoints and should help consumers understand how to use this feature.

Suggestions:

  • Markdown Headings Consistency: The sample response header is currently styled using emphasis (e.g., **Sample response** at line 377). To adhere to markdown linting standards and maintain consistency, consider using a proper heading (e.g., #### Sample response). Here's a suggested diff:

    -**Sample response**
    +#### Sample response
  • Parameter Clarity: The documentation lists notificationId as the required parameter. Ensure that any additional details regarding its format (e.g., whether it should be numeric or a UUID) are captured elsewhere in your API docs if applicable.

Overall, this documentation addition is clear and aligns well with the existing API documentation.

🧰 Tools
🪛 Gitleaks (8.21.2)

371-372:

(curl-auth-header)

🪛 markdownlint-cli2 (0.17.2)

368-368: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)


377-377: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ee2a2cd and cce1264.

📒 Files selected for processing (2)
  • apps/api/docs/api-documentation.md (1 hunks)
  • apps/api/src/modules/notifications/notifications.service.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/modules/notifications/notifications.service.ts
🧰 Additional context used
🪛 Gitleaks (8.21.2)
apps/api/docs/api-documentation.md

371-372:

(curl-auth-header)

🪛 markdownlint-cli2 (0.17.2)
apps/api/docs/api-documentation.md

368-368: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)


377-377: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

Copy link

@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

🧹 Nitpick comments (2)
apps/api/OsmoX.postman_collection.json (2)

3195-3256: New Endpoint – Fetch Active or Archived Notification by Id (Success Case)

This new section introduces a GraphQL query for retrieving a notification by its ID. The success request is well structured:

  • The query requests key fields (such as applicationId, channelType, createdOn, and others) from the notification object.
  • The accompanying test scripts validate that the response is in valid JSON format, that it contains a top-level data property, and that a notification object exists under data.

This implementation aligns with the PR objectives and clearly documents the success scenario.

Suggestion: Consider adding an assertion for the actual content (or at least a few critical fields) of the notification object to ensure that the API returns the expected values.


3257-3316: New Endpoint – Fetch Active or Archived Notification by Id (Not Found Exception)

This item handles the error scenario when an invalid or non-existent notification ID is requested. The test scripts:

  • Verify that the response is valid JSON.
  • Check for the presence of both a data property and an errors array.
  • Assert that the error message is of string type (ensuring that an error is indeed provided).

This properly covers the “not found” case and helps ensure robust error handling for the new endpoint.

Suggestion: It might be beneficial to assert a specific error message (or pattern) so that the test not only confirms an error exists but also that it is descriptive enough (for example, “Notification not found” or similar) to help with debugging.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between cce1264 and 56cf750.

📒 Files selected for processing (1)
  • apps/api/OsmoX.postman_collection.json (2 hunks)

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant