Skip to content

feat: enhance parameter parsing with POST body and dot notation support#582

Merged
w3nl merged 2 commits into
mainfrom
feature/parse-post
Jul 1, 2026
Merged

feat: enhance parameter parsing with POST body and dot notation support#582
w3nl merged 2 commits into
mainfrom
feature/parse-post

Conversation

@w3nl

@w3nl w3nl commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Introduces support for parsing parameters from the request body, prioritizing them over query parameters. Adds the ability to access nested object properties in both query and body parameters using dot notation (e.g., 'user.address.city').

This change is accompanied by an upgrade of the Node.js runtime to version 24 across development, testing, and CI/CD environments, along with various dependency updates. The test runner script has been updated to conditionally enable lcov reporting based on Node.js version.

Summary by CodeRabbit

  • New Features

    • Improved request handling so POST body fields and nested parameters are parsed more reliably, including date-time values.
    • Added support for event-related request data in the test coverage and example fixtures.
  • Bug Fixes

    • POST values now take precedence where expected, reducing mismatches between query and body inputs.
    • Updated test and CI environments to use newer Node.js versions, including Node.js 24.

Introduces support for parsing parameters from the request body, prioritizing them over query parameters. Adds the ability to access nested object properties in both query and body parameters using dot notation (e.g., 'user.address.city').

This change is accompanied by an upgrade of the Node.js runtime to version 24 across development, testing, and CI/CD environments, along with various dependency updates. The test runner script has been updated to conditionally enable lcov reporting based on Node.js version.
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@w3nl, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 79feb5aa-bc2b-4fba-9749-2d209991b798

📥 Commits

Reviewing files that changed from the base of the PR and between 869a615 and 990a00f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json
📝 Walkthrough

Walkthrough

This PR upgrades Node.js versions across CI workflows, Travis config, and package.json engines to Node 24+, adds a custom test runner script with version-conditional coverage reporting, and introduces POST body parameter parsing with nested dot-notation support integrated into the Express request pipeline, validated by new fixture and test cases.

Changes

Node.js Version Upgrade

Layer / File(s) Summary
CI workflow and Travis Node version bumps
.github/workflows/cpd.yml, .github/workflows/lint.yml, .github/workflows/sonarcloud.yml, .github/workflows/vulnerabilities.yml, .github/workflows/test.yml, .travis.yml
Workflow steps and Travis matrix updated to use Node.js 24, with test.yml matrix extended to 24.x/25.x/26.x and Travis to "24"/"25".
Custom test runner and package.json updates
package.json, scripts/run-tests.js
The test script now runs node scripts/run-tests.js, which spawns Node's test runner and conditionally enables lcov coverage reporting for Node >= 24; engines.node tightened to >= 24.

POST body parameter parsing

Layer / File(s) Summary
Nested value helpers and type conversion
src/params.js
Adds getNestedValue, setNestedValue, and parseValue for dot-notation access/assignment and schema-based type conversion (booleans, dates).
parsePost export and parseParams update
src/params.js
Adds exported parsePost for converting/writing nested POST values; parseParams now accepts post and prefers nested post values over query values.
Express callback wiring
src/express-callback.js
Imports and calls parsePost on request.body, passes result into parseParams, and uses parsed post data in feedback and debug logging.
Events fixture and validation tests
src/__fixtures__/spec.json, src/params.test.js, src/server.test.js
Adds a /events POST endpoint fixture, expands params.test.js with POST/nested/date test cases, and adds a createEvent mock controller plus integration test in server.test.js.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ExpressCallback as makeExpressCallback
    participant Params as params.js
    participant Controller

    Client->>ExpressCallback: POST /v1/events with body { event: { startsAt, title } }
    ExpressCallback->>Params: parsePost({ post: request.body, spec })
    Params-->>ExpressCallback: parsedPost (nested values type-converted)
    ExpressCallback->>Params: parseParams({ query, post: parsedPost, spec, mock })
    Params->>Params: getNestedValue(post, name) preferred over query
    Params->>Params: parseValue(schema, value)
    Params-->>ExpressCallback: converted params
    ExpressCallback->>Controller: createEvent(params)
    Controller-->>ExpressCallback: response { startsAt as Date, title }
    ExpressCallback-->>Client: 200 response
Loading

Possibly related PRs

  • trojs/openapi-server#528: Both PRs modify src/express-callback.js's makeExpressCallback flow and feedback/logging payload, directly touching overlapping code.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: parameter parsing now supports POST bodies and dot notation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/parse-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.

@w3nl

w3nl commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/params.js (1)

123-147: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don't drop valid 0/false values after body parsing.

parsePost() now converts body fields before they reach parseParams(), so valid inputs like count: 0 or enabled: false hit the !paramName checks here and get replaced by defaults/examples or removed entirely.

