0
votes

I'm building an Typescript application using an NX monorepo, NestJs/GraphQL/TypeGraphQL (built into @nestjs/graphql)/Prisma/PostgreSQL on the server, and NextJs on the client.

With this stack (when using the code first approach for GraphQL) you need to provide the following schemas for each entity (for example, 'User'):

  1. Prisma model schema (written in Prisma's own Prisma Schema Language), used to model the database:
model User {
  id Int @id @default(autoincrement())
  name String
  email String @unique
  password String
  createdAt DateTime @default(now()) @map("created_at")
  @@map("users")
}
  1. GraphQL returned entity schema (used to define what is returned by a resolver. The decorators are from TypeGraphQL, but are imported from @nestjs/graphql):
import { Field, ObjectType, ID } from '@nestjs/graphql';

@ObjectType()
export class User {
  @Field(() => ID)
  id: number;

  @Field()
  name: string;

  @Field()
  email: string;

  @Field()
  password: string;

  @Field()
  createdAt: Date;
}
  1. GraphQL DTO read/input schema (used to determine what fields are required/validated when someone queries your /graphql endpoint). As you can see I'm using the 'class-validator' package to perform validation using decorators:
import { InputType, Field } from '@nestjs/graphql';
import { IsEmail, IsNotEmpty } from 'class-validator';

@InputType()
export class SignupInput {
  @Field()
  @IsNotEmpty()
  name: string;

  @Field()
  @IsNotEmpty()
  @IsEmail()
  email: string;

  @Field()
  @IsNotEmpty()
  password: string;
}
  1. Client (NextJs) form input validation schema. On the client, I'm using React Hook Form, and passing a validation class, using the 'class-validator' package, to it:
class SignupForm {
  @IsNotEmpty({ message: 'Name is a required' })
  name: string;

  @IsNotEmpty({ message: 'Email is required' })
  @IsEmail({}, { message: 'This is not an email' })
  email: string;

  @IsNotEmpty({ message: 'Password is required' })
  password: string;
}

As you can see there is a LOT of overlap between these different schemas. In the spirit of keeping my code DRY, I was hoping of finding a way of sharing a single schema between all the different parts of my code.

Regarding Prisma, I think this is a lost battle, they require you to write your models in their Prisma Schema Language. There is a package that makes working with TypeGraphQL easier, but it appears not to be working with NestJs. If anyone knows anything different, please say!

Regarding TypeGraphQL, they do have a section in their docs about how to use their schema in the browser, which means it could be shared with my NextJs client. However, after hours of trying, I've been unable to get this working. Mainly, I think this is either because I'm using the TypeGraphQL provided by @nestjs/graphql or becuase of the way my NX monorepo handles Webpack config.

Some helpful links:

https://github.com/MichalLytek/type-graphql/issues/100

https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config

https://github.com/nrwl/nx/issues/3175

https://yonatankra.com/how-to-use-custom-webpack-configuration-in-a-nrwl-project/

Any help would be much appreciated.