Skip to content

Conversation

Adi-204
Copy link
Member

@Adi-204 Adi-204 commented Sep 1, 2025

Description
Add new component QueryParamsVariables and refactor existing codebase.

Related issue(s)
Fixex #1704

Summary by CodeRabbit

  • New Features

    • Added a shared component that renders language- and framework-specific query-parameter code for Python, Java (Quarkus) and JavaScript.
  • Refactor

    • Replaced per-template query-parameter components with the consolidated shared component in WebSocket client templates.
  • Tests

    • Added snapshot tests across languages/scenarios and updated fixture to include WebSocket query parameters; removed legacy per-template tests.
  • Chores

    • Exported/published the shared component for reuse.

Copy link

changeset-bot bot commented Sep 1, 2025

⚠️ No Changeset found

Latest commit: f92e995

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

Copy link

coderabbitai bot commented Sep 1, 2025

Walkthrough

Adds a shared, language-and-framework-aware React component QueryParamsVariables to packages/components, exports it, updates Java Quarkus and Python websocket templates to import and use the shared component (passing language/framework), removes template-local implementations and a Python test file, and adds cross-language snapshot tests plus a fixture with ws query params.

Changes

Cohort / File(s) Summary
Shared component & export
packages/components/src/components/QueryParamsVariables.js, packages/components/src/index.js
New QueryParamsVariables component implementing language/framework-specific code generation for query params (python, javascript, java/quarkus) and exported from package index.
Shared tests & fixture
packages/components/test/components/QueryParamsVariables.test.js, packages/components/test/__fixtures__/asyncapi-v3.yml
Adds snapshot tests exercising python, javascript, java/quarkus renderings and edge cases; fixture extended with a ws binding including query parameters.
Java (Quarkus) template update
packages/templates/clients/websocket/java/quarkus/components/Constructor.js, deleted packages/templates/clients/websocket/java/quarkus/components/QueryParamsVariables.js
Template now imports QueryParamsVariables from @asyncapi/generator-components and invokes it with language="java", framework="quarkus"; local QueryParamsVariables implementation removed.
Python template update & test removal
packages/templates/clients/websocket/python/components/Constructor.js, deleted packages/templates/clients/websocket/python/components/QueryParamsVariables.js, deleted packages/templates/clients/websocket/python/test/components/QueryParamsVariables.test.js
Template now imports shared QueryParamsVariables and calls it with language="python"; prior template-local component and its tests removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title succinctly describes the main change: a refactor to move the QueryParamsVariables component into the @asyncapi/generator-components package; this matches the added shared component and deleted template-local components shown in the diff, and it is concise, specific, and relevant for repository history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🧹 Nitpick comments (5)
packages/components/src/components/QueryParamsVariables.js (1)

101-121: Add stable keys to rendered nodes to avoid React warnings.

Provide keys on siblings returned from map.

Apply:

-  return queryParams.map((param) => {
+  return queryParams.map((param) => {
     const { variableDefinition, ifCondition, assignment, closing } = generateParamCode(param);
+    const keyBase = param[0];
 
-    return (
-      <>
-        <Text indent={variableDefinition.indent} newLines={variableDefinition.newLines}>
+    return (
+      <>
+        <Text key={`${keyBase}-var`} indent={variableDefinition.indent} newLines={variableDefinition.newLines}>
           {variableDefinition.text}
         </Text>
-        <Text indent={ifCondition.indent} newLines={ifCondition.newLines}>
+        <Text key={`${keyBase}-if`} indent={ifCondition.indent} newLines={ifCondition.newLines}>
           {ifCondition.text}
         </Text>
-        <Text indent={assignment.indent} newLines={assignment.newLines}>
+        <Text key={`${keyBase}-assign`} indent={assignment.indent} newLines={assignment.newLines}>
           {assignment.text}
         </Text>
-        {closing && (
-          <Text indent={closing.indent} newLines={closing.newLines}>
+        {closing && (
+          <Text key={`${keyBase}-close`} indent={closing.indent} newLines={closing.newLines}>
             {closing.text}
           </Text>
         )}
       </>
     );
   });
packages/templates/clients/websocket/java/quarkus/components/Constructor.js (1)

16-19: Remove redundant conditional and stabilize formatting of params initialization.

This block only renders when queryParamsArray has entries (early return above), so the ternary is unnecessary. Also add newLines for consistent output.

-      <Text indent={6} >
-        {`${ queryParamsArray && queryParamsArray.length > 0 ? 'params = new HashMap<>(); ' : ''}`
-        }
-      </Text>
+      <Text indent={6} newLines={1}>
+        {'params = new HashMap<>();'}
+      </Text>
packages/templates/clients/websocket/python/components/Constructor.js (1)

31-37: Align param initialization with actual presence of entries (consistency with Java).

Currently params = {} emits when query exists, even if it has 0 entries. Not harmful, but inconsistent with Java and slightly noisier output.

-      ${ query ? 'params = {}' : ''}`
+      ${ queryParamsArray && queryParamsArray.length > 0 ? 'params = {}' : ''}`
         }
       </Text>
       <QueryParamsVariables
         language="python"
         queryParams={queryParamsArray} 
       />
packages/components/test/components/QueryParamsVariables.test.js (2)

18-29: Stabilize snapshots by sorting query param keys.

Order from Map construction can vary; sorting avoids flaky snapshots.

-    const queryParamsArray = queryParamsObject ? Array.from(queryParamsObject.entries()) : [];
+    const queryParamsArray = queryParamsObject
+      ? Array.from(queryParamsObject.entries()).sort(([a],[b]) => a.localeCompare(b))
+      : [];

31-43: DRY the query params extraction in tests.

Minor duplication across tests; a small helper keeps tests tidy.

-  test('renders java quarkus query params correctly with query parameters', () => {
-    const channels = parsedAsyncAPIDocument.channels();
-    const queryParamsObject = getQueryParams(channels);
-    const queryParamsArray = queryParamsObject ? Array.from(queryParamsObject.entries()) : [];
+  const buildQueryParamsArray = () => {
+    const channels = parsedAsyncAPIDocument.channels();
+    const queryParamsObject = getQueryParams(channels);
+    return queryParamsObject
+      ? Array.from(queryParamsObject.entries()).sort(([a],[b]) => a.localeCompare(b))
+      : [];
+  };
+
+  test('renders java quarkus query params correctly with query parameters', () => {
+    const queryParamsArray = buildQueryParamsArray();
     const result = render(
       <QueryParamsVariables 
         language='java'
         framework='quarkus' 
         queryParams={queryParamsArray} 
       />
     );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 15886c5 and 82daa7c.

⛔ Files ignored due to path filters (2)
  • packages/components/test/components/__snapshots__/QueryParamsVariables.test.js.snap is excluded by !**/*.snap
  • packages/templates/clients/websocket/python/test/components/__snapshots__/QueryParamsVariables.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (9)
  • packages/components/src/components/QueryParamsVariables.js (1 hunks)
  • packages/components/src/index.js (1 hunks)
  • packages/components/test/__fixtures__/asyncapi-v3.yml (1 hunks)
  • packages/components/test/components/QueryParamsVariables.test.js (1 hunks)
  • packages/templates/clients/websocket/java/quarkus/components/Constructor.js (2 hunks)
  • packages/templates/clients/websocket/java/quarkus/components/QueryParamsVariables.js (0 hunks)
  • packages/templates/clients/websocket/python/components/Constructor.js (2 hunks)
  • packages/templates/clients/websocket/python/components/QueryParamsVariables.js (0 hunks)
  • packages/templates/clients/websocket/python/test/components/QueryParamsVariables.test.js (0 hunks)
💤 Files with no reviewable changes (3)
  • packages/templates/clients/websocket/python/components/QueryParamsVariables.js
  • packages/templates/clients/websocket/python/test/components/QueryParamsVariables.test.js
  • packages/templates/clients/websocket/java/quarkus/components/QueryParamsVariables.js
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-12T14:23:48.919Z
Learnt from: derberg
PR: asyncapi/generator#1551
File: apps/generator/docs/generator-template.md:45-73
Timestamp: 2025-05-12T14:23:48.919Z
Learning: AsyncAPI 3.0.0 specification introduces significant structural changes from 2.x:
1. Operations become top-level elements with references to channels
2. Channels use 'address' for the topic path instead of having nested publish/subscribe
3. Messages are defined under a 'messages' container in channels
4. Servers can use a 'host' property

Applied to files:

  • packages/components/test/__fixtures__/asyncapi-v3.yml
📚 Learning: 2025-05-12T14:23:48.919Z
Learnt from: derberg
PR: asyncapi/generator#1551
File: apps/generator/docs/generator-template.md:45-73
Timestamp: 2025-05-12T14:23:48.919Z
Learning: AsyncAPI 3.0.0 specification introduces significant structural changes from 2.x:
1. Operations become top-level elements with action property (send/receive) and references to channels
2. Channels use 'address' for the topic path instead of having nested publish/subscribe operations
3. Messages are defined under a 'messages' container in channels
4. The specification decouples operations, channels and messages to improve reusability
5. Servers can use a 'host' property

Applied to files:

  • packages/components/test/__fixtures__/asyncapi-v3.yml
🧬 Code graph analysis (4)
packages/components/test/components/QueryParamsVariables.test.js (3)
packages/templates/clients/websocket/java/quarkus/components/Constructor.js (1)
  • queryParamsArray (7-7)
packages/templates/clients/websocket/python/components/Constructor.js (1)
  • queryParamsArray (7-7)
packages/components/src/components/QueryParamsVariables.js (1)
  • QueryParamsVariables (94-123)
packages/templates/clients/websocket/java/quarkus/components/Constructor.js (3)
packages/components/src/components/QueryParamsVariables.js (1)
  • QueryParamsVariables (94-123)
packages/templates/clients/websocket/java/quarkus/components/ClientConnector.js (1)
  • queryParamsArray (6-6)
packages/templates/clients/websocket/java/quarkus/components/ClientFields.js (1)
  • queryParamsArray (6-6)
packages/components/src/components/QueryParamsVariables.js (1)
packages/helpers/src/utils.js (1)
  • toCamelCase (78-82)
packages/templates/clients/websocket/python/components/Constructor.js (2)
packages/components/src/components/QueryParamsVariables.js (1)
  • QueryParamsVariables (94-123)
packages/templates/clients/websocket/java/quarkus/components/Constructor.js (1)
  • queryParamsArray (7-7)
⏰ 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). (5)
  • GitHub Check: Test generator as dependency with Node 18
  • GitHub Check: Test generator as dependency with Node 20
  • GitHub Check: Acceptance tests for generated templates
  • GitHub Check: Test NodeJS PR - macos-13
  • GitHub Check: Test NodeJS PR - windows-latest
🔇 Additional comments (10)
packages/components/test/__fixtures__/asyncapi-v3.yml (1)

12-28: WS channel binding with query schema looks correct.

Schema structure and defaults align with AsyncAPI 3 + WebSocket channel binding expectations.

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

24-41: No missing Python imports or params initialization
The Python client templates already emit import os via Requires.js and initialize params = {} in Constructor.js when query parameters are used—no updates needed.

Likely an incorrect or invalid review comment.

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

6-7: Export looks good.

Public API wiring for QueryParamsVariables is correct.

packages/templates/clients/websocket/java/quarkus/components/Constructor.js (2)

20-24: Props passed to QueryParamsVariables look correct.

language="java" and framework="quarkus" align with the shared component API.


4-4: Dependency wiring verified: No stale local imports of QueryParamsVariables; @asyncapi/generator-components is declared at v0.2.0 in the template’s package.json.

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

34-37: Props passed to QueryParamsVariables look correct.

language="python" is sufficient here.


2-2: Dependency wiring verified
No local QueryParamsVariables imports remain, and @asyncapi/generator-components@0.2.0 is declared in package.json.

packages/components/test/components/QueryParamsVariables.test.js (3)

1-6: Solid test scaffolding.

Imports and render setup look good.


13-17: Efficient parse strategy.

Parsing once in beforeAll is optimal.


45-62: Good negative-case coverage.

Null, undefined, and empty-array cases are covered.

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.

how about enabling it for JS in the same PR?

@Adi-204
Copy link
Member Author

Adi-204 commented Sep 1, 2025

how about enabling it for JS in the same PR?

@derberg so you mean like just adding JS in QueryParamsVariables or use it in constructor also in same PR like other templates.

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

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

24-41: Python fallback must not override valid falsey values; also sanitize env var name.

Use an explicit None-check and a sanitized env key so False/0/"" are preserved and env names remain POSIX-safe.

   python: (param) => {
-    const paramName = param[0];
+    const rawName = param[0];
+    const envKey = rawName.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase();
     return {
       variableDefinition: {
-        text: `${paramName} = ${paramName} or os.getenv("${paramName.toUpperCase()}")`,
+        text: `${rawName} = ${rawName} if ${rawName} is not None else os.getenv("${envKey}")`,
         indent: 8,
       },
       ifCondition: {
-        text: `if ${paramName} is not None:`,
+        text: `if ${rawName} is not None:`,
         indent: 8,
       },
       assignment: {
-        text: `params["${paramName}"] = ${paramName}`,
+        text: `params["${rawName}"] = ${rawName}`,
         indent: 10,
       },
       closing: null,
     };
   },

To ensure generated Python compiles, verify the Python template emits import os:

#!/bin/bash
# Verify Python websocket constructor/template includes 'import os'
rg -n -C2 --glob 'packages/templates/**/python/**' -S '\bimport os\b'

43-65: Java (Quarkus): fix env var key, params key, and guard against empties.

Only the field should be camelCase; env var and query key should use the raw name. Also avoid inserting empty strings.

   java: {
     quarkus: (param) => {
-      const paramName = toCamelCase(param[0]);
+      const rawName = param[0];
+      const fieldName = toCamelCase(rawName);
+      const envKey = rawName.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase();
       return {
         variableDefinition: {
-          text: `this.${paramName} = (${paramName} != null && !${paramName}.isEmpty()) ? ${paramName} : System.getenv("${paramName.toUpperCase()}");`,
+          text: `this.${fieldName} = (${fieldName} != null && !${fieldName}.isEmpty()) ? ${fieldName} : System.getenv("${envKey}");`,
           indent: 6,
         },
         ifCondition: {
-          text: `if (this.${paramName} != null){`,
+          text: `if (this.${fieldName} != null && !this.${fieldName}.isEmpty()){`,
           indent: 6,
         },
         assignment: {
-          text: `params.put("${paramName}", this.${paramName});`,
+          text: `params.put("${rawName}", this.${fieldName});`,
           indent: 8,
         },
         closing: {
           text: '}',
           indent: 6,
           newLines: 1,
         },
       };
     },

97-105: Fail fast for unsupported language/framework in resolver.

Returning undefined here crashes later. Throw a clear error as previously suggested.

 function resolveQueryParamLogic(language, framework = '') {
   const config = queryParamLogicConfig[language];
   if (typeof config === 'function') {
     return config;
   }
   if (framework && config[framework]) {
     return config[framework];
   }
+  throw new Error(`[QueryParamsVariables] Unsupported language "${language}"${framework ? ` and framework "${framework}"` : ''}.`);
 }
🧹 Nitpick comments (1)
packages/components/src/components/QueryParamsVariables.js (1)

122-143: Add a stable key to each mapped fragment.

Prevents React key warnings in generator runtime.

-  return queryParams.map((param) => {
+  return queryParams.map((param) => {
+    const rawNameForKey = Array.isArray(param) ? param[0] : String(param);
     const { variableDefinition, ifCondition, assignment, closing } = generateParamCode(param);
 
-    return (
-      <>
+    return (
+      <React.Fragment key={rawNameForKey}>
         <Text indent={variableDefinition.indent} newLines={variableDefinition.newLines}>
           {variableDefinition.text}
         </Text>
         <Text indent={ifCondition.indent} newLines={ifCondition.newLines}>
           {ifCondition.text}
         </Text>
         <Text indent={assignment.indent} newLines={assignment.newLines}>
           {assignment.text}
         </Text>
         {closing && (
           <Text indent={closing.indent} newLines={closing.newLines}>
             {closing.text}
           </Text>
         )}
-      </>
+      </React.Fragment>
     );
   });

Add this import at the top of the file:

import React from 'react';
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 82daa7c and 4e8112e.

⛔ Files ignored due to path filters (1)
  • packages/components/test/components/__snapshots__/QueryParamsVariables.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • packages/components/src/components/QueryParamsVariables.js (1 hunks)
  • packages/components/test/components/QueryParamsVariables.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/components/test/components/QueryParamsVariables.test.js
🧰 Additional context used
🧬 Code graph analysis (1)
packages/components/src/components/QueryParamsVariables.js (1)
packages/helpers/src/utils.js (1)
  • toCamelCase (78-82)
⏰ 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: Acceptance tests for generated templates
  • 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 (1)
packages/components/src/components/QueryParamsVariables.js (1)

24-86: Align “include param” semantics across languages.

Python/JS changes include empty strings and 0/false; Java excludes empty strings. Confirm desired cross-language behavior and adjust consistently.

If the intent is “include when not null/undefined”:

  • Python: keep “is not None”.
  • Java: drop !isEmpty().
  • JS: use !== undefined && !== null.

Also applies to: 43-65

Copy link

@Adi-204
Copy link
Member Author

Adi-204 commented Sep 23, 2025

@derberg ready for review!

@derberg derberg changed the title feat: move QueryParamsVariables component to @asyncapi/generator-components refactor: move QueryParamsVariables component to @asyncapi/generator-components Sep 23, 2025
@derberg
Copy link
Member

derberg commented Sep 23, 2025

@Adi-204 I meant enabling query params support in JS template - but yeah, not in scope here

/rtm

@asyncapi-bot asyncapi-bot merged commit 61c3788 into asyncapi:master Sep 23, 2025
22 checks passed
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.

3 participants