Last active
March 8, 2022 00:35
-
-
Save hellos3b/6385a7f7da81da990fdc94eac2989722 to your computer and use it in GitHub Desktop.
GraphQL + TypeORM example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** models/photos/Photo.ts */ | |
import {getRepository, Entity, In, Column, RelationCount, PrimaryGeneratedColumn, ManyToOne, CreateDateColumn, RelationId, OneToMany} from "typeorm"; | |
import { User, Bird, Like } from '@/models' | |
@Entity() | |
export class Photo { | |
@PrimaryGeneratedColumn() | |
id: number; | |
@Column({ length: 255 }) | |
url: string; | |
@Column({ length: 1000, default: "" }) | |
description: string; | |
@CreateDateColumn() | |
timestamp: Date; | |
@ManyToOne(type => User, user => user.photos, { eager: true }) | |
takenBy: User; | |
@RelationId( (photo: Photo) => photo.takenBy) | |
takenById: number; | |
@ManyToOne(type => Bird, bird => bird.photos) | |
bird: Bird; | |
@RelationId( (photo: Photo) => photo.bird) | |
birdId: number; | |
@OneToMany(type => Like, like => like.photoId) | |
likes: Like; | |
@RelationCount( (photo: Photo) => photo.likes) | |
likesCount: number; | |
/** API */ | |
/** Get all photos */ | |
static findAll = () => | |
getRepository(Photo) | |
.find() | |
/** Find photos taken by a specific user */ | |
static takenByUser = (userId: number) => | |
getRepository(Photo) | |
.find({ where: { takenBy: userId}}) | |
static takenByUsers = (userIds: number[]) => | |
getRepository(Photo) | |
.find({ where: { takenBy: In(userIds)}}) | |
/** Get photos of a bird */ | |
static ofBird = (bird: Bird) => | |
getRepository(Photo) | |
.find({bird: bird}) | |
static ofBirdFrom = (birdId: number, userId: number) => | |
getRepository(Photo) | |
.find({ | |
where: { | |
takenBy: userId, | |
bird: birdId | |
} | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** models/photos/PhotoQL.ts */ | |
import {Photo, User, Bird} from '@/models' | |
import {Model, Query, Resolver} from '@/lib/modelQL' | |
import { gql } from 'apollo-server-core'; | |
const schema = gql` | |
extend type Query { | |
photos: [Photo] | |
} | |
type Photo { | |
id: Int! | |
url: String! | |
description: String | |
timestamp: Date! | |
bird: Bird! | |
takenBy: User! | |
likesCount: Int | |
} | |
` | |
@Model("Photo", schema) | |
export class PhotoQL { | |
@Query() | |
async photos() { | |
return Photo.findAll() | |
} | |
@Resolver() | |
takenBy(photo: Photo) { | |
return photo.takenBy || User.findById(photo.takenById) | |
} | |
@Resolver() | |
bird(photo: Photo) { | |
return photo.bird || Bird.findById(photo.birdId) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** models/user/User.ts */ | |
/** The regular model files had the Type ORM definition and the db queries */ | |
import { getRepository, Entity, RelationCount, Column, OneToMany, JoinTable, PrimaryGeneratedColumn, ManyToMany} from "typeorm"; | |
import {Photo, Dex, Subscription} from '@/models' | |
@Entity() | |
export class User { | |
@PrimaryGeneratedColumn() | |
id: number; | |
@Column({ length: 60 }) | |
name: string; | |
@Column({ length: 120, default: "" }) | |
avatar: string; | |
@Column({ length: 120, default: "" }) | |
coverImage: string; | |
@Column({ length: 60, default: "" }) | |
city: string; | |
@OneToMany(type => Photo, photo => photo.takenBy) | |
photos: Photo[]; | |
@RelationCount((user: User) => user.photos) | |
photosCount: number; | |
@ManyToMany(type => Dex, dex => dex.favorites) | |
@JoinTable() | |
dexes: Dex[]; | |
@OneToMany(type => Subscription, sub => sub.user) | |
following: Subscription[] | |
@OneToMany(type => Subscription, sub => sub.following) | |
followers: Subscription[] | |
/** API */ | |
static findById = async (id: number) => | |
getRepository(User) | |
.findOne(id) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** models/user/UserQL.ts */ | |
/** | |
* My 'QL' files defined the schema and the resolvers | |
* I wrote a custom wrapper thing that auto merged schemas | |
**/ | |
import {Model, Query, Resolver} from "@/lib/modelQL" | |
import {Photo, User, Dex, Subscription} from '@/models' | |
import { Activity } from "../activity/Activity"; | |
import {gql} from 'apollo-server-express'; | |
const schema = gql` | |
extend type Query { | |
user(id: Int): User | |
} | |
type User { | |
id: Int! | |
name: String! | |
city: String | |
avatar: String | |
coverImage: String | |
followers: [User] | |
following: [User] | |
dexes: [Dex]! | |
photos: [Photo]! | |
feed: [Photo] | |
photosCount: Int | |
} | |
` | |
@Model("User", schema) | |
export class UserQL { | |
@Resolver() | |
photos(user: User) { | |
return Photo.takenByUser(user.id) | |
} | |
@Resolver() | |
dexes(user: User) { | |
return Dex.favoritedByUser(user) | |
} | |
@Resolver() | |
following(user: User) { | |
return Subscription.getFollowing(user) | |
} | |
@Resolver() | |
followers(user: User) { | |
return Subscription.getFollowers(user) | |
} | |
@Resolver() | |
feed(user: User) { | |
return Activity.fromUser(user.id) | |
} | |
@Query() | |
user(_: void, args: {id: number}) { | |
return User.findById(args.id) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi man, any suggestion on how to create the input to get the relations done and passing the right foreign key to the database, really appreciate