Skip to content
/ genql Public

Type-safe Prisma & GraphQL Generator for the Node.js Ecosystem

Notifications You must be signed in to change notification settings

tk04/genql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

genql

Prisma & GraphQL Generator for the Node.js Ecosystem

Inspired by generators from Elixir's Phoenix Framework and Ruby on Rails

Install

Genql is installable via homebrew if you’re on Mac or Linux. To install, run the following two commands:

$ brew install tk04/tap/genql

Before using genql, you must have Prisma set up on your project. After that, you can create a model by running:

$ genql model [model name] field:type:default_value/"unique" ....

Any type value that starts with an upper case character will escape type checking and be inserted in the prisma.schema file as is.

Example Usage

You can create as many fields as you want, and even generate one-to-one, one-to-many, and many-to-many relationships between models. The third value in the colon-separated argument is reserved for default values. You can also include the “unique” keyword, which will add the “@unique” attribute to a given field.

For example, if we wanted to create a model named “User”, with an auto-incrementing id, name of type string, and an age of type int, you’d run the following command:

$ genql model User id:id:ai name:string age:int

This will add the following code block to your prisma.schema file:

model User {
	id Int @id @default(autoincrement())
	name String 
	age Int 
}

In id:id:ai, “id” is the field name, “id” is the type, and “ai” (stands for auto increment) dictates the type of the id field and the default value. The other viable entry for an id type is id:id:uuid, which generates an Id of type “String”, with a default value of a UUID string.

Genql also supports optional values. For example, if you wanted to make the name value from the previously created model optional, you’d do:

$ genql model User id:id:ai name:"string?" age:int

This will generate the following code:

model User {
	id Int @id @default(autoincrement())
	name String? 
	age Int 
}

Let’s also create a Friend model, with a default UUID id field, a unique string email field, a name field of type string, and establish a one-to-one relationship between the User and the Friend models. Here is the command to do such a task:

$ genql model Friend id:id:uuid email:string:unique name:string --OneToOne user:User

This command will add the following code to your prisma.schema file:

model User {
	id Int @id	@default(autoincrement())
	name String? 
	age Int 
	friend Friend? 
}
model Friend {
	id String @id	@default(uuid())
	email String @unique
	name String 
	user User @relation(fields: [userId], references: [id])
	userId Int @unique
}

Notice that the command also adjusted the User model to establish the one-to-one relationship between the models.

Create GraphQL Resolvers

Other than the model command, genql also supports a “resolvers” command, which will create GraphQL resolvers for a given Prisma model. This command makes a lot of assumptions about your current code organization and structure, so it’s not for everyone. It assumes that you use Type-GraphQL, and organize your resolvers under appname/src/resolvers/. The command also creates a types.ts file with each resolver that includes input & output types to be used in the queries and mutations.

To showcase using it on the Friend model we created previously, run:

$ genql resolvers Friend

This will create 2 files, both under appname/src/resolvers/Friend. The Index.ts file will contain the queries & mutations, while the types.ts file will contain the types. The “resolvers” command is supposed to be used as a basic entry point to get you started with developing your resolvers. So you’re expected to add error handling and adjust the generated code depending on your needs.

This is what the generated Index.ts file will look like:

import { Arg, Ctx, Mutation, Query, Resolver } from "type-graphql";
import { context } from "../context";
import { Friend, createFriendInput, updateFriendInput } from "./types";

@Resolver()
export class FriendResolver {
  @Mutation(() => Friend, { nullable: true })
  deleteFriend(@Ctx() { prisma }: context, @Arg("id") id: string) {
    return prisma.friend.delete({
      where: {
        id: id,
      },
    });
  }
  @Query(() => Friend, { nullable: true })
  getFriend(@Ctx() { prisma }: context, @Arg("id") id: string) {
    return prisma.friend.findFirst({
      where: {
        id: id,
      },
    });
  }
  @Mutation(() => Friend)
  createFriend(
    @Ctx() { prisma }: context,
    @Arg("input") input: createFriendInput
  ) {
    return prisma.friend.create({
      data: {
        ...input,
      },
    });
  }
  @Mutation(() => Friend)
  updateFriend(
    @Ctx() { prisma }: context,
    @Arg("input") input: updateFriendInput
  ) {
    return prisma.friend.update({
      where: { id: input.id },
      data: {
        ...input,
      },
    });
  }
}

And this is what the generated types.ts file will look like:

import { Field, InputType, ObjectType } from "type-graphql";

@ObjectType()
export class Friend {
  @Field({ nullable: true })
  id?: string;
  @Field()
  email: string;
  @Field()
  name: string;
  @Field()
  userId: number;
}
@InputType()
export class createFriendInput {
  @Field({ nullable: true })
  id?: string;
  @Field()
  email: string;
  @Field()
  name: string;
  @Field()
  userId: number;
}
@InputType()
export class updateFriendInput {
  @Field()
  id: string;
  @Field({ nullable: true })
  email?: string;
  @Field({ nullable: true })
  name?: string;
  @Field({ nullable: true })
  userId?: number;
}

About

Type-safe Prisma & GraphQL Generator for the Node.js Ecosystem

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages