All Projects โ†’ YassinEldeeb โ†’ prisma-tgql-types-gen

YassinEldeeb / prisma-tgql-types-gen

Licence: MIT License
โ—ญ Prisma generator for generating TypeGraphQL class types and enums with allowing to edit the generated output without being overwritten ๐Ÿ’ช

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to prisma-tgql-types-gen

nestjs-prisma-starter
Starter template for NestJS ๐Ÿ˜ป includes GraphQL with Prisma Client, Passport-JWT authentication, Swagger Api and Docker
Stars: โœญ 1,107 (+3359.38%)
Mutual labels:  prisma, type-graphql
modelina
Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents.
Stars: โœญ 55 (+71.88%)
Mutual labels:  generator, codegen
lowcode
React Lowcode - prototype, develop and maintain internal apps easier
Stars: โœญ 32 (+0%)
Mutual labels:  generator, codegen
Esview
ๆญค้กน็›ฎๅทฒๆš‚ๅœๅผ€ๅ‘
Stars: โœญ 761 (+2278.13%)
Mutual labels:  generator, codegen
Generator
Use your AsyncAPI definition to generate literally anything. Markdown documentation, Node.js code, HTML documentation, anything!
Stars: โœญ 237 (+640.63%)
Mutual labels:  generator, codegen
Typegraphql Prisma
Prisma 2 generator to emit TypeGraphQL types and CRUD resolvers from your Prisma 2 schema
Stars: โœญ 137 (+328.13%)
Mutual labels:  generator, prisma
Openapi Typescript Codegen
NodeJS library that generates Typescript or Javascript clients based on the OpenAPI specification
Stars: โœญ 249 (+678.13%)
Mutual labels:  generator, codegen
typegraphql-nestjs
TypeGraphQL integration with NestJS
Stars: โœญ 117 (+265.63%)
Mutual labels:  type-graphql, typegraphql
boilerplate
Fullstack boilerplate using Typescript, React, Node & GraphQL
Stars: โœญ 738 (+2206.25%)
Mutual labels:  prisma, type-graphql
badaso
The API & platform builder, build your apps 10x faster even more, it's open source & 100% free !
Stars: โœญ 650 (+1931.25%)
Mutual labels:  generator
nomnoml-cli
Generates images from nomnoml diagram sources in a NodeJS module or on the command line
Stars: โœญ 20 (-37.5%)
Mutual labels:  generator
password
Fast and secure password generator and library
Stars: โœญ 38 (+18.75%)
Mutual labels:  generator
gen
Gen: Friendly & Safer GORM powered by Code Generation
Stars: โœญ 677 (+2015.63%)
Mutual labels:  generator
avro-schema-generator
Library for generating avro schema files (.avsc) based on DB tables structure
Stars: โœญ 38 (+18.75%)
Mutual labels:  generator
hexo-generator-index2
Filtered index generator for Hexo
Stars: โœญ 40 (+25%)
Mutual labels:  generator
FigmaConvertXib
FigmaConvertXib is a tool for exporting design elements from figma.com and generating files to a projects iOS .xib / Android .xml
Stars: โœญ 111 (+246.88%)
Mutual labels:  generator
codegen-ace
๋””๋ฏธ๊ณ  ์ด๊ณผ๋ฐ˜ ์ž…ํ•™๊ณผ์ œ ์ฝ”๋“œ์   ๋„์šฐ๋ฏธ๐Ÿ““
Stars: โœญ 16 (-50%)
Mutual labels:  codegen
Jacob
A lightweight library to provide coroutines in Java
Stars: โœญ 14 (-56.25%)
Mutual labels:  generator
DataAnalyzer.app
โœจ๐Ÿš€ DataAnalyzer.app - Convert JSON/CSV to Typed Data Interfaces - Automatically!
Stars: โœญ 23 (-28.12%)
Mutual labels:  generator
email-template-builder
let this service generate your custom html/text emails
Stars: โœญ 25 (-21.87%)
Mutual labels:  generator

Prisma TypeGraphQL Types Generator

Banner

Prisma

Prisma is Database ORM Library for Node.js, Typescript.

Prisma basically generate each model type definition defined in schema.prisma. Therefore, it's different from other ORMs so It does not require any additional entry classes or repository layers to model your data.

