incetarik / nestjs-graphql-zod

A library providing dynamic GraphQL object classes from their zod validation objects.
Mozilla Public License 2.0
83 stars 10 forks source link

Zod Validation not work when using nestJS @Query decorator #14

Closed railsstudent closed 1 year ago

railsstudent commented 1 year ago

If I use @Query decorator to return a type created by modelFromZod, zod validations are not executed. I use refine() to ensure lat and lng return valid latitude and longitude.

export const GeoZod = zod
  .object({
    lat: zod.string().refine(
      (value) => {
        const latitude = Number.parseFloat(value);
        console.log('latitude', latitude);
        return latitude >= -90 && latitude <= 90;
      },
      {
        message: 'Invalid latitude',
      },
    ),
    lng: zod.string().refine(
      (value) => {
        const longtitude = Number.parseFloat(value);
        console.log('longtitude', longtitude);
        return longtitude >= -180 && longtitude <= 180;
      },
      {
        message: 'Invalid longitude',
      },
    ),
  })
  .required();

export const AddressZod = zod
  .object({
    street: zod.string(),
    suite: zod.string(),
    city: zod.string(),
    zipcode: zod.string(),
    geo: GeoZod,
  })
  .required();

export const UserZod = zod
  .object({
    id: zod.number().int(),
    name: zod.string(),
    username: zod.string(),
    email: zod.string().email(),
    address: AddressZod,
  })
  .required();

Since my POC is a Apollo federated graph, I need to create a custom model and place Directive decorator above the class.

const ZodUserModel = modelFromZod(UserZod);

@ObjectType()
@Directive('@key(fields: "id")')
export class UserModel extends ZodUserModel {
  @Field(() => String, { complexity: 3 })
  name!: string;

  @Field(() => String, { complexity: 2 })
  email!: string;
}
  @Query(() => UserModel)
  // @QueryWithZod(UserZod)
  async user(@Args('id', { type: () => Int }) id: number) {
    return this.usersService.getUser(id);
  }

When I execute the query, console log statements not printed in terminal. If I use QueryWithZod and test on the subgraph, console log statement printed

query userById($id: Int!) {
  user (id: $id) {
    id
    email
    address {
      geo {
        lat
        lng
      }
    }
}

This is a good library and but I think it tailors to standalone GraphQL and can extend to suport Apollo federated graph

incetarik commented 1 year ago

Hi @railsstudent.

The @QueryWithZod(UserZod) would run the validations before the function returns, and @Query simply checks the type of the returned object, not the fields. I may provide another decorator that will simply run the validations without touching the @Query decorator. If I can find a way or have a suggestion, then I'll tell you.

railsstudent commented 1 year ago

Awesome. I really like this library because it combines the goodies of class-validator, graphql-scalar and graphql-validation-directive without the hassle of adding typdef and creating GraphQLDirectives.

I hope it can support my use case and propose it to team leads .