1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as jsonwebtoken from 'jsonwebtoken';

import { Injectable, Middleware, MiddlewareInterface, Field, ObjectDefinition, ObjectImplementation, Resolver, Arg, Schema, BaseSchema, Interface } from 'aerographql';

/**
* Fake Database objects
*/
let users: User[] = [
{ admin: false, age: 25, description: 'Description of Bob', name: 'Bob', id: '0' },
{ admin: true, age: 36, description: 'Description of Alice', name: 'Alice', id: '1' },
{ admin: false, age: 28, description: 'Decription of Steeve', name: 'Steeve', id: '3' }
];

let todos: { [ key: string ]: ( PonctualTodo | RecurentTodo )[] } =
{
Bob: [
{ id: '0', title: 'Todo1', content: 'Bob Todo1 content', occurence: 'Every Week' },
{ id: '1', title: 'Todo2', content: 'Bob Todo2 content', date: 'Friday' },
{ id: '2', title: 'Todo3', content: 'Bob Todo3 content', occurence: 'Every Day' }
],
Alice: [
{ id: '3', title: 'Todo1', content: 'Alice Todo1 content', date: 'Mondy' },
{ id: '4', title: 'Todo2', content: 'Alice Todo2 content', date: 'Saturday' },
{ id: '5', title: 'Todo3', content: 'Alice Todo3 content', occurence: 'Every Week' } ],
Steeve: [
{ id: '6', title: 'Todo1', content: 'Steeve Todo1 content', occurence: 'Every Month' },
{ id: '7', title: 'Todo2', content: 'Steeve Todo2 content', date: 'Tuesday' },
{ id: '8', title: 'Todo3', content: 'Steeve Todo3 content', occurence: 'Every Day' } ]
};

/**
* Custom service to interact with the DB
*/
@Injectable()
class UserService {
find( name: string ) {
return users.find( u => u.name === name );
}
}

/**
* Context definitions
*/
interface Context {
req: express.Request;
user: User;
}

/**
* Authentication middleware
*/
@Middleware()
class AuthMiddleware implements MiddlewareInterface<any> {
constructor( private userService: UserService ) { }
execute( src: any, args: any, context: Context, options: any ) {
let token = context.req.headers[ 'Authorization' ] as string;
try {
jsonwebtoken.verify( token, 'secret' );
}
catch ( e ) {
throw 'Invalid token' + e;
}

let payload = jsonwebtoken.decode( token ) as any;
let u = this.userService.find( payload.name );
return u;
}
}


/**
* Schema definitions
*/
@ObjectDefinition( { name: 'User' } )
export class User {
@Field( { type: 'ID' } ) id: string;
@Field() name: string = "";
@Field() description: string = "Empty description";
@Field() age: number = 0;
@Field() admin: boolean = false;
}

@Interface( { name: 'Todo' } )
export class Todo {
@Field( { type: 'ID' } ) id: string;
@Field() title: string = "";
@Field() content: string = "Empty todo";
}

@ObjectDefinition( { implements: [ Todo ] } )
export class PonctualTodo {
@Field( { type: 'ID' } ) id: string;
@Field() title: string = "";
@Field() content: string = "Empty todo";
@Field() date: string = "Date";
}

@ObjectDefinition( { implements: [ Todo ] } )
export class RecurentTodo {
@Field( { type: 'ID' } ) id: string;
@Field() title: string = "";
@Field() content: string = "Empty todo";
@Field() occurence: string = "Date";
}

@ObjectImplementation( { name: 'User' } )
export class UserImpl {

@Resolver( { type: Todo, list: true } )
todos( user: User, @Arg( { nullable: true } ) search: string ) {
return todos[ user.name ];
}
}

@ObjectImplementation( { name: 'RootQuery' } )
export class RootQuery {
constructor( private userService: UserService ) { }

@Resolver( { type: User } )
user( @Arg() name: string ): User | Promise<User> {
return this.userService.find( name );
}

@Resolver( { type: User, nullable: true, middlewares: [ { middleware: AuthMiddleware, resultName: 'user' } ] } )
viewer( previous: any, context:Context ): User | Promise<User> {
return context.user;
}

}
@Schema( {
rootQuery: 'RootQuery',
components: [ RootQuery, User, UserImpl, Todo, PonctualTodo, RecurentTodo ],
providers: [ UserService ]
} )
export class MySchema extends BaseSchema {
}

/**
* Actual server code
*/
let fakeJWT = ( req: any, rep: any, next: any ) => {
req.headers[ 'Authorization' ] = jsonwebtoken.sign( { name: "Bob" }, 'secret' );
next();
}
let mySchema = new MySchema();
this.app = express();
this.app.use( '/graphql', bodyParser.json(), fakeJWT, graphqlExpress( ( req, res ) => {
return { schema: mySchema.graphQLSchema, context: { req, res } };
} ) );
this.app.use( '/graphiql', graphiqlExpress( { endpointURL: '/graphql' } ) );
this.app.listen( 3000, () => {
console.log( 'Up and running !' );
} );