-
Notifications
You must be signed in to change notification settings - Fork 163
Description
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
- @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.
- 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.
- @customResolver — only works for reading data (queries), not for mutations.
- 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.