Skip to content

Feature: @customMutation directive for mutation callbacks #7077

@AntonAndreevichMoroz

Description

@AntonAndreevichMoroz

Is your feature request related to a problem? Please describe.

Currently, there's no simple, declarative way to intercept and modify data before writing it to the database when performing mutations (create, update). I always have to use workarounds like GraphQL middleware or custom resolvers, which complicate the code and require additional logic. For example, hashing passwords before saving or validating/modifying input data requires writing separate middleware functions that aren't directly bound to a field in the GraphQL schema.

Describe the solution you'd like

I want a new @customMutation directive that will work similarly to @customResolver, but for mutations. This directive should allow you to specify a custom function that will be called before writing data to the database for CREATE and UPDATE operations. Unlike the @populatedBy directive, the new directive shouldn't disable user input—it should receive a value from the user, allow it to be modified, and return it for further writing.

Example of use:

type User @node {
  username: String!
  password: String! @customMutation(callback: "hashPassword")
}

type User @node {
  email: String! @customMutation(callback: "normalizeEmail")
}

The callback function should receive a context with input data and return a modified value:

const hashPassword = ({ value, context }) => {
  return bcrypt.hash(value, 10);
};

Describe alternatives you've considered

  1. @populatedBy — allows for automatic value generation, but completely disables the ability for the user to supply a value, making it unsuitable for scenarios where user input needs to be modified.
  2. GraphQL middleware — allows for intercepting mutations, but requires complex logic to determine which fields need to be modified, and is not directly tied to the fields in the schema.
  3. @customResolver — only works for reading data (queries), not for mutations.
  4. Custom resolvers — require a complete replacement of the standard Neo4j GraphQL mutations, resulting in code duplication and the loss of the benefits of auto-generated resolvers.

Additional context

Such a directive would be particularly useful for:

  • Hashing passwords before storing
  • Normalizing data (e.g., converting email addresses to lowercase)
  • Validating and transforming input data
  • Automatically populating derived fields based on user input
  • Encrypting sensitive data

In the current project, we implemented similar functionality through a custom @hashString directive with GraphQL middleware, but this solution requires a significant amount of code and is not part of the library's standard functionality. Adding @customMutation would make the library more flexible and reduce the need for custom solutions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions