-
-
Notifications
You must be signed in to change notification settings - Fork 675
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(examples): add Typegoose integration example
- Loading branch information
1 parent
be55e3c
commit c03e70d
Showing
19 changed files
with
1,189 additions
and
7 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { ObjectType, Field, Int } from "../../../src"; | ||
import { prop as Property, Ref } from "typegoose"; | ||
|
||
import { User } from "./user"; | ||
|
||
@ObjectType() | ||
export class Rate { | ||
@Field(type => Int) | ||
@Property({ required: true }) | ||
value: number; | ||
|
||
@Field() | ||
@Property({ default: new Date(), required: true }) | ||
date: Date; | ||
|
||
@Field(type => User) | ||
@Property({ ref: User, required: true }) | ||
user: Ref<User>; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { prop as Property, arrayProp as ArrayProperty, Typegoose, Ref } from "typegoose"; | ||
import { ObjectId } from "mongodb"; | ||
import { Field, ObjectType } from "../../../src"; | ||
|
||
import { Rate } from "./rate"; | ||
import { User } from "./user"; | ||
|
||
@ObjectType() | ||
export class Recipe extends Typegoose { | ||
@Field() | ||
readonly _id: ObjectId; | ||
|
||
@Field() | ||
@Property({ required: true }) | ||
title: string; | ||
|
||
@Field({ nullable: true }) | ||
@Property() | ||
description?: string; | ||
|
||
@Field(type => [Rate]) | ||
@ArrayProperty({ items: Rate, default: [] }) | ||
ratings: Rate[]; | ||
|
||
@Field(type => User) | ||
@Property({ ref: User, required: true }) | ||
author: Ref<User>; | ||
} | ||
|
||
export const RecipeModel = new Recipe().getModelForClass(Recipe); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { prop as Property, Typegoose } from "typegoose"; | ||
import { ObjectId } from "mongodb"; | ||
import { Field, ObjectType } from "../../../src"; | ||
|
||
@ObjectType() | ||
export class User extends Typegoose { | ||
@Field() | ||
readonly _id: ObjectId; | ||
|
||
@Field() | ||
@Property({ required: true }) | ||
email: string; | ||
|
||
@Field({ nullable: true }) | ||
@Property() | ||
nickname?: string; | ||
|
||
@Property({ required: true }) | ||
password: string; | ||
} | ||
export const UserModel = new User().getModelForClass(User); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
query GetRecipes { | ||
recipes { | ||
_id | ||
title | ||
author { | ||
} | ||
ratings { | ||
value | ||
} | ||
} | ||
} | ||
|
||
query GetRecipe { | ||
# fill with correct ObjectId | ||
recipe(recipeId: "5c97eecbf49a072a00048ac5") { | ||
_id | ||
title | ||
ratings { | ||
value | ||
user { | ||
nickname | ||
} | ||
date | ||
} | ||
author { | ||
_id | ||
nickname | ||
} | ||
} | ||
} | ||
|
||
mutation AddRecipe { | ||
addRecipe(recipe: { title: "New Recipe" }) { | ||
_id | ||
ratings { | ||
value | ||
} | ||
author { | ||
nickname | ||
} | ||
} | ||
} | ||
|
||
mutation RateRecipe { | ||
# fill with correct ObjectId | ||
rate(rate: { recipeId: "5c97eecbf49a072a00048ac5", value: 4 }) { | ||
_id | ||
ratings { | ||
value | ||
user { | ||
} | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Recipe, RecipeModel } from "./entities/recipe"; | ||
import { User, UserModel } from "./entities/user"; | ||
|
||
export async function seedDatabase() { | ||
const defaultUser = await new UserModel({ | ||
email: "test@github.com", | ||
nickname: "19majkel94", | ||
password: "s3cr3tp4ssw0rd", | ||
} as User).save(); | ||
|
||
await RecipeModel.create([ | ||
{ | ||
title: "Recipe 1", | ||
description: "Desc 1", | ||
author: defaultUser._id, | ||
ratings: [ | ||
{ value: 2, user: defaultUser._id }, | ||
{ value: 4, user: defaultUser._id }, | ||
{ value: 5, user: defaultUser._id }, | ||
{ value: 3, user: defaultUser._id }, | ||
{ value: 4, user: defaultUser._id }, | ||
], | ||
}, | ||
{ | ||
title: "Recipe 2", | ||
author: defaultUser._id, | ||
ratings: [{ value: 2, user: defaultUser }, { value: 4, user: defaultUser }], | ||
}, | ||
] as Recipe[]); | ||
|
||
return { | ||
defaultUser, | ||
}; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import "reflect-metadata"; | ||
import { ApolloServer } from "apollo-server"; | ||
import { connect } from "mongoose"; | ||
import { ObjectId } from "mongodb"; | ||
import * as path from "path"; | ||
import { buildSchema } from "../../src"; | ||
|
||
import { RecipeResolver } from "./resolvers/recipe-resolver"; | ||
import { RateResolver } from "./resolvers/rate-resolver"; | ||
import { User } from "./entities/user"; | ||
import { seedDatabase } from "./helpers"; | ||
import { TypegooseMiddleware } from "./typegoose-middleware"; | ||
import { ObjectIdScalar } from "./object-id.scalar"; | ||
|
||
export interface Context { | ||
user: User; | ||
} | ||
|
||
async function bootstrap() { | ||
try { | ||
// create mongoose connection | ||
const mongoose = await connect("mongodb://localhost:27017/type-graphql"); | ||
|
||
// clean and seed database with some data | ||
await mongoose.connection.db.dropDatabase(); | ||
const { defaultUser } = await seedDatabase(); | ||
|
||
// build TypeGraphQL executable schema | ||
const schema = await buildSchema({ | ||
resolvers: [RecipeResolver, RateResolver], | ||
emitSchemaFile: path.resolve(__dirname, "schema.gql"), | ||
// use document converting middleware | ||
globalMiddlewares: [TypegooseMiddleware], | ||
// use ObjectId scalar mapping | ||
scalarsMap: [{ type: ObjectId, scalar: ObjectIdScalar }], | ||
}); | ||
|
||
// create mocked context | ||
const context: Context = { user: defaultUser }; | ||
|
||
// Create GraphQL server | ||
const server = new ApolloServer({ schema, context }); | ||
|
||
// Start the server | ||
const { url } = await server.listen(4000); | ||
console.log(`Server is running, GraphQL Playground available at ${url}`); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
|
||
bootstrap(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { GraphQLScalarType, Kind } from "graphql"; | ||
import { ObjectId } from "mongodb"; | ||
|
||
export const ObjectIdScalar = new GraphQLScalarType({ | ||
name: "ObjectId", | ||
description: "Mongo object id scalar type", | ||
parseValue(value: string) { | ||
return new ObjectId(value); // value from the client input variables | ||
}, | ||
serialize(value: ObjectId) { | ||
return value.toHexString(); // value sent to the client | ||
}, | ||
parseLiteral(ast) { | ||
if (ast.kind === Kind.STRING) { | ||
return new ObjectId(ast.value); // value from the client query | ||
} | ||
return null; | ||
}, | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Resolver, FieldResolver, Root } from "../../../src"; | ||
|
||
import { Rate } from "../entities/rate"; | ||
import { User, UserModel } from "../entities/user"; | ||
|
||
@Resolver(of => Rate) | ||
export class RateResolver { | ||
@FieldResolver() | ||
async user(@Root() rate: Rate): Promise<User> { | ||
return (await UserModel.findById(rate.user))!; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { ObjectId } from "mongodb"; | ||
import { Resolver, Query, FieldResolver, Arg, Root, Mutation, Ctx } from "../../../src"; | ||
|
||
import { Recipe, RecipeModel } from "../entities/recipe"; | ||
import { Rate } from "../entities/rate"; | ||
import { User, UserModel } from "../entities/user"; | ||
import { RecipeInput } from "./types/recipe-input"; | ||
import { RateInput } from "./types/rate-input"; | ||
import { Context } from "../index"; | ||
import { ObjectIdScalar } from "../object-id.scalar"; | ||
|
||
@Resolver(of => Recipe) | ||
export class RecipeResolver { | ||
@Query(returns => Recipe, { nullable: true }) | ||
recipe(@Arg("recipeId", type => ObjectIdScalar) recipeId: ObjectId) { | ||
return RecipeModel.findById(recipeId); | ||
} | ||
|
||
@Query(returns => [Recipe]) | ||
async recipes(): Promise<Recipe[]> { | ||
return await RecipeModel.find({}); | ||
} | ||
|
||
@Mutation(returns => Recipe) | ||
async addRecipe( | ||
@Arg("recipe") recipeInput: RecipeInput, | ||
@Ctx() { user }: Context, | ||
): Promise<Recipe> { | ||
const recipe = new RecipeModel({ | ||
...recipeInput, | ||
author: user._id, | ||
} as Recipe); | ||
|
||
return await recipe.save(); | ||
} | ||
|
||
@Mutation(returns => Recipe) | ||
async rate(@Arg("rate") rateInput: RateInput, @Ctx() { user }: Context): Promise<Recipe> { | ||
// find the recipe | ||
const recipe = await RecipeModel.findById(rateInput.recipeId); | ||
if (!recipe) { | ||
throw new Error("Invalid recipe ID"); | ||
} | ||
|
||
// set the new recipe rate | ||
const newRate: Rate = { | ||
value: rateInput.value, | ||
user: user._id, | ||
date: new Date(), | ||
}; | ||
|
||
// update the recipe | ||
(recipe.ratings as Rate[]).push(newRate); | ||
await recipe.save(); | ||
return recipe; | ||
} | ||
|
||
@FieldResolver() | ||
async author(@Root() recipe: Recipe): Promise<User> { | ||
return (await UserModel.findById(recipe.author))!; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ObjectId } from "mongodb"; | ||
import { InputType, Field, Int } from "../../../../src"; | ||
|
||
@InputType() | ||
export class RateInput { | ||
@Field() | ||
recipeId: ObjectId; | ||
|
||
@Field(type => Int) | ||
value: number; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { InputType, Field } from "../../../../src"; | ||
|
||
import { Recipe } from "../../entities/recipe"; | ||
|
||
@InputType() | ||
export class RecipeInput implements Partial<Recipe> { | ||
@Field() | ||
title: string; | ||
|
||
@Field({ nullable: true }) | ||
description?: string; | ||
} |
Oops, something went wrong.