Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename field with wildcard support #1215

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

anasshakil
Copy link

@anasshakil anasshakil commented Feb 21, 2023

Description

This allows to rename fields using rename context item.

Example

app.post(
  "/user",
  // Promise
  body("search").rename(async (value) => {
    // do some asynchronous task
    if (value.includes("@")) {
      return "email";
    } else if (value.includes("#")) {
      return "tag";
    }
    return null;
  }),
  // Basic
  check("search")
    .rename((value) => {
      if (value.includes("+")) {
        return "phone";
      }
      return undefined;
    })
    .withMessage("An error occurred"),
  // wildcard field with short-circuiting `string`
  body("user.*.addresses.home").rename("accounts.*.users.*.addresses.billing.street"),
  (req, res) => {
    // Handle the request
    const data = matchedData(req);
    res.json(data);
  }
);

Request Body

{
    "search": "[email protected]",
    "user": [
        {
            "addresses": {
                "home":  "billing address street"
            }
        }
    ]
}

Output

{
  "email": "[email protected]",
   "accounts": [
        {
            "users": [
                {
                    "addresses": {
                        "billing": {
                            "street": "billing address street"
                        }
                    }
                }
            ]
        }
    ]
}

closes #785

To-do list

  • Wildcard support

  • I have added tests for what I changed.

  • This pull request is ready to merge.

@anasshakil anasshakil closed this Feb 21, 2023
@anasshakil anasshakil reopened this Feb 21, 2023
@coveralls
Copy link

coveralls commented Feb 22, 2023

Coverage Status

Coverage: 99.263% (-0.7%) from 100.0% when pulling 5d4dafc on anasshakil:master into eba0cfe on express-validator:master.

Comment on lines 23 to 24
if (typeof actualResult === 'string') {
context.renameFieldInstance(actualResult, meta);
Copy link
Member

Choose a reason for hiding this comment

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

May I ask why you thought of making use of the custom validators?

Changing the meaning of the return of a custom validator will be quite disruptive for everybody, and is certainly a breaking change.

Perhaps a new function in the chain would be a better idea?

Copy link
Author

Choose a reason for hiding this comment

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

We ran into a problem where we needed to rename the search field on the bases of the input. I thought of the custom validator as a solution because it solves both of the requirements. To avoid the breaking change, we can accept the return type of an object containing a field, for example { express_rename: 'foo' }.

src/context.ts Outdated
Comment on lines 116 to 121
if (this.fields.length !== 1) {
throw new Error('Attempt to rename multiple fields.');
}
if (/\.|\*/g.test(originalPath)) {
throw new Error('Attempt to rename a wildcard field');
}
Copy link
Member

Choose a reason for hiding this comment

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

Nice thinking here. I suppose that the callback should be able to handle the name to give to a field though -- as it has access to the full original path.

Copy link
Author

Choose a reason for hiding this comment

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

I had some success on renaming wildcard paths but need to do more work for wildcard support

- Wildcard support
- Test cases added for wildcard and non-wildcard field rename
@anasshakil anasshakil changed the title Rename field using custom validator Rename field with wildcard support Feb 27, 2023
Copy link
Member

@gustavohenke gustavohenke left a comment

Choose a reason for hiding this comment

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

General question: should the old property be removed when renaming the item?

renameFieldInstance will work for setting the new property with the same value as the old field instance, but it won't touch the old one.

// Avoids e.g. undefined values being set on the request if it didn't have the key initially.
const reqValue = path !== '' ? _.get(req[location], path) : req[location];
if (!options.dryRun && reqValue !== instance.value) {
path !== '' ? _.set(req[location], path, newValue) : _.set(req, location, newValue);
}

* @param evaluator the custom evaluator based on the `CustomValidator`
* @returns the current validation chain
*/
rename(evaluator: CustomValidator): Return;
Copy link
Member

Choose a reason for hiding this comment

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

Nice, this is better!
A few comments here though:

  1. This shouldn't stay in the Validators interface. ContextHandler sounds more like it.
  2. Let's add a type specific for the rename callback, so that CustomValidator can evolve independently from the rename functionality.
  3. WDYT of accepting a string value too, which works as a shortcut? For example, rename('banana') automatically renames that field to banana.

import { ContextItem } from './context-item';

export class RenameFieldContextItem implements ContextItem {
message: any;
Copy link
Member

Choose a reason for hiding this comment

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

When you move rename out of Validators, I think that this won't be necessary anymore

export class RenameFieldContextItem implements ContextItem {
message: any;

constructor(private readonly evaluator: CustomValidator, private readonly negated: boolean) {}
Copy link
Member

Choose a reason for hiding this comment

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

Ditto for negated

- Shifted  rename functionality to context handler
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.

[Feature Request] Ability to rename parameters
3 participants