type-graphql icon indicating copy to clipboard operation
type-graphql copied to clipboard

Transforming input fields

Open MatthiasKunnen opened this issue 5 years ago • 9 comments

I find myself short of a simple way to perform reusable input field transformation.

Example:

@InputType()
export class TestInput {
    @Field()
    name: string;
}

I would like to transform the name field before it reaches the resolver to do some basic transformation such as trimming and potentially throwing an error. Ideally I could use something such as @Transform(transformFn).

I've tried @UseMiddleware but, alas, it does not work on input types.

MatthiasKunnen avatar May 21 '19 19:05 MatthiasKunnen

You can try to use custom parameters decorator for that: https://typegraphql.ml/docs/custom-decorators.html#parameter-decorators

But it might be tricky as you will receive whole args object, just like in middlewares. Without #123 it might be tricky to implement something like that.

MichalLytek avatar May 21 '19 19:05 MichalLytek

I've opened graphql/graphql-js#1894 to check whether transformation could be added there as it would make implementation into type-graphql significantly easier.

MatthiasKunnen avatar May 22 '19 12:05 MatthiasKunnen

@MichalLytek, since you pointed out in the graphql-js issue that directives can accomplish this use case, is there still merit for this issue or do I close it too?

MatthiasKunnen avatar Oct 30 '19 16:10 MatthiasKunnen

Closed it by accident. If you still think this feature is useful in type-graphql, I'll reopen it.

MatthiasKunnen avatar Oct 30 '19 16:10 MatthiasKunnen

As we have to create instance of args and input types, as well as map the schema/prop names, so with access to metadata it should be possible to create own transform function e.g. for easier and custom validation rules, without having to trouble with custom scalars and directives visitors.

MichalLytek avatar Oct 30 '19 17:10 MichalLytek

I encountered the same "issue" so below is my "solution"

both issue and solution are quoted because it's not really an issue per se (wherein an issue is more akin to a bug) but more like a (somewhat) specific use case

The idea is to create a middleware in the resolver (since it'll process the data object), do whatever you want to the data object, mutate it and then return the next function.

The code:

@UseMiddleware(async (data, next) => {
    let input = data.args.input as UserInput;
    data.args.input = {
      ...input,
      email: input.email.toLowerCase()
    } as UserInput;
    return await next();
  })

karimdaghari avatar Jan 03 '21 12:01 karimdaghari

Any plans to implement input transform?

RyannGalea avatar Aug 18 '21 06:08 RyannGalea

The vNext aka v2.0 gonna contain that feature. It requires some architectural changes that can be achieved only within a major version.

MichalLytek avatar Aug 18 '21 07:08 MichalLytek

It would be nice if the transform function has access to to the whole input object to perform conditional validation and to allow the use of the delete operator on properties.

MatthiasKunnen avatar May 11 '22 15:05 MatthiasKunnen