What?
Okay then, this is related to my previous article about Rakkit. So I'll advise you to go take a look around ๐.
So, here I will show you a more concrete example of what you can do using Rakkit to create a GraphQL API with a user management system.
But first: the installation of Rakkit ๐พ
So there are few dependencies that we must install to continue:
Here, I would use
apollo-server
but it's also possible to installapollo-server-koa
if you use Rakkit for REST and GraphQL which allows you to link contexts.
Just run this command to install the required dependencies:
npm i rakkit graphql @types/graphql apollo-server reflect-metadata
reflect-metadata allows us to use the decorators with TypeScript
Okay cool, now we just need to configure TypeScript to enable the decorators by creating a tsconfig.json file at the root of the project, containing this:
{ "compileOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "commonjs", "target": "es2016", "noImplicitAny": false, "sourceMap": true, "outDir": "build", "declaration": true, "importHelpers": true, "forceConsistentCasingInFileNames": true, "lib": [ "es2016", "esnext.asyncitable" ], "moduleResolution": "node" } }
./tsconfig.json
The definitions of types ๐ป
Okay then let's start by creating our User
class, which we'll have to decorate with @ObjectType()
:
import { ObjectType, Field } from "rakkit"; import * as Crypto from "crypto"; @ObjectType() export class User { @Field() username: string; @Field() email: string; @Field() id: string; // Just to show a computed property: @Field(type => String) get flatInfos(): string { return [this.name, this.email, this.id].join(":"); } constructor(username: string, email: string) { this.username = username; this.email = email; this.id = Crypto.randomBytes(16).toString("hex"); } }
./types/User.ts
You need a small "database" ๐
So we're going to have to play with some users in order to test our app, so I'm just going to create a list of user instances to make it clearer:
You can use a real database with an ORM like TypeORM for your projects
import { User } from "../types/User"; export const users = [ new User("JohnDoe", "john@doe.com"), new User("JaneDoe", "jane@doe.com"), new User("Ben", "ben@doe.com") ];
./db/users.ts
Resolver (Query, Mutation, Subscription) ๐
It is in the following class that we will define our query/mutation/subscription. It will contain a simple CRUD and a subscription to be notified when a user is registered:
import { Resolve, Query, Mutation, Subscription, IContext, Arg } from "rakkit"; import { User } from "../types/User"; import { users } from "../db/users"; @Resolver() export class UserResolver { @Query(returns => [User]) getAllUsers() { { return users; } @Query({ nullable: true }) getOneUserByName(@Arg("name") name: string): User { return users.find((user) => user.name ==== name); } @Mutation() addUser( // Defining the mutation arguments @Arg("name") name: string, @Arg("email") email: string, context: IContext ): User { const user = new User(name, email); users.push(user); // Publish the event for subscriptions with the created user context.gql.pubSub.publish("USER_ADDED", user); return user; } @Subscription({ topics: "USER_ADDED" }) userAddedNotif(createdUser: User): User { // Send the created user to the client return createdUser; } }
./resolvers/UserResolver.ts
The point of entry ๐ช
Now we need to have an entry point for our application:
// It allows us to use decorators: import "reflect-metadata"; import { Rakkit } from "rakkit"; import { ApolloServer } from "apollo-server"; async function bootstrap() { await Rakkit.start({ gql: { // You give an array of glob string: resolvers: [`${__dirname}/resolvers/*Resolver.ts`] } }); // Retrieve the GraphQL compiled schema: const schema = Rakkit.MetadataStorage.Gql.Schema; const server = new ApolloServer({ schema }); server.listen(); } bootstrap();
./bootstrap.ts
Done, so let's start and test it ! ๐
To start it you must install ts-node
globally to run directly your TypeScript app:
npm i -g ts-node
Then just run this:
ts-node relative-path-to/bootstrap.ts
And just go to http://localhost:4000 with your favorite browser to make some GraphQL queries! ๐ฅ
getOneUserByName - Get a specific user by name:
userAddedNotif - Listen to the user creation event:
Top comments (3)
Oh wow, this looks just like an exact copy of
@nestjs/graphql
just without the big community to back it up.. lolYes the GraphQL package looks like type-graphql (used by nest) but there is several differences that are mentioned in the docs ๐
For the community, every projects start from zero, we are building it ๐
Well, IMO reinventing the wheel is never good :)
And especially in this case it makes absolutely no sense at all.
What would you rather use? A new framework which reinvents everything (not even better), or a battle production tested framework with several community backed packages?