Code Monkey home page Code Monkey logo

type-graphql-series's Introduction

type-graphql-series

Code for: https://www.youtube.com/playlist?list=PLN3n1USn4xlma1bBu3Tloe4NyYn9Ko8Gs

Installing

  1. Clone and install dependecies
git clone https://github.com/benawad/type-graphql-series.git
cd type-graphql-series
yarn
  1. Make sure you have PostgreSQL running on your computer with a database called typegraphql-example and a user who has access to that database with the username postgres and password postgres
  1. Make sure you have Redis running on your computer
  1. Start the server
yarn start

To verified it worked, you can go to http://localhost:4000

If you need any help setting this up feel free to message me on Discord: https://discord.gg/Vehs99V

type-graphql-series's People

Contributors

benawad avatar remusa avatar surtich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

type-graphql-series's Issues

The 'parent' element is declared, but its value is never read.

Dear Ben Awad,
I'm also trying the code in your second lesson (register resolver TypeGraphql) and I went in two different issues.
One I solved, the other not yet.
Solved: createConnection() in typeorm is deprecated so I removed the ormconfig.json file and inserted in index.ts the following code:

import { DataSource } from "typeorm"
export const AppDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "test",
database: "nodedemo",
synchronize: true,
logging: true,
entities: ["src/entity/."],
subscribers: [],
migrations: [],
})

and therefore the following to initialize the connection

const main = async () => {
await AppDataSource.initialize()
.then(() => {
// here you can start to work with your database
})
.catch((error) => console.log(error))

(....etc)

Everything is good. Query and mutation are working fine with the db but if I have still a problem with the variable 'name' as I get the following error "The 'parent' element is declared, but its value is never read.

I used your code so that I have in Register.ts

@resolver(User)
export class RegisterResolver {
@query(() => String)
async helloWorld() {
return "Hello World!";
}

@FieldResolver()
async name(@root() parent: User) {
return '${parent.firstName} ${parent.lastName}';
}
(...etc...)

and in User.ts

@ObjectType()
@entity()
export class User extends BaseEntity {
@field(() => ID)
@PrimaryGeneratedColumn()
id: number

@Field()
@Column()
firstName: string

@Field()
@Column()
lastName: string

@Field()
@Column("text", {unique: true})
email: string

@Field()
name: string;

@Column()
password: string

}

Schema must contain uniquely named types but contains multiple types named "PasswordInput".

Hi Ben,

I get some error while transpiling with "npm start":

UnhandledPromiseRejectionWarning: Error: Schema must contain uniquely named types but contains multiple types named "PasswordInput". at invariant (/Users/user1/Documents/Development/Projects/Current/API/node_modules/graphql/jsutils/invariant.js:21:11) at typeMapReducer (/Users/user1/Documents/Development/Projects/Current/API/node_modules/graphql/type/schema.js:299:57) at Array.reduce (<anonymous>) at new GraphQLSchema (/Users/user1/Documents/Development/Projects/Current/API/node_modules/graphql/type/schema.js:145:28) at Function.generateFromMetadataSync (/Users/user1/Documents/Development/Projects/Current/API/node_modules/type-graphql/dist/schema/schema-generator.js:31:24) at Function.<anonymous> (/Users/user1/Documents/Development/Projects/Current/API/node_modules/type-graphql/dist/schema/schema-generator.js:16:33) at Generator.next (<anonymous>) at /Users/user1/Documents/Development/Projects/Current/API/node_modules/tslib/tslib.js:110:75 at new Promise (<anonymous>) at Object.__awaiter (/Users/user1/Documents/Development/Projects/Current/API/node_modules/tslib/tslib.js:106:16) (node:53364) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2) (node:53364) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code

Do you have any idea where it comes from? I'm quite new to TypeORM and graphQL and a bit overwhelmed ;-)

Confirm email directly to the server

First thanks for this series

I just wanted to add that you can send the confirm url directly to the graphql server (http://localhost:4000/graphql).
Just do a post request with an hidden form and inputs inside the email.
More can be seen here:
https://www.apollographql.com/docs/apollo-server/requests.html or here https://graphql.org/learn/serving-over-http/

Some attention is needed for the value of the hidden input element. The graphql query/mutation needs double quotes inside (i believe), so it would have to be wrapped inside single quotes or maybe use something like " ?

You would have to use a button which is different from a link. But the button can always be styled as a link if necessary.
And also avoid using javascript. Some email providers may not like it as it can be seen as dangerous.

One much simpler alternative is to just use a get request. The advantage is that no form is needed, only a link tag. It would have to call a query (with the token as argument) and not a mutation. Although a little strange in this case (mutation seems to be the correct one), it should work.

For more practical info, one can just do several request in a graphql playground and see the request payload in the network tab of the dev tools.

edit:
Forgot to add that this post was just to mention an alternative solution. But i personally think that independently of the solution, the important part is to give feedback to the user about the confirmed email.

graphql/tsutils/maybe

the module graphql/tsutils/maybe is removed from new versions of graphql.
It should be changed

GraphQLError { message: 'Cannot read property \'req\' of undefined' ....

Hello Ben,
Great tutorial!
My jest tests are failing with the following error:

GraphQLError { message: 'Cannot read property \'req\' of undefined' .....

It seems to go wrong on @Ctx() { req }: IMyContext, in the resolvers. Like req doesn't exist in Ctx.
It only happens with tests. Running the application everything is working fine.

Thanks and regards,

Wilco

Can't import formatArgumentValidationError from type-graphql

Hi,

I just wanted to tell you about this problem, I can't import formatArgumentValidationError from type-graphql,

My tslint : Module '"../../TypeGraphql/node_modules/type-graphql/dist"' has no exported member 'formatArgumentValidationError'.

And i'm using tsconfig as in this repo.

Cheers

Upload value invalid.

Thanks, Ben for the series, please help I'm getting this error

{
  "message": "Variable \"$picture\" got invalid value {}; 
              Expected type Upload. Upload value invalid.",
}

This is how I pass the values on Postman
I've checked the docs over and over

{
   "query": "mutation UploadFile($picture: Upload!) {uploadFile(picture: $picture) }", 
   "variables": {"picture": null}
}

and for the map field this is what I pass

{ 
   map:  ["variables.picture"] 
}

and then the file field which is 0

   0: uploaded_file

Upload Value Invalid

 uploadClicked($event: any) {
    let file = $event.target.files[0];
    this.addPictureGQL.mutate({ picture: file }).subscribe((res) => {
      console.log(res);
    });
  }

This is my code in angular.
Before you say that you don't like angular, I don't either. Its for a school project.


The code works fine with postman, but I can't mutate and keeps throwing me errors.

image

I tried

this.addPictureGQL
      // @ts-ignore
      .mutate({ variables: { picture: file } })
      .subscribe((res) => {
        console.log(res);
      });
  }

But I got
image

Unhandled promise rejection

I am more or less following your playlist, and I'm running into an UnhandledPromiseRejection error within my Login.ts.

I have the code:

import {
  Resolver,
  Mutation,
  FieldResolver,
  Root,
  Arg,
  Ctx
} from "type-graphql";
import { User } from "../../entities/User";
import { LoginContext } from "src/types/LoginContext";

@Resolver()
export class LoginResolver {
  @FieldResolver()
  async name(@Root() parent: User) {
    return `${parent.firstName} ${parent.lastName}`;
  }

  @Mutation(() => User, { nullable: true })
  async login(
    @Arg("email") email: string,
    @Arg("password") password: string,
    @Ctx() ctx: LoginContext
  ): Promise<User> {
    // TODO: DB User lookup
    return User.MockedUser(email);
  }
}

export default LoginResolver;

And my User.js:

import { ObjectType, Field, ID } from "type-graphql";
import bcrypt from "bcryptjs";

@ObjectType()
export class User {

  @Field(() => ID)
  id: number;

  @Field()
  email: string;

  password: string;

  @Field()
  firstName: string;

  @Field()
  lastName: string;

  @Field()
  name: string;

  static MockedUser(email: string): User {
    const u = new User();
    u.id = 1;
    u.email = email;
    u.firstName = "Bob";
    u.lastName = "Jones";

    return u;
  }
}

which is basically the same as yours although, I am faking a User lookup.

However, the typescript compiler is complaining of:

UnhandledPromiseRejectionWarning: Error: No provided object type in '@Resolver' decorator for class 'LoginResolver!'

Googling this doesn't help too much. Do you have any idea what might cause this error to be raised?

Error: Schema must contain uniquely named types but contains multiple types named, but i didnt defined two schemas with the same name

this is the type that is triggering the error

const { GraphQLObjectType, GraphQLInt } = graphql;

module.exports = new GraphQLObjectType({
  name: 'Responsavel',
  fields: () => ({
    id: {
      type: GraphQLInt,
      resolve(responsavel) {
        return responsavel.id
      }
    }
  })
})

the error happens when i try to define the 'responsavel' field in the Usuario schema, i had created other fields that call other graphql schema types using the same logic, but just the 'responsavel' fires an error

const { GraphQLObjectType, GraphQLString, GraphQLInt } = graphql;
const TipoUsuarioEnumType = require('../scalar_types/TipoUsuarioEnum')
const AlunoType = require('./Aluno')
const ProfessorType = require('./Professor')
const ResponsavelType = require('./Responsavel')
const GestorType = require('./Gestor')
const AtividadeType = require('./Atividade')
const Usuario = require("../models/Usuario")
module.exports = new GraphQLObjectType({
  name: 'Usuario',
  fields: () => ({
    id: {
      type: GraphQLInt,
      resolve(usuario) {
        return usuario.id
      }
    },
    nomeDeUsuario: {
      type: GraphQLString,
      resolve(usuario) {
        return usuario.nomeDeUsuario
      }
    },
    nomeCompleto: {
      type: GraphQLString,
      resolve(usuario) {
        return usuario.nomeCompleto
      }
    },
    tipo: {
      type: TipoUsuarioEnumType,
      resolve(usuario) {
        return usuario.tipo
      }
    },
    email: {
      type: GraphQLString,
      resolve(usuario) {
        return usuario.email
      }
    },
    senha: {
      type: GraphQLString,
      resolve(usuario) {
        return usuario.senha
      }
    },
    responsavel: {
      type: ResponsavelType,
      resolve(parent, args, context, info) {
          return Usuario.findByPk(parent.id).then(usuario => {
            return usuario.getResponsavel()
          })
      }
    },
    aluno:{
      type: AlunoType,
      resolve(parent, args, context, info) {
          return Usuario.findByPk(parent.id).then(usuario => {
            return usuario.getAluno()
          })
      }
    },
    professor:{
      type: ProfessorType,
      resolve(parent, args, context, info) {
          return Usuario.findByPk(parent.id).then(usuario => {
            return usuario.getProfessor()
          })
      }
    },
    gestor: {
      type: GestorType,
      resolve(parent, args, context, info) {
          return Usuario.findByPk(parent.id).then(usuario => {
            return usuario.getGestor()
          })
      }
    },
    atividades: {
      type: AtividadeType,
      resolve(parent, args, context, info) {
          return Usuario.findByPk(parent.id).then(usuario => {
            return usuario.getAtividades()
          })
      }
    },
  })
})

Faker produces wrong Emails.

Hi,

I just wanted to tell you about this problem, I figured out after a while. Faker produces wrong gmail addresses with underscores in them. It is a known problem. So if anyone follows your videos and has a wrong faker version, the tests will fail from time to time, which is no fun. As a quick fix I just replaced underscores with periods from the generated email addresses. You can test it in the playground with and Email like: [email protected] and the answer will include "isEmail": "email must be an email".

You can close this issue immediately, I just thought it might be helpful for others if they encounter that problem and visit/search this git for a solution.

Cheers

[Question] async/await or Promises in @Field decorator

Thanks for your great tutorial!

I have in my "User-entity" a field like the "name" field you create at about minute 2:30 of video 3, but I am returning a value from Redis. So it is actually returning a promise in stead of a string. It is working, but I get an TypeScript error saying:

"Type 'Promise<string | null>' is not assignable to type 'string'."

  @Field()
  userName(@Root() parent: User): string {
    return redis.get(usernamePrefix + parent._id)
  }

Do you know how to properly return the Redis output?
So, it is working, I am just wondering if there is a better way or how to get rid of the TypeSript Error.

Thanks and regards,

Wilco

Problems with version updates to apollo-server and with typegraphql

Hi Ben,

I've just tried to install the server with updated versions to latest for typegraphql and apollo and ran into some errors.

I've fixed most of them but i'm stuck with this one:

UnhandledPromiseRejectionWarning: Error: Schema must contain uniquely named types but contains multiple types named "PasswordInput".

I wonder if you had any advice on fixing this?

Register resolver test returns null

Register functionality is doing fine but the test seems to return null on data.
Register โ€บ create user

expect(received).toMatchObject(expected)

- Expected
+ Received

  Object {
-   "data": Object {
-     "register": Object {
-       "email": "[email protected]",
-       "firstName": "Reginald",
-       "lastName": "Windler",
-     },
-   },
+   "data": null,
  }

  44 |     });
  45 | 

at src/modules/user/register/Register.test.ts:46:22
at fulfilled (src/modules/user/register/Register.test.ts:5:58)

Feature request - Flexible reusable filters on queries

Hey Ben - great series so far. I'm wondering how to best implement something in type-graphql / typeorm and hoping you consider covering it in this series.

One thing I really like about prisma or hasura is how it reduces boilerplate by automatically generating very extensive arguments when you want to do advanced queries. I.e.

{
    users(where:{ firstName_beginswith:'ja', email_contains:'@gmail' })...
}

and so on. By studying prisma I've been able to implement something similar using knex. First I define all the different type args I want to filter on like: https://github.com/jakelowen/apollo-server-2-auth-starter/blob/master/src/typeDefs/user.graphql

And then passing args through a custom knex query builder function: https://github.com/jakelowen/apollo-server-2-auth-starter/blob/master/src/utils/filterQuery.js

And then tie it all together in a resolver like:

let query = db.table(fetchPayload.table.name);
query = filterQuery(query, fetchPayload.where);

data = await paginator(
      db,
      query,
      fetchPayload.orderBy,
      fetchPayload.limit,
      fetchPayload.after,
      fetchPayload.table.uniqueColumn,
);

I think I could figure out a way to do something similar in type-graphql / typeorm by defining the args manually: i.e. @Arg("firstName_beginswith" { nullable: true }) f?: string,

Can you think of a way using higher order type-graphql resolvers to iterate over the exposed field()'s of an entity and automatically create those kinds of filter args?

OR can you think of another automated way to enable rich querying? Would love to hear your thoughts on that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.