Suggested fix
 export const parseParams = ({ query, post, spec, mock = false }) =>
   spec
     .map((parameter) => {
       const { name, schema } = parameter
       const {
         default: defaultValue,
         example: exampleValue
       } = schema
       // Check post first, then query (post data takes precedence)
       // Support nested objects with dot notation
       const paramName = getNestedValue(post, name) ?? getNestedValue(query, name)
+      const hasValue = paramName !== undefined && paramName !== null
 
-      if (!paramName && defaultValue !== undefined) {
+      if (!hasValue && defaultValue !== undefined) {
         return { name, value: defaultValue }
       }
 
-      if (!paramName && mock && exampleValue !== undefined) {
+      if (!hasValue && mock && exampleValue !== undefined) {
         return { name, value: exampleValue }
       }
 
-      if (!paramName) {
+      if (!hasValue) {
         return undefined
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/params.js` around lines 123 - 147, parseParams is treating valid falsy
body values as missing because it uses !paramName after getNestedValue(post,
name) / getNestedValue(query, name), which drops 0 and false. Update the checks
in parseParams to only fall back to defaultValue/exampleValue or return
undefined when the resolved value is actually null or undefined, while
preserving legitimate falsy values. Keep the precedence logic (post over query)
and the parseValue step unchanged.
🧹 Nitpick comments (1)
scripts/run-tests.js (1)

11-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

else branch is effectively dead code given engines.node: ">= 24".

Since package.json now requires Node >= 24, nodeMajor will always satisfy the >= 24 check in any environment that honors the engines constraint, making the fallback destination-only branch unreachable in practice. Harmless as defensive coding, but consider removing it (or documenting why it's kept, e.g. to support environments that ignore engines) for clarity.

♻️ Optional simplification if the fallback is confirmed unnecessary
-// The built-in lcov reporter is used on supported Node versions.
-const reporterArgs = nodeMajor >= 24
-  ? [
-      '--test-reporter=lcov',
-      '--test-reporter-destination=stdout',
-      '--test-reporter-destination=./coverage/lcov.info'
-    ]
-  : ['--test-reporter-destination=stdout']
+const reporterArgs = [
+  '--test-reporter=lcov',
+  '--test-reporter-destination=stdout',
+  '--test-reporter-destination=./coverage/lcov.info'
+]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/run-tests.js` around lines 11 - 17, The fallback reporterArgs branch
in run-tests.js is unreachable because the project already requires Node >= 24,
so simplify the nodeMajor check in reporterArgs to remove the dead `:
['--test-reporter-destination=stdout']` path, or add a short comment if you
intend to keep it for environments that ignore engines.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/params.js`:
- Around line 123-133: The precedence logic in parseParams is currently applied
to the merged query object, which lets body values override path params as well.
Update parseParams in src/params.js to respect parameter.in so the post-vs-query
precedence only applies to query-like inputs, and adjust src/express-callback.js
so context.request?.params is passed separately instead of being merged into
query. Use parseParams and the request parameter mapping in express-callback as
the main points to change.

---

Outside diff comments:
In `@src/params.js`:
- Around line 123-147: parseParams is treating valid falsy body values as
missing because it uses !paramName after getNestedValue(post, name) /
getNestedValue(query, name), which drops 0 and false. Update the checks in
parseParams to only fall back to defaultValue/exampleValue or return undefined
when the resolved value is actually null or undefined, while preserving
legitimate falsy values. Keep the precedence logic (post over query) and the
parseValue step unchanged.

---

Nitpick comments:
In `@scripts/run-tests.js`:
- Around line 11-17: The fallback reporterArgs branch in run-tests.js is
unreachable because the project already requires Node >= 24, so simplify the
nodeMajor check in reporterArgs to remove the dead `:
['--test-reporter-destination=stdout']` path, or add a short comment if you
intend to keep it for environments that ignore engines.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b30b0c83-9edc-442d-bb06-6342dea80be4

📥 Commits

Reviewing files that changed from the base of the PR and between ae30cf4 and 869a615.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • .github/workflows/cpd.yml
  • .github/workflows/lint.yml
  • .github/workflows/sonarcloud.yml
  • .github/workflows/test.yml
  • .github/workflows/vulnerabilities.yml
  • .travis.yml
  • package.json
  • scripts/run-tests.js
  • src/__fixtures__/spec.json
  • src/express-callback.js
  • src/params.js
  • src/params.test.js
  • src/server.test.js

Comment thread src/params.js
Comment on lines +123 to +133
export const parseParams = ({ query, post, spec, mock = false }) =>
spec
.map((parameter) => {
const { name, schema } = parameter
const {
type,
default: defaultValue,
example: exampleValue
} = schema
const Type = types[type]
const paramName = query?.[name]
// Check post first, then query (post data takes precedence)
// Support nested objects with dot notation
const paramName = getNestedValue(post, name) ?? getNestedValue(query, name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Scope body precedence to query params only.

This selection ignores parameter.in. Because src/express-callback.js passes a merged {...request.params, ...request.query} object as query, a body field can now override a path parameter too, which is broader than the stated “body beats query” contract.

Suggested direction
-export const parseParams = ({ query, post, spec, mock = false }) =>
+export const parseParams = ({ query, path, post, spec, mock = false }) =>
   spec
     .map((parameter) => {
       const { name, schema } = parameter
+      const paramName =
+        parameter.in === 'path'
+          ? getNestedValue(path, name)
+          : getNestedValue(post, name) ?? getNestedValue(query, name)

And in src/express-callback.js, pass context.request?.params separately instead of folding it into query.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/params.js` around lines 123 - 133, The precedence logic in parseParams is
currently applied to the merged query object, which lets body values override
path params as well. Update parseParams in src/params.js to respect parameter.in
so the post-vs-query precedence only applies to query-like inputs, and adjust
src/express-callback.js so context.request?.params is passed separately instead
of being merged into query. Use parseParams and the request parameter mapping in
express-callback as the main points to change.

@w3nl w3nl merged commit 0060485 into main Jul 1, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants