Skip to content

refactor: update getQueryParams to support multiple channels#2026

Open
SushanthMusham wants to merge 3 commits intoasyncapi:masterfrom
SushanthMusham:fix-getqueryparams-all-channels
Open

refactor: update getQueryParams to support multiple channels#2026
SushanthMusham wants to merge 3 commits intoasyncapi:masterfrom
SushanthMusham:fix-getqueryparams-all-channels

Conversation

@SushanthMusham
Copy link
Copy Markdown

@SushanthMusham SushanthMusham commented Mar 17, 2026

Description

This PR refactors the getQueryParams helper function to return query parameters for all available channels, rather than just the first one. This is a foundational change to support multi-channel WebSocket/Kafka generations.

Changes:

  • Core Helper: Modified getQueryParams in @asyncapi/generator-helpers to return an object keyed by channel names.
  • Compatibility Layers: Since this is a breaking change for existing templates, I implemented "bridge" logic in the following areas to maintain backward compatibility (extracting parameters from the first available channel):
    • @asyncapi/generator-react-sdk (QueryParamsVariables component)
    • core-template-client-websocket-python
    • core-template-client-websocket-java-quarkus
  • Testing: Updated 14+ test suites and associated snapshots to align with the new data structure while ensuring zero regressions in output.

Related Issue(s)

Fixes #1973

Checklist

  • Conventional Commits compliant title.
  • All 17 tasks passed locally via npm test.
  • Snapshots updated and verified.
Screenshot 2026-03-17 at 5 56 31 PM

Summary by CodeRabbit

  • Refactor

    • Consolidated query-parameter handling to support per-channel defaults and added a helper to extract the first channel’s parameters when needed.
  • Templates

    • WebSocket client templates now prefer the first channel’s query parameters when present.
  • Tests

    • Updated Java and Python template tests to align with the first-channel extraction flow.
  • Documentation

    • Updated inline examples to demonstrate the revised query-parameter extraction.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 17, 2026

⚠️ No Changeset found

Latest commit: 0c2900e

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

@asyncapi-bot
Copy link
Copy Markdown
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.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 53c83b28-a6d9-44ee-b33b-495c1837759b

📥 Commits

Reviewing files that changed from the base of the PR and between 56957ea and 0c2900e.

📒 Files selected for processing (1)
  • packages/helpers/src/bindings.js

📝 Walkthrough

Walkthrough

Aggregates WebSocket query parameter defaults across all channels, changes getQueryParams to return a per-channel object, adds getFirstChannelQueryParams (first channel → Map), and updates templates, components, and tests to consume the new shapes and helper. No public signatures were removed.

Changes

Cohort / File(s) Summary
Helpers
packages/helpers/src/bindings.js, packages/helpers/src/index.js, packages/helpers/test/bindings.test.js
getQueryParams now collects ws.query.properties for all channels and returns an object keyed by channel name → parameter object (string defaults). Added and exported getFirstChannelQueryParams which returns the first channel’s parameters as a Map. Tests updated to access channel-keyed results.
Components & Component Tests
packages/components/src/components/QueryParamsVariables.js, packages/components/test/components/QueryParamsVariables.test.js
JSDoc example and tests changed to build queryParamsArray from the first channel’s entries (via first-channel Map/object) instead of an aggregated Map across channels; runtime component logic unchanged.
Java Quarkus Templates & Tests
packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js, .../client.java.js, packages/templates/clients/websocket/java/quarkus/test/components/*.test.js
Templates and tests switched to call getFirstChannelQueryParams(...) and consume Map-style first-channel params; one template generator changed export shape (to module.exports = connector_java) and adjusted generated Java code to use the new query param source.
Python WebSocket Templates & Tests
packages/templates/clients/websocket/python/components/ClientClass.js, packages/templates/clients/websocket/python/template/client.py.js, packages/templates/clients/websocket/python/test/components/*.test.js
Templates/tests now obtain allQueryParams = getQueryParams(channels) then conditionally derive a Map from the first channel’s params (null-guarded). Downstream components receive the first-channel Map or null.
Various Template Tests
packages/templates/clients/websocket/.../test/components/*.test.js
Multiple tests updated to replace getQueryParams(channels) usage with getFirstChannelQueryParams(channels) (or to extract first-channel params from getQueryParams) and to convert returned Map/object into arrays where required for snapshots.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses 'refactor:' prefix and clearly summarizes the main change - updating getQueryParams to support multiple channels instead of just one.
Linked Issues check ✅ Passed The PR successfully implements the objective from issue #1973 by refactoring getQueryParams to handle all channels with ws bindings and introducing getFirstChannelQueryParams for backward compatibility.
Out of Scope Changes check ✅ Passed All changes directly support the refactoring objective: updates to getQueryParams signature, new getFirstChannelQueryParams helper, component updates to use the new helper, and comprehensive test updates. A security-focused commit about null-prototype objects is a minor complementary hardening change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (7)
packages/templates/clients/websocket/python/test/components/QueryParamsArgumentsDocs.test.js (1)

23-26: Guard empty-channel results before first-channel extraction.

If getQueryParams returns an empty object, Line 24 produces undefined and Line 25 will throw on Object.entries(undefined). Add a key-length check before indexing.

Suggested fix
 let queryParamsArray = null;
-if (allQueryParams) {
-  const firstChannelName = Object.keys(allQueryParams)[0];
-  queryParamsArray = Object.entries(allQueryParams[firstChannelName]);
+if (allQueryParams && Object.keys(allQueryParams).length > 0) {
+  const firstChannelName = Object.keys(allQueryParams)[0];
+  const firstChannelQueryParams = allQueryParams[firstChannelName];
+  queryParamsArray = firstChannelQueryParams ? Object.entries(firstChannelQueryParams) : null;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/clients/websocket/python/test/components/QueryParamsArgumentsDocs.test.js`
around lines 23 - 26, The code assumes allQueryParams has at least one key and
does Object.keys(allQueryParams)[0] then Object.entries(...) which will throw if
allQueryParams is empty; update the block that sets firstChannelName and
queryParamsArray to first check that Object.keys(allQueryParams).length > 0 (or
that firstChannelName is truthy) before indexing and calling Object.entries, and
only set queryParamsArray when a channel exists (leave it empty or default
otherwise) so references to firstChannelName and queryParamsArray are safe;
target the variables allQueryParams, firstChannelName and queryParamsArray in
the test.
packages/templates/clients/websocket/python/test/components/Requires.test.js (1)

20-27: Consider adding a defensive check for empty allQueryParams.

If getQueryParams returns an empty object {}, Object.keys(allQueryParams)[0] will be undefined, causing Object.entries(allQueryParams[undefined]) to throw a TypeError. While the fixture presumably contains query params, a small guard would make this more robust:

🛡️ Proposed defensive fix
 const allQueryParams = getQueryParams(channels);
 
 // Convert the first channel's parameters back into a Map so the test doesn't break
 let queryParams = null;
-if (allQueryParams) {
+if (allQueryParams && Object.keys(allQueryParams).length > 0) {
   const firstChannelName = Object.keys(allQueryParams)[0];
   queryParams = new Map(Object.entries(allQueryParams[firstChannelName]));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/templates/clients/websocket/python/test/components/Requires.test.js`
around lines 20 - 27, The test assumes getQueryParams(channels) returns a
non-empty object and directly accesses Object.keys(allQueryParams)[0], which can
be undefined; update the block around allQueryParams in Requires.test.js to
defensively handle an empty result by checking that allQueryParams is truthy and
has at least one key before accessing the first channel (e.g., use const keys =
Object.keys(allQueryParams); if (allQueryParams && keys.length > 0) { const
firstChannelName = keys[0]; queryParams = new
Map(Object.entries(allQueryParams[firstChannelName] || {})); } ), ensuring you
reference getQueryParams, allQueryParams, and queryParams in the change.
packages/templates/clients/websocket/python/components/ClientClass.js (1)

10-71: Consider adding JSDoc for the exported function.

The ClientClass function is exported but lacks JSDoc documentation. As per coding guidelines, functions should include clear JSDoc comments with parameter types and return values.

📝 Suggested JSDoc addition
+/**
+ * Renders the Python WebSocket client class.
+ *
+ * `@param` {Object} props - Component props.
+ * `@param` {Object} props.asyncapi - The parsed AsyncAPI document.
+ * `@param` {Object} props.params - Template parameters including server, appendClientSuffix, and customClientName.
+ * `@returns` {JSX.Element} The rendered Python client class.
+ */
 export function ClientClass({ asyncapi, params }) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/templates/clients/websocket/python/components/ClientClass.js` around
lines 10 - 71, Add a JSDoc block above the exported function ClientClass that
documents the function, its parameters and return type: describe the first param
asyncapi as the AsyncAPI document/object (type AsyncAPI or any), the second
param params as an options object documenting expected fields (e.g. server,
appendClientSuffix, customClientName), and state the function returns a
JSX/React/Text element (or string template fragment) used to render the client
class; reference the function name ClientClass and the parameter names asyncapi
and params so the comment is placed directly above export function ClientClass({
asyncapi, params }) and follows project JSDoc style.
packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js (2)

6-30: Consider adding JSDoc for the exported function.

The default exported async function lacks JSDoc documentation describing its parameters and return value.

📝 Suggested JSDoc addition
+/**
+ * Generates the Java Quarkus WebSocket connector file.
+ *
+ * `@param` {Object} props - Generator props.
+ * `@param` {Object} props.asyncapi - The parsed AsyncAPI document.
+ * `@param` {Object} props.params - Template parameters including server, appendClientSuffix, and customClientName.
+ * `@returns` {Promise<JSX.Element>} The rendered connector file.
+ */
 export default async function ({ asyncapi, params }) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js`
around lines 6 - 30, Add a JSDoc block above the default exported async function
to document the input parameters and return value: describe the function as
async and list the shape/meaning of the single destructured parameter ({
asyncapi, params }) including expected params fields (server,
appendClientSuffix, customClientName), note that it uses helpers
getServer/getClientName/getQueryParams and returns a JSX File element containing
ConnectorDependencies and ClientConnector (i.e., a template fragment), and
document any thrown errors or side effects if applicable.

9-18: Consider extracting the repeated bridge logic into a shared helper.

The same "first channel to Map" conversion pattern is duplicated across multiple template files (Python ClientClass.js, Java connector.java.js, client.java.js, etc.). Consider adding a utility function in @asyncapi/generator-helpers to reduce duplication:

// Example helper in generator-helpers
function getFirstChannelQueryParamsAsMap(channels) {
  const allQueryParams = getQueryParams(channels);
  if (!allQueryParams) return null;
  const firstChannelName = Object.keys(allQueryParams)[0];
  return new Map(Object.entries(allQueryParams[firstChannelName]));
}

This would simplify all consuming code to a single function call while preserving backward compatibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js`
around lines 9 - 18, Extract the duplicated "first channel to Map" logic into a
shared helper called getFirstChannelQueryParamsAsMap in
`@asyncapi/generator-helpers`: implement a function that calls
getQueryParams(channels), returns null if falsy, otherwise picks the first
channel key and returns new Map(Object.entries(...)); then replace the inline
pattern in connector.java.js (the allQueryParams variable and subsequent Map
construction that sets queryParams) with a single call to
getFirstChannelQueryParamsAsMap(asyncapi.channels()) to keep behavior identical
and remove duplication.
packages/components/test/components/QueryParamsVariables.test.js (1)

22-26: Consider extracting the repeated first-channel conversion into a test helper.

The same block appears 3 times; centralizing it will reduce drift and keep future shape changes easier to apply.

♻️ Refactor sketch
+function getFirstChannelQueryParamsArray(channels) {
+  const queryParamsObject = getQueryParams(channels);
+  if (!queryParamsObject || Object.keys(queryParamsObject).length === 0) return [];
+  const firstChannelName = Object.keys(queryParamsObject)[0];
+  return Object.entries(queryParamsObject[firstChannelName] ?? {});
+}
...
-    const queryParamsObject = getQueryParams(channels);
-    let queryParamsArray = [];
-    if (queryParamsObject) {
-      const firstChannelName = Object.keys(queryParamsObject)[0];
-      queryParamsArray = Object.entries(queryParamsObject[firstChannelName]);
-    }
+    const queryParamsArray = getFirstChannelQueryParamsArray(channels);

Also applies to: 41-45, 60-64

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/components/test/components/QueryParamsVariables.test.js` around
lines 22 - 26, Extract the repeated conversion logic for test fixtures into a
small test helper (e.g., getQueryParamsArray) and replace the three identical
blocks that compute queryParamsArray from queryParamsObject using
firstChannelName/ Object.entries with a single call to that helper; the helper
should accept queryParamsObject, guard for falsy input, compute
Object.keys(queryParamsObject)[0] as firstChannelName, and return
Object.entries(queryParamsObject[firstChannelName]) so tests use a single source
of truth for this transformation.
packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js (1)

21-30: LGTM with optional defensive improvement.

The two-step extraction pattern correctly adapts to the new multi-channel getQueryParams API. For test code with a known fixture, this is acceptable.

Optional: Add a guard for the empty object edge case if you want the pattern to be more robust for future reuse:

🛡️ Optional defensive guard
     // Extract the parameters from the first channel into an array for the tests
     queryParamsArray = null;
-    if (allQueryParams) {
+    if (allQueryParams && Object.keys(allQueryParams).length > 0) {
       const firstChannelName = Object.keys(allQueryParams)[0];
       queryParamsArray = Object.entries(allQueryParams[firstChannelName]);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js`
around lines 21 - 30, The test currently assumes allQueryParams has at least one
channel before reading Object.keys(allQueryParams)[0]; add a defensive guard
around the extraction of firstChannelName and building queryParamsArray: check
that allQueryParams is an object and has at least one key (non-empty) before
calling Object.keys(...) and Object.entries(...), otherwise set queryParamsArray
to an empty array or a sensible default; update the code around getQueryParams,
allQueryParams, firstChannelName, and queryParamsArray to handle the
empty-object case safely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/components/src/components/QueryParamsVariables.js`:
- Around line 116-145: The JSDoc example for the QueryParamsVariables component
contains malformed comment markers (many instances of "* *") which breaks
rendering; edit the JSDoc example block for QueryParamsVariables in
QueryParamsVariables.js and replace all occurrences of "* *" at the start of
example lines with a single "*" so each example line is a proper JSDoc line
(preserve spacing/indentation and all example content, only fix the duplicated
asterisks).

In `@packages/helpers/src/bindings.js`:
- Around line 14-59: Update the JSDoc for getQueryParams to specify that the
channels parameter is an AsyncAPI Channels collection (not a plain Object) that
implements .isEmpty() and .all(), and document assumptions and error conditions:
note that the function expects channels to be non-null and to provide .isEmpty()
and .all() methods (or it will return null/skip processing), and describe return
values (object mapping channelName -> params or null when no ws query params
found). Reference getQueryParams(channels), the channels .isEmpty() and .all()
usage, and the expectation that channel bindings provide a ws binding with
.value()?.query.

In
`@packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/client.java.js`:
- Around line 17-20: The current block uses Object.keys(allQueryParams)[0]
without ensuring there is at least one key, which can throw; update the guard
around allQueryParams to also check that Object.keys(allQueryParams).length > 0
and that the resolved firstChannelName entry exists before converting to a Map.
Specifically, change the conditional that references
allQueryParams/firstChannelName and ensure queryParams = new
Map(Object.entries(allQueryParams[firstChannelName])) only runs when a non-empty
key list exists and allQueryParams[firstChannelName] is truthy.

In `@packages/templates/clients/websocket/python/template/client.py.js`:
- Around line 16-19: The template assumes allQueryParams has at least one key
and does Map(Object.entries(...)) unguarded; add a guard to ensure a
firstChannelName and a defined allQueryParams[firstChannelName] before
converting to a Map and otherwise set queryParams to an empty Map. Specifically,
update the block that references allQueryParams, firstChannelName and
queryParams so it checks Object.keys(allQueryParams).length > 0 (or that
firstChannelName is truthy and allQueryParams[firstChannelName] !== undefined)
before calling Object.entries, and fallback to new Map() when there are no
entries.

In
`@packages/templates/clients/websocket/python/test/components/InitSignature.test.js`:
- Around line 60-63: The code assumes allQueryParams has at least one key before
calling Object.entries and can throw when allQueryParams is an empty object;
change the guard to ensure there is at least one channel and that the first
channel's params exist before calling Object.entries (e.g., check
Object.keys(allQueryParams).length > 0 and that allQueryParams[firstChannelName]
is defined) so queryParamsArray is only assigned from Object.entries when a
valid object exists (referencing allQueryParams, firstChannelName, and
queryParamsArray in InitSignature.test.js).

---

Nitpick comments:
In `@packages/components/test/components/QueryParamsVariables.test.js`:
- Around line 22-26: Extract the repeated conversion logic for test fixtures
into a small test helper (e.g., getQueryParamsArray) and replace the three
identical blocks that compute queryParamsArray from queryParamsObject using
firstChannelName/ Object.entries with a single call to that helper; the helper
should accept queryParamsObject, guard for falsy input, compute
Object.keys(queryParamsObject)[0] as firstChannelName, and return
Object.entries(queryParamsObject[firstChannelName]) so tests use a single source
of truth for this transformation.

In
`@packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js`:
- Around line 6-30: Add a JSDoc block above the default exported async function
to document the input parameters and return value: describe the function as
async and list the shape/meaning of the single destructured parameter ({
asyncapi, params }) including expected params fields (server,
appendClientSuffix, customClientName), note that it uses helpers
getServer/getClientName/getQueryParams and returns a JSX File element containing
ConnectorDependencies and ClientConnector (i.e., a template fragment), and
document any thrown errors or side effects if applicable.
- Around line 9-18: Extract the duplicated "first channel to Map" logic into a
shared helper called getFirstChannelQueryParamsAsMap in
`@asyncapi/generator-helpers`: implement a function that calls
getQueryParams(channels), returns null if falsy, otherwise picks the first
channel key and returns new Map(Object.entries(...)); then replace the inline
pattern in connector.java.js (the allQueryParams variable and subsequent Map
construction that sets queryParams) with a single call to
getFirstChannelQueryParamsAsMap(asyncapi.channels()) to keep behavior identical
and remove duplication.

In
`@packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js`:
- Around line 21-30: The test currently assumes allQueryParams has at least one
channel before reading Object.keys(allQueryParams)[0]; add a defensive guard
around the extraction of firstChannelName and building queryParamsArray: check
that allQueryParams is an object and has at least one key (non-empty) before
calling Object.keys(...) and Object.entries(...), otherwise set queryParamsArray
to an empty array or a sensible default; update the code around getQueryParams,
allQueryParams, firstChannelName, and queryParamsArray to handle the
empty-object case safely.

In `@packages/templates/clients/websocket/python/components/ClientClass.js`:
- Around line 10-71: Add a JSDoc block above the exported function ClientClass
that documents the function, its parameters and return type: describe the first
param asyncapi as the AsyncAPI document/object (type AsyncAPI or any), the
second param params as an options object documenting expected fields (e.g.
server, appendClientSuffix, customClientName), and state the function returns a
JSX/React/Text element (or string template fragment) used to render the client
class; reference the function name ClientClass and the parameter names asyncapi
and params so the comment is placed directly above export function ClientClass({
asyncapi, params }) and follows project JSDoc style.

In
`@packages/templates/clients/websocket/python/test/components/QueryParamsArgumentsDocs.test.js`:
- Around line 23-26: The code assumes allQueryParams has at least one key and
does Object.keys(allQueryParams)[0] then Object.entries(...) which will throw if
allQueryParams is empty; update the block that sets firstChannelName and
queryParamsArray to first check that Object.keys(allQueryParams).length > 0 (or
that firstChannelName is truthy) before indexing and calling Object.entries, and
only set queryParamsArray when a channel exists (leave it empty or default
otherwise) so references to firstChannelName and queryParamsArray are safe;
target the variables allQueryParams, firstChannelName and queryParamsArray in
the test.

In
`@packages/templates/clients/websocket/python/test/components/Requires.test.js`:
- Around line 20-27: The test assumes getQueryParams(channels) returns a
non-empty object and directly accesses Object.keys(allQueryParams)[0], which can
be undefined; update the block around allQueryParams in Requires.test.js to
defensively handle an empty result by checking that allQueryParams is truthy and
has at least one key before accessing the first channel (e.g., use const keys =
Object.keys(allQueryParams); if (allQueryParams && keys.length > 0) { const
firstChannelName = keys[0]; queryParams = new
Map(Object.entries(allQueryParams[firstChannelName] || {})); } ), ensuring you
reference getQueryParams, allQueryParams, and queryParams in the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2148922a-f2a0-4cea-ace3-8a4caf5969d3

📥 Commits

Reviewing files that changed from the base of the PR and between b2f677e and 895f788.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • packages/components/src/components/QueryParamsVariables.js
  • packages/components/test/components/QueryParamsVariables.test.js
  • packages/helpers/src/bindings.js
  • packages/helpers/test/bindings.test.js
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/client.java.js
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientConnector.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientDependencies.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientFields.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConnectorDependencies.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/Constructor.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/DefaultConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/EchoWebSocket.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/URIParams.test.js
  • packages/templates/clients/websocket/python/components/ClientClass.js
  • packages/templates/clients/websocket/python/template/client.py.js
  • packages/templates/clients/websocket/python/test/components/Constructor.test.js
  • packages/templates/clients/websocket/python/test/components/InitSignature.test.js
  • packages/templates/clients/websocket/python/test/components/QueryParamsArgumentsDocs.test.js
  • packages/templates/clients/websocket/python/test/components/Requires.test.js

Comment on lines +16 to +19
if (allQueryParams) {
const firstChannelName = Object.keys(allQueryParams)[0];
queryParams = new Map(Object.entries(allQueryParams[firstChannelName]));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add an empty-result guard before Map conversion.

If allQueryParams is {}, this currently calls Object.entries(undefined) and throws during template generation.

🛠️ Proposed hardening
   let queryParams = null;
-  if (allQueryParams) {
-    const firstChannelName = Object.keys(allQueryParams)[0];
-    queryParams = new Map(Object.entries(allQueryParams[firstChannelName]));
+  if (allQueryParams && Object.keys(allQueryParams).length > 0) {
+    const firstChannelName = Object.keys(allQueryParams)[0];
+    const firstChannelParams = allQueryParams[firstChannelName];
+    if (firstChannelParams) {
+      queryParams = new Map(Object.entries(firstChannelParams));
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/templates/clients/websocket/python/template/client.py.js` around
lines 16 - 19, The template assumes allQueryParams has at least one key and does
Map(Object.entries(...)) unguarded; add a guard to ensure a firstChannelName and
a defined allQueryParams[firstChannelName] before converting to a Map and
otherwise set queryParams to an empty Map. Specifically, update the block that
references allQueryParams, firstChannelName and queryParams so it checks
Object.keys(allQueryParams).length > 0 (or that firstChannelName is truthy and
allQueryParams[firstChannelName] !== undefined) before calling Object.entries,
and fallback to new Map() when there are no entries.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@SushanthMusham look at this suggestion and apply it

Comment on lines +60 to +63
if (allQueryParams) {
const firstChannelName = Object.keys(allQueryParams)[0];
queryParamsArray = Object.entries(allQueryParams[firstChannelName]);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard against empty allQueryParams before calling Object.entries.

Line 60 only checks truthiness. If allQueryParams is {}, Line 62 evaluates Object.entries(undefined) and throws.

Suggested fix
-    let queryParamsArray = null;
-    if (allQueryParams) {
-      const firstChannelName = Object.keys(allQueryParams)[0];
-      queryParamsArray = Object.entries(allQueryParams[firstChannelName]);
-    }
+    let queryParamsArray = null;
+    if (allQueryParams) {
+      const channelNames = Object.keys(allQueryParams);
+      if (channelNames.length > 0) {
+        const firstChannelName = channelNames[0];
+        queryParamsArray = Object.entries(allQueryParams[firstChannelName] ?? {});
+      }
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/clients/websocket/python/test/components/InitSignature.test.js`
around lines 60 - 63, The code assumes allQueryParams has at least one key
before calling Object.entries and can throw when allQueryParams is an empty
object; change the guard to ensure there is at least one channel and that the
first channel's params exist before calling Object.entries (e.g., check
Object.keys(allQueryParams).length > 0 and that allQueryParams[firstChannelName]
is defined) so queryParamsArray is only assigned from Object.entries when a
valid object exists (referencing allQueryParams, firstChannelName, and
queryParamsArray in InitSignature.test.js).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@SushanthMusham look at this suggestion and apply it

Copy link
Copy Markdown
Member

@Adi-204 Adi-204 left a comment

Choose a reason for hiding this comment

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

@SushanthMusham, the only concern I have with the current refactoring is the repeated pattern below:

// Fetch all channel parameters with our new helper
const allQueryParams = getQueryParams(channels);

// Convert the first channel's parameters back into a Map for the tests
queryParams = null;
if (allQueryParams) {
  const firstChannelName = Object.keys(allQueryParams)[0];
  queryParams = new Map(Object.entries(allQueryParams[firstChannelName]));
}

This logic is now duplicated across multiple components due to the helper change, which makes the code a bit redundant and harder to maintain.

I think it would be better to introduce an additional helper that directly returns the parameters for the first channel (in the required format). That way, we can avoid repetition and keep the components cleaner.
Also address the coderabbit comments it is much better now and give nice suggestions.

@Adi-204 Adi-204 self-assigned this Mar 24, 2026
@derberg derberg moved this to In Progress in Maintainers work Mar 25, 2026
@SushanthMusham
Copy link
Copy Markdown
Author

I’ve completed the refactor as suggested.
Changes:

  1. Added a new helper getFirstChannelQueryParams in generator-helpers to centralize the compatibility logic.
  2. Updated all Java Quarkus templates and test files to use this helper.
  3. Fixed edge cases where an empty allQueryParams object caused issues (flagged by CodeRabbit).
  4. Verified all 46 tests locally — they’re passing.
    Ready for another look! @Adi-204

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/helpers/src/bindings.js`:
- Around line 19-55: The code uses plain object literals for document-controlled
keys which allows prototype pollution; replace the mutable plain objects with
null-prototype objects by creating result and the per-channel channelParams
using Object.create(null) instead of {} (references: result, channelParams,
channelName, properties, channels.all(), and the loop that assigns query
property names) so that assigning document-derived keys cannot mutate
Object.prototype.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 898b5c3d-e907-4d4d-82b2-42d1c74191b4

📥 Commits

Reviewing files that changed from the base of the PR and between 895f788 and 56957ea.

📒 Files selected for processing (17)
  • packages/components/src/components/QueryParamsVariables.js
  • packages/helpers/src/bindings.js
  • packages/helpers/src/index.js
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/client.java.js
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientConnector.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientDependencies.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientFields.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConnectorDependencies.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/Constructor.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/DefaultConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/EchoWebSocket.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/URIParams.test.js
  • packages/templates/clients/websocket/python/template/client.py.js
  • packages/templates/clients/websocket/python/test/components/InitSignature.test.js
✅ Files skipped from review due to trivial changes (4)
  • packages/templates/clients/websocket/java/quarkus/test/components/Constructor.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/URIParams.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConnectorDependencies.test.js
  • packages/components/src/components/QueryParamsVariables.js
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/client.java.js
  • packages/templates/clients/websocket/java/quarkus/test/components/EchoWebSocket.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/DefaultConstructorSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/InitConnector.test.js
  • packages/templates/clients/websocket/python/test/components/InitSignature.test.js
  • packages/templates/clients/websocket/java/quarkus/test/components/ClientDependencies.test.js
  • packages/templates/clients/websocket/python/template/client.py.js
  • packages/templates/clients/websocket/java/quarkus/template/src/main/java/com/asyncapi/connector.java.js

@sonarqubecloud
Copy link
Copy Markdown

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

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

getQueryParams helper function assumes only one channel has ws bindings.

4 participants