All Articles

Creating a Reddit Clone Using React and GraphQL - 13

inner peace

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;

}

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...");

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

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: [],
});

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;

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,
}

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();

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 } });

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

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

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;

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

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

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;

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;
}

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();
}

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 amazing tutorial and I highly recommend you to check that out.

Main image credit