However, there are limitations to prisma solution, if you're building GraphQL APIs with TypegraphQL and Prisma you've to write the same types as classes and enums in TypeGraphQL and maintain both of Prisma definitions and TypegraphQL classes and enums to be synced as you edit them and that's not very cool in my opinion.

So I created a Prisma generator to help us with generating all of the TypegraphQL models and enums by introspecting the type definitions in prisma.schema file and do all of the work for you, so you don't have to constantly go back and forth between your TypegraphQL class types and prisma.schema file when you decide to make changes.

How this differs from typegraphql-prisma by the legend himself @MichalLytek?

Features

  • Doesn't generate CRUD resolvers as typegraphql-prisma does.
  • Generates TypegraphQL class types and enums from your prisma.schema file.
  • It searches for a prettier config starting from your working directory and if it was found, It uses it for formatting the generated output.
  • The Generated output is very human readable and doesn't look like generated code what so ever.
  • The Generated output can be edited so you can edit the generated output and the next generation won't overwrite your changes but sustain them.
  • change whatever you want in the generated files and when you mess up the generator will correct you.
  • make the fields be skipped or nullable(require authentication).
  • specify the locations to tell where do you want to output the models and the enums.
  • only installs graphql-scalars automatically if any custom scalar types were used in prisma.schema like Json or Bytes
  • option to use yarn for installing graphql-scalars (default is npm).
  • add prefix or suffix to exported class names and enums.

Usage

Define Generator in schema.prisma and that's it

generator PrismaTypeGraphQLTypesGenerator {
  provider     = "npx prisma-typegraphql-types-generator"
  modelsOutput = "./src/models" // Optional defaults to "./src/generated/models"
  enumsOutput  = "./src/types/enums" // Optional defaults to "./src/generated/enums"
  useYarn      = true // Optional if you want `graphql-scalars` installation to be done via yarn defaults to "npm"
  exportedNameSuffix = "GQL" // Optional if you want to add a suffix to the end of your exported class names and enums
  exportedNamePrefix = "TYPE" // Optional if you want to prefix your exported class names and enums
}

If this is the prisma.schema ๐Ÿ‘‡

โ„น you can set the modelsOutput and the enumsOutput paths to be wherever you want and the class models files will figure out their way to get to the enums path no problem.

generator client {
  provider = "prisma-client-js"
}

generator PrismaTypeGraphQLTypesGenerator {
  provider     = "npx prisma-typegraphql-types-generator"
  modelsOutput = "./src/models"
  enumsOutput  = "./src/types/enums"
  useYarn      = true
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id                            String                 @id @default(cuid())
  name                          String                 @db.VarChar(255)
  // @nullable
  email                         String                 @unique
  // @skip
  password                      String?
  bio                           String?                @db.VarChar(160)
  // @skip
  tokenVersion                  Int                    @default(0)
  // @skip
  confirmed                     Boolean                @default(false)
  profilePic                    String?
  posts                         Post[]
  githubId                      String?                @unique
  lastTimelineVisit             DateTime?
  createdAt                     DateTime               @default(now())
  updatedAt                     DateTime               @updatedAt
}

model Post {
  id             String    @id @default(cuid())
  title          String
  body           String
  tags           String[]
  published      Boolean   @default(false)
  // @skip
  authorId       String
  author         User      @relation(fields: [authorId], references: [id], onDelete: Cascade)
  readingTimeTxt String
  readingTimeMin Float
  coverImg       String?
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt
}

The generated output will be like this ๐Ÿ˜Ž

// src/models/User.ts
import { Field, ID, ObjectType } from 'type-graphql'
import { Post } from './Post'

@ObjectType()
export class User {
  @Field((_type) => ID)
  id: string

  @Field()
  name: string

  @Field({ nullable: true })
  email: string

  @Field({ nullable: true })
  bio?: string

  @Field({ nullable: true })
  profilePic?: string

  @Field((_type) => [Post])
  posts: Post[]

  @Field({ nullable: true })
  githubId?: string

  @Field({ nullable: true })
  lastTimelineVisit?: Date

  @Field()
  createdAt: Date

  @Field()
  updatedAt: Date

  // skip overwrite ๐Ÿ‘‡
}
// src/models/Post.ts
import { Field, ID, ObjectType, Float } from 'type-graphql'
import { User } from './User'
import { Language } from '../src/types/enums/Language'

