fix(case-helpers): preserve custom_data keys at any nesting depth - #226
Open
TabishRiazBajwa wants to merge 1 commit into
Open
Conversation
convertToSnakeCase only guarded customData at the top level of the request body. Simulation payloads nest customData inside payload.data, so its keys were silently snake_cased before being sent to the API, breaking webhook handlers that expected the original camelCase keys. Make the customData carve-out depth-insensitive by checking for the key recursively during decamelization, not just at the top level. Fixes PaddleHQ#220
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
convertToSnakeCaseinsrc/internal/api/case-helpers.tshas a carve-out that preservescustomDatacontents when it appears as a top-level key on the request body. This works correctly forpaddle.subscriptions.create(),paddle.transactions.create(), etc.However, when creating a simulation via
paddle.simulations.create(),customDatais nested insidepayload.data— not at the top level. The existing guard never fires, so all camelCase keys insidecustomDataget silently converted to snake_case before being sent to the Paddle API.Result: simulation webhooks deliver
{ tenant_id: "abc" }instead of{ tenantId: "abc" }, breaking any webhook handler that reads theoriginal keys — and producing a silent data corruption that's hard to debug.Fix
Move the
customDatapreservation logic intodecamelizeKeysso it applies at any depth of the object tree, not just the top level. When the recursive walk encounters an object key namedcustomData, it copies the value as-is (snake-cased key, original value) instead of recursing into it.Testing
convertToSnakeCasewithcustomDatanested inside a simulationpayload.dataobject.customDatatests still pass.Fixes #220