Skip to content
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

Updated chat schema #2466

Merged
merged 104 commits into from
Oct 21, 2024
Merged

Conversation

disha1202
Copy link

@disha1202 disha1202 commented Aug 18, 2024

What kind of change does this PR introduce?

Issue Number:

Fixes #2465

Did you add tests for your changes?

Snapshots/Videos:

If relevant, did you update the documentation?

Summary

Does this PR introduce a breaking change?

Other information

Have you read the contributing guide?

Summary by CodeRabbit

  • New Features

    • Introduced a new unified Chat and ChatMessage structure for improved chat functionality.
    • Added a createChat mutation to facilitate the creation of both direct and group chats.
    • Implemented a unified sendMessageToChat mutation for sending messages to any chat type.
    • Introduced new queries: chatById and chatsByUserId for retrieving chat information.
    • Added subscription for real-time message updates through messageSentToChat.
  • Bug Fixes

    • Enhanced error handling for missing chats and messages, ensuring proper notifications and responses.
  • Documentation

    • Updated GraphQL schema definitions to reflect new naming conventions and functionalities.
  • Tests

    • Expanded test coverage for new chat functionalities and resolver logic to ensure expected behavior.
  • Chores

    • Refined ESLint configuration for improved TypeScript support and consistent naming conventions.

@palisadoes
Copy link
Contributor

@disha1202 Please fix the conflicting files. It seems this is due to the PR I recently merged. I'll try to revert it.

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

🧹 Outside diff range and nitpick comments (3)
tests/resolvers/ChatMessage/sender.spec.ts (3)

17-18: LGTM: Test setup updated correctly, with a minor suggestion.

The beforeAll hook has been updated to use createTestChatMessage instead of createTestDirectChatMessage, which is consistent with the refactoring. The assignment to testChatMessage is correct, using the fourth element of the returned array.

Consider destructuring the array for improved readability:

const [,,, testChatMessage] = await createTestChatMessage();

This makes it clearer that we're intentionally using the fourth element of the returned array.


44-49: LGTM: Second test case updated correctly, with a minor suggestion.

The second test case has been successfully updated to use testChatMessage instead of testDirectChatMessage. The parent object is now correctly created from testChatMessage, maintaining the original test logic while adapting to the new ChatMessage structure.

For consistency with the first test case, consider moving the null check for parent before its usage:

if (testChatMessage?._id) {
  const parent = testChatMessage.toObject();
  if (!parent) {
    throw new Error("Parent object is undefined.");
  }
  parent._id = testChatMessage._id;
  parent.sender = new Types.ObjectId(); // Set to a non-existing ObjectId

  try {
    // ... rest of the test case
  } catch (error: unknown) {
    // ... error handling
  }
}

This change would make the error handling more consistent between the two test cases.

Also applies to: 51-53, 55-61


Line range hint 1-67: Overall consistency is good, with a minor suggestion for the describe block.

The file has been successfully updated to reflect the change from DirectChatMessage to ChatMessage. All references have been consistently updated, and the test logic has been preserved while adapting to the new structure.

Update the describe block to reflect the new ChatMessage structure:

describe("resolvers -> ChatMessage -> sender", () => {
  // ... existing test cases
});

This change would make the describe block consistent with the new ChatMessage naming convention used throughout the file.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between de1dea1 and 6a4ea4b.

📒 Files selected for processing (1)
  • tests/resolvers/ChatMessage/sender.spec.ts (3 hunks)
🧰 Additional context used
🔇 Additional comments (4)
tests/resolvers/ChatMessage/sender.spec.ts (4)

2-2: LGTM: Import path updated correctly.

The import path for the sender resolver has been updated to reflect the new ChatMessage structure, which is consistent with the refactoring from DirectChatMessage to a more generic ChatMessage.


7-8: LGTM: Test helper imports updated correctly.

The imports for TestChatMessageType and createTestChatMessage have been updated to reflect the new chat message structure. This change is consistent with the overall refactoring from DirectChatMessage to ChatMessage.


12-12: LGTM: Test variable declaration updated correctly.

The test variable declaration has been updated from testDirectChatMessage to testChatMessage, with the corresponding type change to TestChatMessageType. This change aligns with the refactoring to a more generic ChatMessage structure.


27-27: LGTM: Test case updated correctly.

The first test case has been updated to use testChatMessage instead of testDirectChatMessage. The parent object is now correctly created from testChatMessage, and the user lookup uses testChatMessage.sender. These changes are consistent with the refactoring to a more generic ChatMessage structure while maintaining the original test logic.

