DEV Community

Cover image for Creating a Reddit Clone Using React and GraphQL - 13
Rasika Gayan Gunarathna
Rasika Gayan Gunarathna

Posted on • Originally published at rasikag.com

Creating a Reddit Clone Using React and GraphQL - 13

This blog post originally posted on my blog site and you can find it here.

Now we want to add the relationship with POST and USER. This is a one-to-many relationship. In the MikrORM documentation, the many-to-one relationship can create by adding @ManyToOne in the entity. In example,


// mikro orm documentation example
@Entity()
export class Book {

@ManyToOne()
author!: Author;

}

Enter fullscreen mode Exit fullscreen mode

But when we set the value of author to Book entity, we need to manually get the author and set it. If we searched more, we can set the author like this,

// mikro orm documentation exaple
book.auther = orm.em.getReference < Author > (Author, "...id...");
Enter fullscreen mode Exit fullscreen mode

So, because of that, we are moving to TypeORM. Yeah, kinda huge change.

To add TypeORM to the server project, use this yarn command.


yarn add typeorm

Enter fullscreen mode Exit fullscreen mode

Then we need to change the index.ts file in the server project. First we need to add the config object to TypeORM. I created a new database for typeorm.

const conn = await createConnection({
  type: "postgresql",
  database: "redditdev03",
  username: "postgresql",
  password: mySecretKeys.myDbPassword,
  logging: true,
  synchronize: true,
  entities: [],
});
Enter fullscreen mode Exit fullscreen mode

In the above code, I need to add entities. Before that, we need to change our current entities to match with typeorm.

I change the User and Post Files. We need to change Property to Column and there are other annotations related to type-orm and replace with mikro-orm annotation. I will mention new annotations here and you can check the full changed file in GitHub.

PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, Column;
Enter fullscreen mode Exit fullscreen mode

Now we can fill entities array from type-ormconfig object. We can remove mikro-orm related things from index.ts file. Also we don’t need to pass anything to context object. Now our ApolloServer context object like this.


context: ({ req, res }: RedditDbContext) => ({
  res,
  redis,
}

Enter fullscreen mode Exit fullscreen mode

We can extend BaseEntity in User and Post entity classes. Because of that, we can use pre-defined methods for data manipulation. In the RedditDbContext object form types.ts file, we don’t need mikro-orm object. We can remove it. We used that mikro-orm object to access context in our resolvers. Let’s go and fix those. Because we extended the BaseEntity type from User and Post entities, we can use those methods in resolvers like Post.find().

For reference here is the insert query.

return Post.create({ title }).save();
Enter fullscreen mode Exit fullscreen mode

So, now we just change the post resolver and user resolver. (There are so many small changes to match with type-orm each method. So please refer to the Github files.)

If we try to find something without a primary key we need to use where property in findOne method.

await User.findOne({ where: { email } });
Enter fullscreen mode Exit fullscreen mode

While moving to type-orm we can use its query builder. Here is the code for that.

const result = await getConnection()
  .createQueryBuilder()
  .insert()
  .into(User)
  .values({
    username: options.username,
    email: options.email,
    password: hashedPassword,
  })
  .returning("*")
  .execute();
Enter fullscreen mode Exit fullscreen mode

Now we all set the type-orm. Let’s add the relationship to Post entity.


@Field()
@Column()
creatorId: number;
// posts need to match with User's property name
@ManyToOne(() => User, user => user.posts)
creator: User;

Enter fullscreen mode Exit fullscreen mode

So we need to add the posts property in the User entity.


@OneToMany(() => Post, (post) => post.creator)
posts: Post[];

Enter fullscreen mode Exit fullscreen mode

Also, we are adding new fields to Post entity. Because these are not null fields, we need to clear Post table and start it again.


@Field()
@Column()
text!: string;

@Field()
@Column({type: "int", default: 0})
points!: number;

Enter fullscreen mode Exit fullscreen mode

Then we are creating a InputType for the post. This will easier to work with the front-end.

@InputType()
class PostInput {
  @Field()
  title: string;
  @Field()
  text: string;
}
Enter fullscreen mode Exit fullscreen mode

Then we need to change the createPost method in post resolver.


@Mutation(() => Post)
async createPost(
  @Arg("input") input: PostInput,
  @Ctx() { req }: RedditDbContext
): Promise<Post> {
  return Post.create({ ...input, creatorId: req.session.userId }).save();
}

Enter fullscreen mode Exit fullscreen mode

Now we have a slight error that event anyone can create a post without login to the system. We can avoid it by checking user id in the session, but any place that we need to check user logging status we need to add a if statement. To avoid that we can use middleware. Let’s see how can we use middleware from the next post.


Thanks for reading this. If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.
That’s for today friends. See you soon. Thank you.

References:

This article series based on the Ben Award - Fullstack React GraphQL TypeScript Tutorial. This is an amazing tutorial and I highly recommend you to check that out.

Main image credit

Top comments (0)