@ObjectType()
export class Post {
  @Field((_type) => ID)
  id: string

  @Field()
  title: string

  @Field()
  body: string

  @Field((_type) => [String])
  tags: string[]

  @Field()
  published: boolean

  @Field((_type) => User)
  author: User

  @Field()
  readingTimeTxt: string

  @Field((_type) => Float)
  readingTimeMin: number

  @Field({ nullable: true })
  coverImg?: string

  @Field((_type) => Language)
  language: Language

  @Field()
  createdAt: Date

  @Field()
  updatedAt: Date

  // skip overwrite ๐Ÿ‘‡
}
// src/types/enums/Language.ts
import { registerEnumType } from 'type-graphql'

export enum Language {
  Typescript = 'Typescript',
  Javascript = 'Javascript',
  Go = 'Go',
  Rust = 'Rust',
  Python = 'Python',
  Java = 'Java',
  Swift = 'Swift',
}
registerEnumType(Language, {
  name: 'Language',
})

What's the // @skip and // @nullable do in prisma.schema file?

// @skip before a field in your prisma.schema file means you're telling the generator that this field is just specific for backend stuff and won't be queryable by graphql clients, so it skips adding it to the class type.

// @nullable before a field in your prisma.schema file means you're telling the generator that this field can be queryable but it depends on who's asking, so an email as an example won't be exposed to anyone just authenticated user can show his email, so It marks that field as nullable: true to assure that you won't get the email of the user if you're not that user himself.

How to edit the Generated Code without being overwritten by the generator?

You've probably noticed the // skip overwrite ๐Ÿ‘‡ comment at the very bottom of any generated class model and this's a part of what I like to call Safe Areas where you can write code without being overwritten by the generator.

So there're 4 Safe Areas:

1- above the class where you can add your own logic here and import other files/libraries

โ„น when you try messing up by removing imports that a class needs, the generator will correct you and add it again

// src/models/User.ts
import { Field, ID, ObjectType } from 'type-graphql'
import { Post } from './Post'
+ import { addTwoNumbers } from '../utils/sillyStuff'
+
+ console.log(addTwoNumbers(1, 4))
+
@ObjectType()
export class User {
  @Field((_type) => ID)
  id: string
  ...

2- Field Config object

// src/models/User.ts
@ObjectType()
export class User {
  ...
- @Field({ nullable: true })
+ @Field({
+   nullable: true
+   description: 'This field is looking kinda sussy',
+   simple: true,
+   complexity: 5,
+ })
  username?: string
  ...

3- below the // skip overwrite ๐Ÿ‘‡ comment

// src/models/User.ts
@ObjectType()
export class User {
  ...
  // skip overwrite ๐Ÿ‘‡
+ @Field()
+ sayHello: string
}

4- after the class

// src/models/User.ts
@ObjectType()
export class User {
  ...
  // skip overwrite ๐Ÿ‘‡
}

+ @ObjectType()
+ export class UserPayload {
+   @Field((_type) => User)
+   data: User
+
+   @Field()
+   token: string
+ }

Real World Example

Blogs/Podcasts-Platform

Known Issues

Basically the only times you'll see the TypeGraphQL file introspecter fails is caused by the leaky implementation I did to grab the object from the field decorator.

1- Can't use the object shorthand syntax in the field config object.

Won't work ๐Ÿ‘‡

...
import { complexity } from '../shared/complexity'

@ObjectType()
export class User {
+ @Field((_type) => ID, { complexity })
  id: string
  ...
}

2- Using commas in any string in the field config object confuses the introspecter to make it think that this comma is the end of defining a certain field in this object, so currently the solution is to add the string to a variable outside of the class and use it bellow.

Won't work ๐Ÿ‘‡

...
import { complexity } from '../shared/complexity'

@ObjectType()
export class User {
+ @Field((_type) => ID, { name: ",", complexity: 1 })
  id: string
  ...
}

Will work ๐Ÿ‘‡

...
import { complexity } from '../shared/complexity'

const IDFieldName = ","

@ObjectType()
export class User {
+ @Field((_type) => ID, { name: IDFieldName, complexity: 1 })
  id: string
  ...
}

Contributing

We'll be very thankful for all your contributions, whether it's for helping us find issues in our code, highlighting features that're missing, writing tests for uncovered cases, or contributing to the codebase.

Read the Contributing guide to get started.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].