Also applies to: 34-34

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

🧹 Outside diff range and nitpick comments (1)
eslint.config.mjs (1)

113-113: Unnecessary addition of @typescript-eslint plugin for GraphQL files

In the configuration for .graphql files, the @typescript-eslint plugin has been added:

plugins: {
    "@typescript-eslint": typescriptEslint,
},

Since .graphql files are not TypeScript files, including the @typescript-eslint plugin may be unnecessary and could lead to linting issues or confusion. Consider removing the @typescript-eslint plugin from this configuration to keep the linting process accurate and efficient.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6a4ea4b and 7d96ccc.

📒 Files selected for processing (1)
  • eslint.config.mjs (3 hunks)
🧰 Additional context used

},

languageOptions: {
parser: parser,
parser: tsParser,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect parser specified for GraphQL files

The tsParser (TypeScript parser) is set as the parser for .graphql files:

languageOptions: {
    parser: tsParser,
},

Using tsParser for GraphQL files may not be appropriate because .graphql files are not written in TypeScript. This could result in parsing errors or incorrect linting results. Consider using a GraphQL-specific parser or removing the parser specification for this file type if it's not needed.

Apply this diff to correct the parser configuration:

 languageOptions: {
-    parser: tsParser,
 },

@DMills27 DMills27 self-requested a review October 13, 2024 20:54
@palisadoes
Copy link
Contributor

  1. Please fix the conflicting files.
  2. @DMills27 Please review

@disha1202
Copy link
Author

Hi @palisadoes

Updated the PR,
Please look into it

DMills27
DMills27 previously approved these changes Oct 20, 2024
Copy link
Member

@DMills27 DMills27 left a comment

Choose a reason for hiding this comment

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

LGTM

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: 5

🧹 Outside diff range and nitpick comments (7)
src/typeDefs/mutations.ts (3)

87-87: LGTM! Consider adding a description comment.

The addition of the createChat mutation aligns well with the PR objective of consolidating chat types. It provides a flexible approach to chat creation using the generic chatInput type.

Consider adding a brief description comment above the mutation to explain its purpose and usage, similar to other mutations in this file. For example:

# Creates a new chat (either direct or group) based on the provided input
createChat(data: chatInput!): Chat

235-239: LGTM! Consider updating the mutation description.

The modifications to the sendMessageToChat mutation are well-aligned with the PR objectives:

  1. The addition of the optional replyTo parameter enables message threading.
  2. The return type change to ChatMessage! reflects the consolidated chat structure.

Consider updating or adding a description comment for this mutation to reflect its expanded functionality. For example:

# Sends a message to a chat (direct or group) with optional reply functionality
sendMessageToChat(
  chatId: ID!
  messageContent: String!
  replyTo: ID
): ChatMessage! @auth

Line range hint 1-339: Overall changes align well with PR objectives

The modifications to the mutations in this file effectively implement the consolidation of chat types:

  1. Removal of separate direct and group chat mutations (createDirectChat, removeDirectChat, removeGroupChat, sendMessageToDirectChat, etc.).
  2. Introduction of a unified createChat mutation.
  3. Update of sendMessageToChat to handle both direct and group chats with added reply functionality.

These changes simplify the API and provide a more flexible approach to chat management. The new structure should make it easier to maintain and extend chat functionality in the future.

As the chat system evolves, consider the following:

  1. Ensure that the chatInput type is comprehensive enough to handle all chat creation scenarios.
  2. Update related resolvers and services to properly handle the new unified chat structure.
  3. Review and update any client-side code that may be affected by these API changes.
src/typeDefs/inputs.ts (2)

19-24: LGTM! Consider adding a comment for clarity.

The new chatInput type effectively combines DirectChat and GroupChat functionalities, aligning well with the PR objectives. The structure is flexible and accommodates both direct and group chat scenarios.

Consider adding a brief comment above the chatInput type to explain its dual purpose:

"""
Input type for creating or updating a chat, supporting both direct and group chats.
"""
input chatInput {
  # ... existing fields ...
}

This comment would enhance clarity for developers using this input type in the future.


Line range hint 26-30: Clarify the role of createGroupChatInput or consider removing it.

With the introduction of the new chatInput type that handles both direct and group chats, the presence of createGroupChatInput might lead to confusion and potential inconsistencies.

Consider one of the following actions:

  1. If createGroupChatInput is no longer in use, remove it to avoid confusion.
  2. If it's still needed, add a comment explaining its specific use case and how it differs from chatInput.
  3. If it's meant to be deprecated, mark it as such and provide migration instructions to use chatInput instead.

Example of deprecation:

"""
@deprecated Use `chatInput` with `isGroup: true` instead.
This input type will be removed in a future version.
"""
input createGroupChatInput {
  # ... existing fields ...
}

Clarifying or removing this input type will ensure consistency and prevent potential maintenance issues in the future.

src/constants.ts (1)

Line range hint 1-1023: Consider refactoring constants for improved maintainability.

While the addition of MESSAGE_NOT_FOUND_ERROR is appropriate, I've noticed that this file contains a large number of constants. To improve maintainability and readability, consider the following suggestions:

  1. Group related constants into separate files (e.g., errorConstants.ts, configConstants.ts, etc.).
  2. Use enums for related constant groups where applicable.
  3. Consider using a more structured approach for error constants, such as a class-based system that allows for easy internationalization and consistent error handling.

Here's an example of how you might start refactoring:

// errorConstants.ts
export enum ErrorCode {
  NOT_FOUND = 'notFound',
  ALREADY_EXISTS = 'alreadyExists',
  UNAUTHORIZED = 'unauthorized',
  // ... other error codes
}

export class AppError {
  constructor(
    public code: ErrorCode,
    public message: string,
    public param: string
  ) {}

  static MESSAGE_NOT_FOUND = new AppError(
    ErrorCode.NOT_FOUND,
    'Message not found',
    'message'
  );

  // ... other error constants
}

// Usage
throw AppError.MESSAGE_NOT_FOUND;

This approach would make the constants more maintainable and easier to use consistently throughout the application.

src/typeDefs/types.ts (1)

721-734: Make the admins Field Non-Nullable for Better Type Safety

The admins field is defined as [User], which allows the list or its elements to be null. If a chat should always have an admins list (even if empty) and each admin should be a valid User, consider defining the field as [User!]! to enhance type safety and prevent potential null values.

Apply this diff to update the field type:

 admins: [User]
+admins: [User!]!
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7d96ccc and 63336b2.

📒 Files selected for processing (8)
  • eslint.config.mjs (0 hunks)
  • schema.graphql (6 hunks)
  • src/constants.ts (1 hunks)
  • src/resolvers/Mutation/index.ts (4 hunks)
  • src/typeDefs/inputs.ts (1 hunks)
  • src/typeDefs/mutations.ts (2 hunks)
  • src/typeDefs/types.ts (1 hunks)
  • src/types/generatedGraphQLTypes.ts (20 hunks)
💤 Files with no reviewable changes (1)
  • eslint.config.mjs
🧰 Additional context used
📓 Learnings (1)
src/types/generatedGraphQLTypes.ts (2)

<retrieved_learning>
Learnt from: disha1202
PR: #2466
File: src/types/generatedGraphQLTypes.ts:3096-3101
Timestamp: 2024-09-22T09:37:15.069Z
Learning: Direct chats do not need to be associated with any organization, so the organizationId field in ChatInput remains optional.
</retrieved_learning>

<retrieved_learning>
Learnt from: disha1202
PR: #2466
File: src/types/generatedGraphQLTypes.ts:3096-3101
Timestamp: 2024-10-08T16:13:41.996Z
Learning: Direct chats do not need to be associated with any organization, so the organizationId field in ChatInput remains optional.
</retrieved_learning>

🔇 Additional comments (11)
src/resolvers/Mutation/index.ts (3)

25-25: LGTM: Import changes align with PR objectives.

The addition of createChat and sendMessageToChat imports, along with the removal of separate direct and group chat imports (not visible in the diff), aligns well with the PR objective of consolidating chat functionality. This change supports the transition to a unified Chat entity.

Also applies to: 84-84


Line range hint 1-235: Summary: Changes align well with PR objectives.

The modifications to src/resolvers/Mutation/index.ts effectively support the consolidation of chat functionality:

  1. Removal of separate direct and group chat imports and exports.
  2. Addition of unified createChat and sendMessageToChat imports and exports.

These changes are minimal, focused, and consistent with the PR objective of merging DirectChat and GroupChat into a single Chat entity. The file maintains its original purpose as a central point for mutation resolvers, reducing the risk of unintended side effects.


146-146: LGTM: Export changes support unified chat structure.

The addition of createChat and sendMessageToChat exports in the Mutation object, coupled with the removal of separate direct and group chat exports (not visible in the diff), effectively supports the new unified chat structure. This change is consistent with the PR objectives.

To ensure all necessary chat-related mutations are accounted for, please run the following verification script:

Also applies to: 202-202

✅ Verification successful

Verified: Chat-related mutations are correctly updated.

The new mutations createChat and sendMessageToChat are present in the Mutation object, and the old mutations have been successfully removed. This confirms that the export changes effectively support the unified chat structure as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all necessary chat-related mutations are present and no old mutations remain.

# Test: Check for the presence of new chat mutations and absence of old ones
echo "Checking for new chat mutations:"
grep -n "createChat" src/resolvers/Mutation/index.ts
grep -n "sendMessageToChat" src/resolvers/Mutation/index.ts

echo "Checking for absence of old chat mutations:"
grep -n "createDirectChat" src/resolvers/Mutation/index.ts
grep -n "createGroupChat" src/resolvers/Mutation/index.ts
grep -n "sendMessageToDirectChat" src/resolvers/Mutation/index.ts
grep -n "sendMessageToGroupChat" src/resolvers/Mutation/index.ts

Length of output: 681

src/constants.ts (1)

67-72: LGTM! New error constant added for message not found scenario.

The new MESSAGE_NOT_FOUND_ERROR constant is well-structured and consistent with other error constants in the file. This addition aligns with the chat system updates mentioned in the PR objectives.

To ensure this new constant is being utilized correctly, please run the following script to check its usage in chat-related files:

✅ Verification successful

Verification Complete: MESSAGE_NOT_FOUND_ERROR is properly utilized across relevant files.

No issues found regarding the usage of the new error constant.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check usage of MESSAGE_NOT_FOUND_ERROR in chat-related files

# Search for MESSAGE_NOT_FOUND_ERROR in all .ts files
echo "Searching for MESSAGE_NOT_FOUND_ERROR usage:"
rg "MESSAGE_NOT_FOUND_ERROR" --type ts

# Search for potential spots where MESSAGE_NOT_FOUND_ERROR should be used
echo "\nPotential spots where MESSAGE_NOT_FOUND_ERROR might be needed:"
rg "message.*not.*found" --type ts

Length of output: 1432

src/typeDefs/types.ts (1)

736-745: Clarify the Purpose and Usage of the deletedBy Field

The deletedBy field in the ChatMessage type is defined as [User], suggesting that multiple users can delete the same message independently, affecting their view of the chat. Please verify if the intended behavior is to support per-user message deletion (soft deletion) or global deletion.

To confirm how deletedBy is used across the codebase, you can run the following script:

This will help determine if the implementation aligns with the desired message deletion functionality.

schema.graphql (2)

193-206: Well-structured 'Chat' type with essential fields

The Chat type is appropriately defined, including all necessary fields for chat functionality. The use of non-nullable types where necessary enhances data integrity.


1602-1602: ⚠️ Potential issue

Add authentication directive to 'messageSentToChat' subscription

To secure the subscription and prevent unauthorized access to chat messages, include the @auth directive.

Apply this diff:

 type Subscription {
-  messageSentToChat(userId: ID!): ChatMessage
+  messageSentToChat(userId: ID!): ChatMessage @auth
   ...
 }

Likely invalid or redundant comment.

src/types/generatedGraphQLTypes.ts (4)

13-14: Imports for Chat Models Added Correctly

The new chat models InterfaceChat and InterfaceChatMessage are imported appropriately.


265-279: Chat Type Definition Aligns with Unified Schema

The Chat type is well-defined and reflects the consolidation of direct and group chats into a single entity.


281-291: ChatMessage Type Defined Accurately

The ChatMessage type correctly represents messages within the unified chat structure.


3106-3109: ChatInput Type Includes Necessary Fields

The ChatInput type provides the required fields for creating both group and direct chats.

Comment on lines +721 to +734
type Chat {
_id: ID!
isGroup: Boolean!
name: String
createdAt: DateTime!
creator: User
messages: [ChatMessage]
organization: Organization
updatedAt: DateTime!
users: [User!]!
admins: [User]
lastMessageId: String
image: String
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure Consistent Use of ID Type for Identifiers

The lastMessageId field in the Chat type is currently defined as String. Since it represents an identifier for a message, consider changing its type to ID for consistency and clarity.

Apply this diff to update the field type:

 lastMessageId: String
+lastMessageId: ID
📝 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
type Chat {
_id: ID!
isGroup: Boolean!
name: String
createdAt: DateTime!
creator: User
messages: [ChatMessage]
organization: Organization
updatedAt: DateTime!
users: [User!]!
admins: [User]
lastMessageId: String
image: String
}
type Chat {
_id: ID!
isGroup: Boolean!
name: String
createdAt: DateTime!
creator: User
messages: [ChatMessage]
organization: Organization
updatedAt: DateTime!
users: [User!]!
admins: [User]
lastMessageId: ID
image: String
}

Comment on lines +208 to +217
type ChatMessage {
_id: ID!
chatMessageBelongsTo: Chat!
createdAt: DateTime!
deletedBy: [User]
messageContent: String!
replyTo: ChatMessage
sender: User!
updatedAt: DateTime!
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding a 'type' field to 'ChatMessage' for message categorization

Including a type field in the ChatMessage type can help categorize messages (e.g., TEXT, IMAGE, VIDEO). This enhances flexibility and allows clients to handle different message types appropriately.

Define the MessageType enum:

enum MessageType {
  TEXT
  IMAGE
  VIDEO
  FILE
}

Update the ChatMessage type:

 type ChatMessage {
   _id: ID!
   chatMessageBelongsTo: Chat!
   createdAt: DateTime!
   deletedBy: [User]
   messageContent: String!
   replyTo: ChatMessage
   sender: User!
   updatedAt: DateTime!
+  type: MessageType!
 }

removeUserFromUserFamily(familyId: ID!, userId: ID!): UserFamily!
removeUserImage: User!
removeUserTag(id: ID!): UserTag
resetCommunity: Boolean!
revokeRefreshTokenForUser: Boolean!
saveFcmToken(token: String): Boolean!
sendMembershipRequest(organizationId: ID!): MembershipRequest!
sendMessageToDirectChat(chatId: ID!, messageContent: String!): DirectChatMessage!
sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage!
sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID): ChatMessage!
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include 'type' parameter in 'sendMessageToChat' mutation

Adding a type parameter to the sendMessageToChat mutation allows specifying the message type, aligning with the updated ChatMessage structure.

Update the mutation signature:

 type Mutation {
-  sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID): ChatMessage!
+  sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID, type: MessageType!): ChatMessage!
   ...
 }
