fix: Strip undefined values in ParseServerRESTController to match HTTP mode#10269
fix: Strip undefined values in ParseServerRESTController to match HTTP mode#10269yog27ray wants to merge 4 commits intoparse-community:alphafrom
Conversation
…TTP mode behavior When `directAccess: true` is enabled, `ParseServerRESTController` passes request data directly to Parse Server internals without JSON serialization. In HTTP mode, `JSON.stringify()` naturally strips `undefined` values from payloads. With directAccess, `undefined` values are preserved, passed to MongoDB's `$set` operator, and converted to `null` by the BSON driver. This causes fields that should be absent to be stored as `null`, breaking `doesNotExist` queries and changing data semantics. The fix adds a `stripUndefined()` helper that removes keys with `undefined` values from the request body, making directAccess behave identically to HTTP mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
I will reformat the title to use the proper commit message syntax. |
|
🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review. Tip
Note Please respond to review comments from AI agents just like you would to comments from a human reviewer. Let the reviewer resolve their own comments, unless they have reviewed and accepted your commit, or agreed with your explanation for why the feedback was incorrect. Caution Pull requests must be written using an AI agent with human supervision. Pull requests written entirely by a human will likely be rejected, because of lower code quality, higher review effort and the higher risk of introducing bugs. Please note that AI review comments on this pull request alone do not satisfy this requirement. |
📝 WalkthroughWalkthroughAdded a recursive Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment Tip You can customize the high-level summary generated by CodeRabbit.Configure the |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
spec/ParseServerRESTController.spec.js (1)
679-695: Add one nested undefined regression case to close the parity gap.This test is good for top-level fields. Please add a case like
{ nested: { absentField: undefined } }to ensure nested updates also match HTTP behavior.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/ParseServerRESTController.spec.js` around lines 679 - 695, Add a nested-undefined regression case to the existing test "should not convert undefined values to null on update with directAccess" in ParseServerRESTController.spec.js: after the current PUT that includes absentField: undefined, also perform a PUT (or include in the same update) with a nested object like { nested: { absentField: undefined } } and then GET the object and assert that getRes.nested is defined, getRes.nested.absentField is undefined, and that 'absentField' is not an own property of getRes.nested; update expectations in the test to cover both top-level and nested undefined behavior so nested updates mirror HTTP behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/ParseServerRESTController.js`:
- Around line 32-43: The stripUndefined function currently only removes
undefined at the top level; update stripUndefined to recursively traverse
objects and arrays so its behavior matches JSON.stringify: for objects (function
stripUndefined) iterate keys and if a value is undefined omit the key, otherwise
set key to stripUndefined(value); for arrays return a new array mapping each
element to stripUndefined(element) but convert undefined elements to null (i.e.,
if element === undefined return null); preserve primitives and null as-is and
avoid mutating the original input. Ensure the function handles nested
objects/arrays and returns a fresh structure.
---
Nitpick comments:
In `@spec/ParseServerRESTController.spec.js`:
- Around line 679-695: Add a nested-undefined regression case to the existing
test "should not convert undefined values to null on update with directAccess"
in ParseServerRESTController.spec.js: after the current PUT that includes
absentField: undefined, also perform a PUT (or include in the same update) with
a nested object like { nested: { absentField: undefined } } and then GET the
object and assert that getRes.nested is defined, getRes.nested.absentField is
undefined, and that 'absentField' is not an own property of getRes.nested;
update expectations in the test to cover both top-level and nested undefined
behavior so nested updates mirror HTTP behavior.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 40b804d3-ed21-4a29-b323-4dff6e0f2cc2
📒 Files selected for processing (2)
spec/ParseServerRESTController.spec.jssrc/ParseServerRESTController.js
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## alpha #10269 +/- ##
==========================================
- Coverage 92.53% 92.53% -0.01%
==========================================
Files 192 192
Lines 16481 16490 +9
Branches 226 226
==========================================
+ Hits 15251 15259 +8
- Misses 1210 1211 +1
Partials 20 20 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
JSON.parse(JSON.stringify(data)) perfectly replicates HTTP mode's serialization roundtrip — stripping undefined at all nesting levels, not just top-level keys. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ingify()) JSON.parse(JSON.stringify()) is expensive. Replace with a recursive stripUndefined that walks the object tree efficiently — strips undefined keys from objects at all nesting levels and converts undefined array elements to null, matching JSON.stringify behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mtrezza
left a comment
There was a problem hiding this comment.
Can you add a test to compare that with behavior when directAccess is false? It should yield the same result.
Issue
When
directAccess: trueis enabled,undefinedvalues in update (PUT) payloads are converted tonulland stored in the database. This breaksdoesNotExist/existsqueries and changes data semantics.Root cause:
ParseServerRESTControllerpasses request data directly to Parse Server internals without JSON serialization. In HTTP mode,JSON.stringify()naturally stripsundefinedvalues from payloads. With directAccess,undefinedvalues are preserved all the way totransformUpdate()inMongoTransform.js, which passes them into MongoDB's$setoperator. The MongoDB BSON driver then convertsundefinedtonull.The CREATE path is unaffected because
parseObjectToMongoObjectForCreate()already has anif (value !== undefined)check (MongoTransform.js line 476). The UPDATE path intransformUpdate()lacks this check (line 529).Approach
Added a
stripUndefined()helper inParseServerRESTController.jsthat removes keys withundefinedvalues from the request body before passing it to the router. This makes directAccess behave identically to HTTP mode, whereJSON.stringify()stripsundefinedvalues.Why fix here instead of
transformUpdate(): Without directAccess,JSON.stringifystripsundefinedbefore data ever reachestransformUpdate()— sotransformUpdatenever seesundefinedvalues in HTTP mode and works fine. The bug only exists becausedirectAccessbypasses JSON serialization. Fixing at theParseServerRESTControllerlevel — the component that's added whendirectAccessis enabled — addresses the root cause at the right layer.Reproduction:
Tasks
Summary by CodeRabbit
Bug Fixes
Tests