Skip to content

Commit 118b0dd

Browse files
committed
feat: Add Favorite entity, resolver, and relations
- Add new Favorite entity and its resolver - Establish relations between Favorite and User, Book entities - Add JWT support in server.ts (entry point for GraphQL function for Lambda)
1 parent d36604a commit 118b0dd

File tree

13 files changed

+246
-26
lines changed

13 files changed

+246
-26
lines changed

package-lock.json

Lines changed: 107 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@types/node": "^20.8.7",
2020
"dotenv": "^16.3.1",
2121
"graphql": "^16.8.1",
22+
"jsonwebtoken": "^9.0.2",
2223
"pg": "^8.4.0",
2324
"pg-hstore": "^2.3.4",
2425
"reflect-metadata": "^0.1.13",

src/data-source.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import "reflect-metadata";
22
import { DataSource, DataSourceOptions } from "typeorm";
33
import { User } from "./entity/User";
44
import { Book } from "./entity/Book";
5+
import { Favorite } from "./entity/Favorite";
56
import { config } from "dotenv";
67
import { validateEnvVars } from "./utils/env";
78

@@ -28,7 +29,7 @@ const options: DataSourceOptions = {
2829
database: process.env.DB_NAME,
2930
synchronize: process.env.NODE_ENV !== "production",
3031
logging: false,
31-
entities: [Book, User],
32+
entities: [Book, User, Favorite],
3233
migrations: [],
3334
subscribers: [],
3435
ssl: true,

src/entity/Book.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm";
1+
import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from "typeorm";
2+
import { Favorite } from "./Favorite";
23

34
@Entity()
45
export class Book {
@@ -22,4 +23,7 @@ export class Book {
2223

2324
@Column({ type: "int", default: 0 })
2425
ratingsCount: number;
26+
27+
@OneToMany(() => Favorite, (favorite) => favorite.book)
28+
favorites: Favorite[];
2529
}

src/entity/Favorite.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
2+
import { User } from "./User";
3+
import { Book } from "./Book";
4+
5+
@Entity()
6+
export class Favorite {
7+
@PrimaryGeneratedColumn()
8+
id: number;
9+
10+
@ManyToOne(() => User, (user) => user.favorites)
11+
user: User;
12+
13+
@ManyToOne(() => Book, (book) => book.favorites)
14+
book: Book;
15+
}

src/entity/User.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
1+
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
2+
import { Favorite } from "./Favorite";
23

34
@Entity()
45
export class User {
6+
@PrimaryGeneratedColumn()
7+
id: number;
58

6-
@PrimaryGeneratedColumn()
7-
id: number
8-
9-
@Column()
10-
firstName: string
11-
12-
@Column()
13-
lastName: string
14-
15-
@Column()
16-
age: number
9+
@Column()
10+
auth0Id: string;
1711

12+
@OneToMany(() => Favorite, (favorite) => favorite.user)
13+
favorites: Favorite[];
1814
}

src/graphql/resolvers/Favorite.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { dataSource } from "../../data-source";
2+
import { Favorite } from "../../entity/Favorite";
3+
import { User } from "../../entity/User";
4+
import { Book } from "../../entity/Book";
5+
6+
export const FavoriteResolvers = {
7+
Mutation: {
8+
favoriteBook: async (_, { userId, bookId }, context) => {
9+
try {
10+
console.log("User ID:", userId);
11+
console.log("Book ID:", bookId);
12+
if (!userId || !bookId) {
13+
throw new Error("User ID or Book ID not provided");
14+
}
15+
const dataSourceInstance = await dataSource;
16+
const userRepository = dataSourceInstance.getRepository(User);
17+
const bookRepository = dataSourceInstance.getRepository(Book);
18+
const favoriteRepository = dataSourceInstance.getRepository(Favorite);
19+
20+
const user = await userRepository.findOne({ where: { id: userId } });
21+
const book = await bookRepository.findOne({ where: { id: bookId } });
22+
if (!user || !book) {
23+
throw new Error("User or Book not found");
24+
}
25+
26+
const favorite = new Favorite();
27+
favorite.user = user;
28+
favorite.book = book;
29+
30+
const savedFavorite = await favoriteRepository.save(favorite);
31+
console.log("Saved favorite:", savedFavorite);
32+
return savedFavorite;
33+
} catch (error) {
34+
console.error("Error favoriting book:", error);
35+
throw error;
36+
}
37+
},
38+
},
39+
Query: {
40+
favoriteBooks: async (_, { userId }, context) => {
41+
try {
42+
const dataSourceInstance = await dataSource;
43+
const favoriteRepository = dataSourceInstance.getRepository(Favorite);
44+
45+
const favorites = await favoriteRepository.find({
46+
where: { user: { id: userId } },
47+
relations: ["user", "book"],
48+
});
49+
console.log("Fetched favorites:", favorites);
50+
return favorites;
51+
} catch (error) {
52+
console.error("Error fetching favorite books:", error);
53+
throw error;
54+
}
55+
},
56+
},
57+
};

src/graphql/resolvers/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { UserResolvers } from "./User";
22
import { BookResolvers } from "./Book";
3+
import { FavoriteResolvers } from "./Favorite";
34

45
export const resolvers = {
56
Query: {
67
...UserResolvers.Query,
78
...BookResolvers.Query,
9+
...FavoriteResolvers.Query,
10+
},
11+
Mutation: {
12+
...FavoriteResolvers.Mutation,
813
},
914
};

src/graphql/types/Book.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ export const BookType = `
77
image: String
88
rating: Float!
99
ratingsCount: Int!
10+
favorites: [Favorite!]!
1011
}
1112
`;

src/graphql/types/Favorite.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const FavoriteType = `
2+
type Favorite {
3+
id: ID!
4+
user: User!
5+
book: Book!
6+
}
7+
`;

0 commit comments

Comments
 (0)