Documentation
Agatee/CLI
- Version: 1.3.1-beta.0
- Author: Niaina Dorel
If you have any questions that are beyond the scope of this documentation, Please feel free to email via niainaratsima@gmail.com.
Installation
Prerequisites
First assumed that you have installed :
Install Agatee CLI
To install the Agatee CLI just hit the command :
npm install -g @agatee/cli
If permission error occured, you can try to run the command as sudo
sudo npm install -g @agatee/cli
Print the installed agatee version
$> gat version
1.3.1-beta.0
Create your first Agatee App
-
New App using GraphQL API :
gat create my-app -api graphql
-
New App using REST API :
gat create my-app
Go to your App directory then serve it
cd my-app && gat serve
You can specify the port using --port
option, default is 3000
Congratulation 🎉 your first Agatee App is now running !
GraphQL Component
Generate component
To generate component just hit
gat generate component hero
It will generate 3 files at app/components/hero
directory :
hero.graphql
: to put GraphQL schema and fieldhero.resolver.ts
: to put resolvershero.service.ts
: to put service
--moongoose-model
option when generating component (just assumed that you already add mongoose feature)
After generating the component you need to add the resolver to @GatGraphql resolvers array at app/graphql/index.ts
import { ApolloServer } from "apollo-server-express";
import { GatGraphql, FinalResolvers, FinalTypeDefs, FinalPermissions } from "@agatee/graphql";
import { makeExecutableSchema } from "@graphql-tools/schema";
import { applyMiddleware } from "graphql-middleware";
import { shield } from "graphql-shield";
import { Server } from "../server";
import { HeroResolver } from "../components/hero/hero.resolver";
@GatGraphql({
resolvers: [HeroResolver]
})
export class GatGraphqlModule {
...
Let's add Query
Open the project with your favorite editor and let's add hero field in our app/components/hero/hero.graphql
type Hero {
name: String
power: Int
id: Int
}
Then let's create sample data and getAll method in our service app/components/hero/hero.service.ts
import { Injectable } from '@agatee/core';
export interface IHero {
name: string;
power: number;
id: number;
}
// Sample data
const heroes: IHero[] = [
{
name: 'Super Man',
power: 10,
id: 1
},
{
name: 'Hulk',
power: 9,
id: 2
}
]
@Injectable()
export class HeroService {
// Get all heroes
getAll(): IHero[] {
return heroes;
}
}
Now let's add Query resolver to get all heroes in our HeroResolver at app/components/hero/hero.resolver.ts
import { GatGqlResolver, Query } from "@agatee/graphql";
import { HeroService, IHero } from "./hero.service";
@GatGqlResolver({
schema: "./hero.graphql",
})
export class HeroResolver {
constructor(private service: HeroService) {}
// Get all heroes resolver
@Query('heroes: [Hero]')
heroes(): IHero[] {
return this.service.getAll();
}
}
Here, we decorate the resolver method heroes by the Query
decorator.
The parameter need by Query decorator is the GQL Query Field. The decorator will add this field to the final GQL type Query field
Now let's test our Query by opening localhost:3000/graphql
Adding Mutation
It's like adding Query but instead of Query
decorator just use Mutation
decorator from @agatee/graphql
Setup GQL context
you can config the GQL context at app/graphql/index.ts
in setupApolloServer
method
...
setupApolloServer() {
const schema = applyMiddleware(
makeExecutableSchema({typeDefs: this.typeDefs, resolvers: this.resolvers}),
shield(this.permissions)
)
this.appoloServer = new ApolloServer({
typeDefs: this.typeDefs,
resolvers: this.resolvers,
schema,
/// Here you can config the context
context: ({req}) => {
return {body: req.body, headers: req.headers, params: req.params};
}
});
....
Query Permission
To create Query with Permission, decorate the resolver method with Permission
decorator.
The decorator need a rule as params.
For example let's create isAdmin rule and add it to heroes resolver at app/components/hero/hero.resolver.ts
import { GatGqlResolver, Permission, Query } from "@agatee/graphql";
import { rule } from "graphql-shield";
import { HeroService, IHero } from "./hero.service";
// Define isAdminRule
// Assumed that you've already setted up context in app/graphql/index.ts and add body field equal to req.body
const isAdmin = rule()((_, __, {body}) => {
return body.variables.admin;
})
@GatGqlResolver({
schema: "./hero.graphql",
})
export class HeroResolver {
constructor(private service: HeroService) {}
// Get all heroes resolver
@Permission(isAdmin) // Permission for the this Query
@Query('heroes: [Hero]')
heroes(): IHero[] {
return this.service.getAll();
}
}
Rest Component
Generate component
To generate component just hit
gat generate component hero
It will generate 3 files at app/components/hero
directory :
hero.router.ts
: to put routershero.controller.ts
: to put controllershero.service.ts
: to put service
--moongoose-model
option when generating component (just assumed that you already add mongoose feature)
After generating the component you need to add the router to @GatModule routes array at app/app.ts
...
import { HeroRouter } from "./components/hero/hero.router";
...
@GatModule({
// IMport all component's router here to make them reachable
routes: [HeroRouter],
middlewares
})
export class AppModule {
constructor(private server: Server) {}
bootstrap() {
this.server.start();
}
}
Generate component with crud endpoint
Before adding component with crud endpoint assumed that you've already add mongoose feature
gat generate component super-hero --moongoose-model --endpoint crud
or
gat g c super-hero -mm -e crud
All CRUD endpoint will be generated for the new component.
If you need to omit an specifique endpoint just remove the char coresponding to it from crud
For example to omit delete endpoint, the command become :
gat g c super-hero -mm -e crud
Let's take a look to the app/components/super-hero/super-hero.router.ts
file
import { Request, Response } from "express";
import { GatRouterModule, GET, POST, PUT, DELETE } from "@agatee/core";
import { SuperHeroController } from './super-hero.controller';
@GatRouterModule({
path: "/api/super-hero",
})
export class SuperHeroRouter {
constructor(private controller: SuperHeroController) {}
// Create endpoint using POST method reachable from '/api/super-hero'
@POST("/")
create(req, res) {
this.controller.create(req, res);
}
// Read endpoint using GET method reachable from '/api/super-hero'
@GET("/")
list(req, res) {
this.controller.list(req, res);
}
@GET("/:id")
read(req, res) {
this.controller.read(req, res);
}
// Update endpoint using PUT method reachable from '/api/super-hero'
@PUT("/:id")
update(req, res) {
this.controller.update(req, res);
}
// Delete endpoint using DELETE method reachable from '/api/super-hero'
@DELETE("/:id")
delete(req, res) {
this.controller.delete(req, res);
}
}
Add middlewares to a route
To add middlewares to a route method just decorate it with the Middlewares
decorator from @agatee/core
The Middlewares
decorator need an array of middlewares as params
For example let's add isAdmin middleware to the Create router of SuperHero component :
app/components/super-hero/super-hero.router.ts
...
import { GatRouterModule, GET, POST, PUT, DELETE, Middlewares } from "@agatee/core";
import { SuperHeroController } from './super-hero.controller';
const isAdmin = (req, res, next) => {
if (req.body.isAdmin) {
next();
} else {
res.status(403).send('Forbidden');
}
}
@GatRouterModule({
path: "/api/super-hero",
})
export class SuperHeroRouter {
constructor(private controller: SuperHeroController) {}
@Middlewares([isAdmin]) // MIddleware for create endpoint
@POST("/")
create(req, res) {
this.controller.create(req, res);
}
@GET("/")
list(req, res) {
this.controller.list(req, res);
}
Add Mongoose to your App
To add mongoose hit:
gat add mongoose ${options}
Options:
-db-uri
: SRV string-db-host
: DB host (not need if using --db-uri)-db-port
: DB port (not need if using --db-uri)-db
: DB name (not need if using --db-uri)-db-user
: DB username (not need if using --db-uri)-db-pass
: DB password (not need if using --db-uri)
.env
file.
Add Socket.io to your App
To add Socket.io hit:
gat add socket.io
The socket server port is add to .env
(by default 3001)
Then you need to add the MainSocket
to @GatModule
imports array
...
import { MainSocket } from "./modules/socket/main.socket";
...
@GatModule({
routes: [
...
],
middlewares,
imports: [
MainSocket // IMPORT OF MAINSOCKET
]
})
export class AppModule {
constructor(private server: Server) {
this.setStaticFolders();
}
...
Listen to event @On(eventName)
To listen an event just create a method to MainSocket
at app/modules/socket/main.socket.ts
For example to listen event named 'event-test' :
import {Server, Socket} from 'socket.io';
// Add the On decorator
import { GatSocket, onConnection, On } from '@agatee/socket';
@GatSocket
export class MainSocket implements onConnection {
public readonly io: Server;
...
@On('event-test')
test(socket: Socket, data: any) {
console.log('Client with id ', socket.id, ' send a data ', data);
}
}
Create a new Socket Instance
To generate new socket instance named chat for example, hit :gat g socket-instance chat
Then like the MainSocket, you need to import
ChatSocket
to the @GatModule
imports array
Add GraphQL
If you create an app using --api graphql
option, the GraphQL has been already added
gat add graphql