📝 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
sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID): ChatMessage!
sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID, type: MessageType!): ChatMessage!

@@ -1500,12 +1467,11 @@
agendaItemByEvent(relatedEventId: ID!): [AgendaItem]
agendaItemByOrganization(organizationId: ID!): [AgendaItem]
agendaItemCategoriesByOrganization(organizationId: ID!): [AgendaCategory]
chatById(id: ID!): Chat!
chatsByUserId(id: ID!): [Chat]
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Implement pagination in 'chatsByUserId' query to enhance performance

Fetching all chats for a user at once can lead to performance bottlenecks, especially for users with many chats. Implementing pagination improves scalability and user experience.

Modify the chatsByUserId query:

 type Query {
-  chatsByUserId(id: ID!): [Chat]
+  chatsByUserId(id: ID!, first: Int, after: String): ChatConnection
   ...
 }

+type ChatConnection {
+  edges: [ChatEdge]
+  pageInfo: PageInfo!
+}
+
+type ChatEdge {
+  cursor: String!
+  node: Chat
+}

Committable suggestion was skipped due to low confidence.

Comment on lines +2019 to +2022
input chatInput {
image: String
isGroup: Boolean!
name: String
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure 'organizationId' is required when 'isGroup' is true in 'chatInput'

For group chats associated with an organization, making organizationId mandatory when isGroup is true ensures data consistency and proper linkage.

Consider updating the chatInput definition:

 input chatInput {
   image: String
   isGroup: Boolean!
   name: String
-  organizationId: ID
+  organizationId: ID  # Consider making this non-nullable when isGroup is true
   userIds: [ID!]!
 }

Implement validation logic to enforce this constraint during mutation processing.

Committable suggestion was skipped due to low confidence.

@DMills27
Copy link
Member

@disha1202 Please fix the conflicting files.

@disha1202 disha1202 dismissed DMills27’s stale review October 21, 2024 12:55

The merge-base changed after approval.

@disha1202
Copy link
Author

Hi @DMills27

Fixed conflicting files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants