Skip to content

Conversation

@Adi-204
Copy link
Member

@Adi-204 Adi-204 commented Aug 10, 2025

Description
Add new component RegisterMessageHandler and refactor existing codebase.

Related issue(s)
Fixes #1662

Summary by CodeRabbit

  • New Features

    • Introduced a configurable component to render WebSocket message handler registration methods in Python, JavaScript, and Dart, with support for custom method names, parameters, and code snippets.
  • Refactor

    • Unified message handler registration logic into a single component, replacing separate implementations for each language.
    • Updated client templates to use the new component with language-specific configurations.
    • Centralized method rendering logic by introducing a new component for generating method code snippets.
    • Refactored connection closing component to leverage the new method generation component.
  • Tests

    • Added comprehensive tests to ensure correct rendering across different languages and configurations.

@changeset-bot
Copy link

changeset-bot bot commented Aug 10, 2025

⚠️ No Changeset found

Latest commit: 7e043b8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Aug 10, 2025

Walkthrough

A new reusable RegisterMessageHandler React component was introduced in the @asyncapi/generator-components package to support rendering message handler registration methods for Python, JavaScript, and Dart. Language-specific implementations and their usages in client templates were replaced with this generalized component. Corresponding tests were added, and template usages were updated to leverage the new component.

Changes

Cohort / File(s) Change Summary
Component Introduction & Export
packages/components/src/components/RegisterMessageHandler.js, packages/components/src/index.js
Added new generic RegisterMessageHandler component supporting Python, JavaScript, and Dart; exported from the main index.
Component Testing
packages/components/test/components/RegisterMessageHandler.test.js
Added tests covering various languages, method names, parameters, and code snippets for the new component.
Dart Client Template Refactor
packages/templates/clients/websocket/dart/components/ClientClass.js, packages/templates/clients/websocket/dart/components/RegisterMessageHandler.js
Updated to use the new generic component with Dart-specific props; removed the old Dart-specific component.
JavaScript Client Template Refactor
packages/templates/clients/websocket/javascript/components/ClientClass.js, packages/templates/clients/websocket/javascript/components/RegisterMessageHandler.js
Updated to use the new generic component with JavaScript-specific props; removed the old JavaScript-specific component.
Python Client Template Refactor
packages/templates/clients/websocket/python/components/ClientClass.js, packages/templates/clients/websocket/python/components/RegisterMessageHandler.js
Updated to use the new generic component with Python-specific props and docstring; removed the old Python-specific component.
Method Rendering Refactor
packages/components/src/components/MethodGenerator.js, packages/components/src/components/CloseConnection.js
Added new generic MethodGenerator component; refactored CloseConnection to delegate method rendering to MethodGenerator.
MethodGenerator Testing
packages/components/test/components/MethodGenerator.test.js
Added tests to verify MethodGenerator output across languages, configurations, and code variations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Assessment against linked issues

Objective Addressed Explanation
Introduce new component for RegisterMessageHandler in @asyncapi/generator-components (#1662)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes detected.

Possibly related PRs

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

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

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate unit tests to generate unit tests 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.

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.

@asyncapi-bot
Copy link
Contributor

What reviewer looks at during PR review

The following are ideal points maintainers look for during review. Reviewing these points yourself beforehand can help streamline the review process and reduce time to merge.

  1. PR Title: Use a concise title that follows our Conventional Commits guidelines and clearly summarizes the change using imperative mood (it means spoken or written as if giving a command or instruction, like "add new helper for listing operations")

    Note - In Generator, prepend feat: or fix: in PR title only when PATCH/MINOR release must be triggered.

  2. PR Description: Clearly explain the issue being solved, summarize the changes made, and mention the related issue.

    Note - In Generator, we use Maintainers Work board to track progress. Ensure the PR Description includes Resolves #<issue-number> or Fixes #<issue-number> this will automatically close the linked issue when the PR is merged and helps automate the maintainers workflow.

  3. Documentation: Update the relevant Generator documentation to accurately reflect the changes introduced in the PR, ensuring users and contributors have up-to-date guidance.

  4. Comments and JSDoc: Write clear and consistent JSDoc comments for functions, including parameter types, return values, and error conditions, so others can easily understand and use the code.

  5. DRY Code: Ensure the code follows the Don't Repeat Yourself principle. Look out for duplicate logic that can be reused.

  6. Test Coverage: Ensure the new code is well-tested with meaningful test cases that pass consistently and cover all relevant edge cases.

  7. Commit History: Contributors should avoid force-pushing as much as possible. It makes it harder to track incremental changes and review the latest updates.

  8. Template Design Principles Alignment: While reviewing template-related changes in the packages/ directory, ensure they align with the Assumptions and Principles. If any principle feels outdated or no longer applicable, start a discussion these principles are meant to evolve with the project.

  9. Reduce Scope When Needed: If an issue or PR feels too large or complex, consider splitting it and creating follow-up issues. Smaller, focused PRs are easier to review and merge.

  10. Bot Comments: As reviewers, check that contributors have appropriately addressed comments or suggestions made by automated bots. If there are bot comments the reviewer disagrees with, react to them or mark them as resolved, so the review history remains clear and accurate.

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

🧹 Nitpick comments (3)
packages/components/test/components/RegisterMessageHandler.test.js (1)

1-83: Solid snapshot coverage across languages (LGTM) + add a negative test

Coverage looks good: default rendering, custom names, params, and pre/post code across JS/Python/Dart. Two improvements:

  • Add a negative test asserting a clear error for unsupported language (e.g., language='go') to lock in failure mode if configs are missing.
  • Optional: Prefer inline snapshots for faster review and to keep tests self-contained.

If you want, I can propose a negative test snippet for an unsupported language.

packages/components/src/components/RegisterMessageHandler.js (2)

24-27: Python block indentation: keep inner suites consistent

The if/else suites use different inner indentation widths (2 vs 4). Make them consistent to avoid style regressions in generated code.

 if callable(handler):
   self.message_handlers.append(handler)
 else:
-    print("Message handler must be callable")
+  print("Message handler must be callable")

46-53: JSDoc defaults: use bracket syntax for optional params

Use standard JSDoc optional/default notation to improve tooling support.

- * @param {Object} props - Component props.
- * @param {Language} props.language - Programming language used for method formatting.
- * @param {string} props.methodName='registerMessageHandler' - Name of the method to generate.
- * @param {string[]} props.methodParams=[] - List of parameters for the method.
- * @param {string} props.preExecutionCode - Code to insert before the main function logic.
- * @param {string} props.postExecutionCode - Code to insert after the main function logic.
+ * @param {Object} props - Component props.
+ * @param {Language} props.language - Programming language used for method formatting.
+ * @param {string} [props.methodName='registerMessageHandler'] - Name of the method to generate.
+ * @param {string[]} [props.methodParams=[]] - List of parameters for the method.
+ * @param {string} [props.preExecutionCode] - Code to insert before the main function logic.
+ * @param {string} [props.postExecutionCode] - Code to insert after the main function logic.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61653bc and a2e27aa.

⛔ Files ignored due to path filters (2)
  • packages/components/test/components/__snapshots__/RegisterMessageHandler.test.js.snap is excluded by !**/*.snap
  • packages/templates/clients/websocket/test/integration-test/__snapshots__/integration.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (9)
  • packages/components/src/components/RegisterMessageHandler.js (1 hunks)
  • packages/components/src/index.js (1 hunks)
  • packages/components/test/components/RegisterMessageHandler.test.js (1 hunks)
  • packages/templates/clients/websocket/dart/components/ClientClass.js (2 hunks)
  • packages/templates/clients/websocket/dart/components/RegisterMessageHandler.js (0 hunks)
  • packages/templates/clients/websocket/javascript/components/ClientClass.js (2 hunks)
  • packages/templates/clients/websocket/javascript/components/RegisterMessageHandler.js (0 hunks)
  • packages/templates/clients/websocket/python/components/ClientClass.js (2 hunks)
  • packages/templates/clients/websocket/python/components/RegisterMessageHandler.js (0 hunks)
💤 Files with no reviewable changes (3)
  • packages/templates/clients/websocket/dart/components/RegisterMessageHandler.js
  • packages/templates/clients/websocket/javascript/components/RegisterMessageHandler.js
  • packages/templates/clients/websocket/python/components/RegisterMessageHandler.js
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/templates/clients/websocket/dart/components/ClientClass.js (1)
packages/components/src/components/RegisterMessageHandler.js (1)
  • RegisterMessageHandler (54-91)
packages/templates/clients/websocket/python/components/ClientClass.js (1)
packages/components/src/components/RegisterMessageHandler.js (1)
  • RegisterMessageHandler (54-91)
packages/templates/clients/websocket/javascript/components/ClientClass.js (1)
packages/components/src/components/RegisterMessageHandler.js (1)
  • RegisterMessageHandler (54-91)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Acceptance tests for generated templates
  • GitHub Check: Test generator as dependency with Node 20
  • GitHub Check: Test generator as dependency with Node 18
  • GitHub Check: Test NodeJS PR - windows-latest
  • GitHub Check: Test NodeJS PR - macos-13
  • GitHub Check: Test NodeJS PR - ubuntu-latest
🔇 Additional comments (6)
packages/components/src/index.js (1)

4-5: Exports Verified: RegisterMessageHandler is properly exposed

I’ve confirmed that:

  • packages/components/src/components/RegisterMessageHandler.js exists.
  • packages/components/src/index.js re-exports it.
  • packages/components/package.json’s main field points to lib/index.js, so downstream consumers will resolve it correctly.
  • There are no shipped TypeScript definitions in this package, so no additional type exports are needed.
packages/templates/clients/websocket/javascript/components/ClientClass.js (1)

18-21: Props are correct for JS (LGTM)

language="javascript" with methodParams={['handler']} aligns with the shared component’s defaults and expected JS signature.

packages/templates/clients/websocket/python/components/ClientClass.js (2)

28-33: Python method signature and docstring positioning look correct (LGTM)

  • methodName='register_message_handler' and methodParams={['self', 'handler']} are idiomatic for Python.
  • Using preExecutionCode with a triple-quoted string ensures it becomes the function’s docstring when it’s the first body statement.

40-44: Consistent CloseConnection usage (LGTM)

CloseConnection configured with language="python" and a docstring is consistent with this refactor.

packages/templates/clients/websocket/dart/components/ClientClass.js (2)

19-22: Dart method signature is well-typed (LGTM)

Using methodParams={['void Function(String) handler']} yields a clear, typed Dart signature and aligns with default methodName for Dart.


26-26: CloseConnection consistency (LGTM)

language="dart" set explicitly — consistent with the shared-component approach.

@sonarqubecloud
Copy link

@Adi-204 Adi-204 changed the title refactor: move RegisterMessageHandler component to @asyncapi/generator-components refactor: move RegisterMessageHandler and MethodGenerator component to @asyncapi/generator-components Aug 10, 2025
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

♻️ Duplicate comments (3)
packages/components/src/components/RegisterMessageHandler.js (1)

44-49: Guard against unsupported languages to avoid runtime crash

websocketMessageRegisterConfig[language] may be undefined. Add a safeguard before destructuring.

 export function RegisterMessageHandler({ language, methodName = 'registerMessageHandler', methodParams = [], preExecutionCode = '', postExecutionCode = '' }) {
-  const {
-    methodDocs = '',
-    methodLogic = ''
-  } = websocketMessageRegisterConfig[language];
+  const wsCfg = websocketMessageRegisterConfig[language];
+  if (!wsCfg) {
+    throw new Error(`Unsupported language: ${language}`);
+  }
+  const {
+    methodDocs = '',
+    methodLogic = '',
+  } = wsCfg;
packages/components/src/components/MethodGenerator.js (2)

12-16: Prefer 4-space Python indentation and control openingTag spacing via config

  • Python typically uses 4 spaces; current indentSize: 2 diverges from common style.
  • Let config carry spacing needs (e.g., ' {' for JS/Dart, ':' for Python) instead of hardcoding builder spaces.

This reduces style issues and aligns with language norms.

-const defaultMethodConfig = {
-  python: { returnType: 'def', openingTag: ':', indentSize: 2 },
-  javascript: { openingTag: '{', closingTag: '}', indentSize: 2 },
-  dart: { returnType: 'void', openingTag: '{', closingTag: '}', indentSize: 2 }
-};
+const defaultMethodConfig = {
+  python: { returnType: 'def', openingTag: ':', indentSize: 4 },
+  // Opening brace includes leading space to avoid manual spacing in the builder
+  javascript: { openingTag: ' {', closingTag: '}', indentSize: 2 },
+  dart: { returnType: 'void', openingTag: ' {', closingTag: '}', indentSize: 2 },
+};

69-72: Fix signature construction: remove unconditional leading blank line and stray spaces

Current template:

  • Adds a blank line when methodDocs is empty.
  • Inserts a leading space when returnType is empty (JS/Dart).
  • Forces a space before Python colon: def foo() :.

Build signature and lines conditionally.

-  const methodCode = `${methodDocs}
-${returnType} ${methodName}(${params}) ${openingTag}
-${indentedLogic}
-${closingTag}`;
+  const signatureParts = [];
+  if (returnType) signatureParts.push(returnType);
+  signatureParts.push(`${methodName}(${params})`);
+  // openingTag includes any required spacing (e.g., ' {' for JS/Dart, ':' for Python)
+  const signature = `${signatureParts.join(' ')}${openingTag}`;
+
+  const methodLines = [];
+  if (methodDocs) methodLines.push(methodDocs);
+  methodLines.push(signature);
+  if (indentedLogic) methodLines.push(indentedLogic);
+  if (closingTag) methodLines.push(closingTag);
+  const methodCode = methodLines.join('\n');
🧹 Nitpick comments (4)
packages/components/test/components/MethodGenerator.test.js (1)

91-99: Empty method body yields a blank line — decide desired style and assert it

With no methodLogic, current output contains an empty line between signature and closing brace. If you prefer compact function() {}/def foo(): without a blank line, update MethodGenerator to omit the body line when empty and adjust snapshots. Otherwise, add a test asserting the intentional blank line to lock the style in.

packages/components/src/components/CloseConnection.js (1)

51-61: Pass newLines explicitly for consistent spacing around generated methods

Other components use newLines={2} to separate methods. If consistent spacing is desired, pass newLines here too (or centralize the default).

-    <MethodGenerator
+    <MethodGenerator
       language={language}
       methodName={methodName}
       methodParams = {methodParams}
       methodDocs = {methodDocs}
       methodLogic = {methodLogic}
       preExecutionCode = {preExecutionCode}
       postExecutionCode = {postExecutionCode}
       indent = {2}
+      newLines = {2}
     />
packages/components/src/components/RegisterMessageHandler.js (1)

50-61: Ensure handler is part of methodParams in caller usage

The logic references handler; if callers forget to pass it in methodParams, generated code will be incorrect. Consider validating methodParams includes the appropriate argument (or document prominently).

packages/components/src/components/MethodGenerator.js (1)

63-68: Avoid indenting empty lines to reduce trailing whitespace and noise

Current mapping adds empty strings (lines with only EOL). After the signature fix above (which already omits empty indented body), behavior is improved. If you keep current approach, consider filtering empty lines before join.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2e27aa and 7e043b8.

⛔ Files ignored due to path filters (1)
  • packages/components/test/components/__snapshots__/MethodGenerator.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • packages/components/src/components/CloseConnection.js (2 hunks)
  • packages/components/src/components/MethodGenerator.js (1 hunks)
  • packages/components/src/components/RegisterMessageHandler.js (1 hunks)
  • packages/components/src/index.js (1 hunks)
  • packages/components/test/components/MethodGenerator.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/components/src/index.js
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/components/src/components/CloseConnection.js (1)
packages/components/src/components/MethodGenerator.js (1)
  • MethodGenerator (33-79)
packages/components/test/components/MethodGenerator.test.js (2)
apps/react-sdk/src/renderer/renderer.ts (1)
  • render (63-77)
packages/components/src/components/MethodGenerator.js (1)
  • MethodGenerator (33-79)
packages/components/src/components/RegisterMessageHandler.js (1)
packages/components/src/components/MethodGenerator.js (1)
  • MethodGenerator (33-79)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test generator as dependency with Node 20
  • GitHub Check: Test generator as dependency with Node 18
  • GitHub Check: Acceptance tests for generated templates
  • GitHub Check: Test NodeJS PR - windows-latest
  • GitHub Check: Test NodeJS PR - ubuntu-latest
  • GitHub Check: Test NodeJS PR - macos-13

@Adi-204
Copy link
Member Author

Adi-204 commented Aug 10, 2025

@derberg I had to add 2 components in one PR because sonar was complaining about code duplication. And now I think it is much more easier to add new components of websocket template and minimal changes to be done.

Copy link
Member

@derberg derberg left a comment

Choose a reason for hiding this comment

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

Interesting approach, let's give it a try, nice job!

@derberg
Copy link
Member

derberg commented Aug 18, 2025

/rtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: Introduce new component for RegisterMessageHandler in @asyncapi/generator-components

3 participants