SlideShare une entreprise Scribd logo
1  sur  47
Télécharger pour lire hors ligne
GraphQL BKK 2.0
Meetup, Bangkok, 27th September 2018
Nice to meet you!
Tobias 
2
Lucas Junerey
GraphQL BKK Roadmap
3
past
1.0
Setup
Continuous
Deployment
Ongoing Meetups
every 2
months
GraphQL Asia
Conference in Bangkok
2019
Partnerships
Apollo Prisma BrikL
4
GraphQL Day  AppSync
workshop coming up...
You  Your Company?
Talk to Us
Nimbl3 Gatsby
● GraphQL Introduction
● Nimbl3
● Gatsby (Tony)
● Resolver patterns (Lucas)
● Connect, Talk, Hack until 10pm
No breaks 
5
~ 8.30pm
6
  
1 2 3
Your GraphQL?
GraphQL
Introduction
GraphQL - A Query Language for
APIs not databases
8
… and more
… and more
… and more
9
Declarative data
fetching
Exposes a single
endpoint and
responds to queries
New API
standard
GraphQL
10
GraphQL is NOT
only for React
Developers
● Facebook started using
GraphQL in 2012 in their native
mobile apps
● It can be used with any
programming languages and
framework
11
Everywhere where client communicates with API!
REST
● Increased mobile
usage creates need
for efficient data
loading
● Variety of different
frontend
frameworks and
platforms
● Fast development 
expectation for
rapid feature
development
12
?REST has been a popular way to expose data from a server
Who’s using GraphQL?
13
14
15
Get started?
Apollo Boost + Apollo Launchpad
?
Gatsby
Resolver PatternsLucas Munhoz  Tobias Meixner
Backend Tasks
19
- Authentication
- Authorization
- Database access
- Caching
- Tracing
- Logging
- Error handling
20
 Middleware
Route Controller
Data Layer
HTTP
Request
/payments
HTTP
Response
REST
isAuthenticated
getUserPayments
db.payments.find
1 request === 1 response
Status Code 200,
OK
{ data }
[
{
id: tr_10340J2eZvKYlo2Cg42HilbB,
amount: 5687,
arrival_date: 1386374400,
automatic: true,
balance_transaction: txn_19XJJ02eZvKYlo2ClwuJ1rbA,
created: 1386212146,
currency: usd,
failure_balance_transaction: null,
failure_code: null,
method: standard,
source_type: card,
status: paid,
type: bank_account
},
{
…
}
]
async function isAuthenticated(req, res, next) {
const user = await getUserViaJWT(req.headers.authorization)
if (!user){
return res.status(401).end()
}
// Inject user in the request object
req.user = user
next() // Call next middleware in the chain
}
app.post('/login’, controller.login)
app.get('/payments', isAuthenticated, controller.getUserPayments)
isAdmin
21
 Middleware
Route Controller
Data Layer
HTTP Request
/users/:id/ban
HTTP
Response
REST
isAuthenticated
banUser
db.users.update
1 request === 1 response
Status Code 200,
OK
{ data }
async function isAuthenticated(req, res, next) { … }
async function isAdmin(req, res, next) {
const user = req.user
if (!user.roles.includes('admin')){
return res.status(401).end()
}
next() // Call next middleware in the chain
}
app.put('/users/:id/ban', [isAuthenticated, isAdmin], controller.banUser)
22
 Resolver
Data Layer
HTTP
Request
/graphql
HTTP
Response
GraphQL
...
Status Code 200,
OK
{ data }
query {
payments {
id
amount
currency
source_type
status
}
}
async function payments(parent, args, context, info) {
const userId = context.user.id
const payments = await context.db.getUserPayments({ userId })
return payments
}
{
data: {
payments: [
{
id: tr_10340J2eZvKYlo2Cg42HilbB,
amount: 5687,
currency: usd,
source_type: card,
status: paid,
},
{
...
}
]
}
23
query {
payments {
id
amount
currency
source_type
status
}
}
{
data: {
payments: [
{
id: tr_10340J2eZvKYlo2Cg42HilbB,
amount: 5687,
currency: usd,
source_type: card,
status: paid,
},
{
...
}
]
}
}
24
type Payment {
id: UUID!
amount: Float!
currency: String!
source_type: String!
invoice: Invoice!
}
# Root Type
type Query {
payments(status: String): [Payment!]!
}
query {
payments {
id
amount
currency
source_type
status
}
}
Schema Definition Execution
Scalar Type
# Schema definition ./src/schema.graphql
scalar UUID
# Root Resvolver ./src/resolvers/uuid.js
const GraphQLUUID = new GraphQLScalarType({
name: 'UUID',
description: 'The `UUID` scalar type represents UUID values as specified by [RFC 4122].',
serialize: value = {
if (!isUUID(value)) {
throw new TypeError(`UUID cannot represent non-UUID value: ${value}`);
}
return value.toLowerCase();
},
parseValue: value = {
if (!isUUID(value)) {
throw new TypeError(`UUID cannot represent non-UUID value: ${value}`);
}
25
type Payment {
...
invoice: Invoice!
}
type Invoice {
id: UUID!
issued_at: DateTime!
payment: Payment
url: String!
}
type Query { … }
query {
payments {
id
status
invoice {
id
issued_at
url
}
}
}
Schema Definition Execution
Field Type
# Type resolver ./src/resolvers/payment.js
export default {
Payment: {
invoice: async (parent, args, context, info) = {
const invoice = await context.db.getInvoiceForPayment({
paymentId: parent.id
})
return invoice
}
}
}
{
data: {
payments: [
{
id: ...,
status: paid,
invoice: {
id: ...,
issued_at: Thu Sep 27 2018...,
url: https://invoice/download
},
},
...
}
“
Each field in a GraphQL schema is
backed by a resolver.
26
27
query {
payments {
id
invoice {
id
payment {
id
invoice {
payment {
invoice {
payment {
invoice {
id
issued_at
}
}
...
“GraphQL queries can traverse related objects and their
fields, letting clients fetch lots of related data in one
request, instead of making several roundtrips as one would
need in a classic REST architecture.
28
29
● Access control must be moved to resolver
or data layer (no more middleware)
29
Challenges
● Free data traversing of types and
relationships adds more complexity to
access control and data fetching
● Request and response must be multiplex
(query batching)
query {
payments(status: paid) {
id
status
}
subscribers {
id
firstName
lastName
subscribed_at
}
}
{
data: {
payments: [{
id: ...,
status: paid,
}],
subscribers: [{
id: ...,
firstName: James,
lastName: Porlante,
subscribed_at: ...,
}]
}
}
30
Context Injection
async function payments(parent, args, context, info) {
const userId = context.user.id
const payments = await context.db.getUserPayments({ userId })
return payments
}
const resolvers = require('./resolvers')
const repositories = require('./repositories') // - Data Layer
const server = new GraphQLServer({
typeDefs: importSchema('./src/schema.graphql'),
resolvers,
context: (request) = ({
...request,
db: repositories,
user: getUserViaJWT(req.headers.authorization),
sentry: Sentry
})
})
31
● Clients don’t rely more on status code, so
errors must be parsed and formatted for
every query
● Code must be DRY
31
Challenges
32
Resolver Chain + Error Handling
import { createResolver } from 'apollo-resolvers';
import { createError, isInstance } from 'apollo-errors';
const UnknownError = createError('UnknownError', {
message: 'An unknown error has occurred! Please try again later'
});
export const baseResolver = createResolver(
//incoming requests will pass through this resolver like a no-op
null,
(root, args, context, error) = isInstance(error) ? error : new UnknownError()
);
const ForbiddenError = createError('ForbiddenError', {
message: 'You are not allowed to do this'
});
const AuthenticationRequiredError = createError('AuthenticationRequiredError', {
message: 'You must be logged in to do this'
});
export const isAuthenticatedResolver = baseResolver.createResolver(
(root, args, context, info) = {
if (!context.user) throw new AuthenticationRequiredError();
}
);
const isAdminResolver = isAuthenticatedResolver.createResolver(
// Extract the user from the context
(root, args, { user }, info) = {
if (!user.roles.includes('admin')) throw new ForbiddenError();
}
)
// ./src/resolvers/query.ts
export default {
subscribers: isAdminResolver.createResolver(
(root, args, context, info) = {
return context.db.getAllSubscribers()
}
})
}
33
graphql-middleware
export const logInput = async (resolve, root, args, context, info) = {
console.log(`1. logInput: ${JSON.stringify(args)}`)
const result = await resolve(root, args, context, info)
console.log(`5. logInput`)
return result
}
export const logResult = async (resolve, root, args, context, info) = {
console.log(`2. logResult`)
const result = await resolve(root, args, context, info)
console.log(`4. logResult: ${JSON.stringify(result)}`)
return result
}
const { logInput, logOutput } = require('./middlewares')
const server = new GraphQLServer({
typeDefs,
resolvers,
middlewares: [logInput, logResult],
})
server.start(() = console.log('Server is running on
http://localhost:4000'))
34
Schema Directives
directive @rest(url: String) on FIELD_DEFINITION
type Query {
people: [Person] @rest(url: /api/v1/people)
}
class RestDirective extends SchemaDirectiveVisitor {
public visitFieldDefinition(field) {
const { url } = this.args;
field.resolve = () = fetch(url);
}
}
const schema = makeExecutableSchema({
typeDefs,
schemaDirectives: {
rest: RestDirective
}
});
35
Schema Directives from Prisma
type Payment {
id: ID! @unique
status: @default(value: “not-paid”)
invoice: Invoice! @relation(name: Payment_Invoice)
}
36
Backend  Database as a Service
37
and others...
Prisma
38
Hasura
Patterns
39
● Root resolvers
● Type  Field resolvers
● Context injection
● Apollo Resolvers
● GraphQL Middleware
● Schema directives
● Database / Backend as a service
A
B
S
T
R
A
C
T
I
O
N
Personal flavour
and opinion
Legacy APIs
Project size
Complexity
Apply depending on
Use case

Packages to extend GraphQL native resolvers
40
● graphql-tools
● apollo-server
● graphql-compose
● graphql-shield
● graphql-middleware
● graphql-sequelize
● mongoose-schema-to-graphql
● ...
Resolver Cheat Sheet
41
Auth Authz ORM Datasource Logging Caching Tracing
Type  Field resolvers
Modular resolvers
Root resolvers
GraphQL Middleware
Context injection
Schema directives
DaaS / BaaS
Resolver patterns @ BrikL
42
Auth Authz ORM Data Logging Caching Tracing
Type  Field resolvers
Modular resolvers
Root resolvers
GraphQL Middleware
Context injection
Schema directives
DaaS / BaaS
Resolver patterns @ BrikL
43
Auth Authz ORM Data Logging Caching Tracing
Type  Field resolvers
Modular resolvers
Root resolvers
GraphQL Middleware
Context injection
Schema directives
DaaS / BaaS
Schema
Resolver patterns @ Envisioning
44
Auth Authz ORM Data Logging Caching Tracing
Type  Field resolvers
Modular resolvers
Root resolvers
GraphQL Middleware
Context injection
Schema directives
DaaS / BaaS
45
Thanks!
Any questions?
Connect, Talk, Hack until 10pm
See you in November
References
46
https://www.prisma.io/docs/tutorials/build-graphql-servers/misc/resolver-patterns-eifeecahx4/
https://www.apollographql.com/docs/graphql-tools/resolvers
https://blog.apollographql.com/layering-graphql-on-top-of-rest-569c915083ad
https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/
https://www.prisma.io/blog/graphql-middleware-zie3iphithxy/
https://medium.com/@colecodes/structuring-data-with-apollo-server-e114a302aec7
https://itnext.io/graphql-resolvers-the-injector-pattern-a7e1d880c512
https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1
Credits (Slidetheme)
Special thanks to all the people who made and
released these awesome resources for free:
● Presentation template by SlidesCarnival
● Photographs by Unsplash
47

Contenu connexe

Tendances

Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...MongoDB
 
PyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolPyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolCrea Very
 
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]Connecting and using PostgreSQL database with psycopg2 [Python 2.7]
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]Dinesh Neupane
 
Spray Json and MongoDB Queries: Insights and Simple Tricks.
Spray Json and MongoDB Queries: Insights and Simple Tricks.Spray Json and MongoDB Queries: Insights and Simple Tricks.
Spray Json and MongoDB Queries: Insights and Simple Tricks.Andrii Lashchenko
 
The rise of json in rdbms land jab17
The rise of json in rdbms land jab17The rise of json in rdbms land jab17
The rise of json in rdbms land jab17alikonweb
 
Webinar: Transitioning from SQL to MongoDB
Webinar: Transitioning from SQL to MongoDBWebinar: Transitioning from SQL to MongoDB
Webinar: Transitioning from SQL to MongoDBMongoDB
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidRodrigo de Souza Castro
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQueryPhDBrown
 
Reducing Development Time with MongoDB vs. SQL
Reducing Development Time with MongoDB vs. SQLReducing Development Time with MongoDB vs. SQL
Reducing Development Time with MongoDB vs. SQLMongoDB
 
Webinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationWebinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationMongoDB
 
MongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015NoSQLmatters
 

Tendances (19)

Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
 
PyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolPyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management tool
 
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]Connecting and using PostgreSQL database with psycopg2 [Python 2.7]
Connecting and using PostgreSQL database with psycopg2 [Python 2.7]
 
Id32
Id32Id32
Id32
 
Spray Json and MongoDB Queries: Insights and Simple Tricks.
Spray Json and MongoDB Queries: Insights and Simple Tricks.Spray Json and MongoDB Queries: Insights and Simple Tricks.
Spray Json and MongoDB Queries: Insights and Simple Tricks.
 
The rise of json in rdbms land jab17
The rise of json in rdbms land jab17The rise of json in rdbms land jab17
The rise of json in rdbms land jab17
 
Webinar: Transitioning from SQL to MongoDB
Webinar: Transitioning from SQL to MongoDBWebinar: Transitioning from SQL to MongoDB
Webinar: Transitioning from SQL to MongoDB
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no android
 
Kode
KodeKode
Kode
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQuery
 
Road to react hooks
Road to react hooksRoad to react hooks
Road to react hooks
 
Reducing Development Time with MongoDB vs. SQL
Reducing Development Time with MongoDB vs. SQLReducing Development Time with MongoDB vs. SQL
Reducing Development Time with MongoDB vs. SQL
 
16 18
16 1816 18
16 18
 
Webinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationWebinar: Index Tuning and Evaluation
Webinar: Index Tuning and Evaluation
 
Ajax chap 5
Ajax chap 5Ajax chap 5
Ajax chap 5
 
MongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() Output
 
Ajax chap 4
Ajax chap 4Ajax chap 4
Ajax chap 4
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
 
Mobile Web 5.0
Mobile Web 5.0Mobile Web 5.0
Mobile Web 5.0
 

Similaire à GraphQL Bangkok Meetup 2.0

A real-world Relay application in production - Stefano Masini - Codemotion Am...
A real-world Relay application in production - Stefano Masini - Codemotion Am...A real-world Relay application in production - Stefano Masini - Codemotion Am...
A real-world Relay application in production - Stefano Masini - Codemotion Am...Codemotion
 
A Tour of Building Web Applications with R Shiny
A Tour of Building Web Applications with R Shiny A Tour of Building Web Applications with R Shiny
A Tour of Building Web Applications with R Shiny Wendy Chen Dubois
 
How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...Oleksandr Tarasenko
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsTimur Shemsedinov
 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platformsAyush Sharma
 
Implementation of GUI Framework part3
Implementation of GUI Framework part3Implementation of GUI Framework part3
Implementation of GUI Framework part3masahiroookubo
 
Synchronize AD and OpenLDAP with LSC
Synchronize AD and OpenLDAP with LSCSynchronize AD and OpenLDAP with LSC
Synchronize AD and OpenLDAP with LSCLDAPCon
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hacksteindistributed matters
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silexMichele Orselli
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 
Serverless Apps - droidcon london 2012
Serverless Apps - droidcon london 2012Serverless Apps - droidcon london 2012
Serverless Apps - droidcon london 2012Friedger Müffke
 
Data integration
Data integrationData integration
Data integrationBallerina
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access RunbookTaha Shakeel
 
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeKAI CHU CHUNG
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)croquiscom
 
GraphQL, Redux, and React
GraphQL, Redux, and ReactGraphQL, Redux, and React
GraphQL, Redux, and ReactKeon Kim
 
GraphQL the holy contract between client and server
GraphQL the holy contract between client and serverGraphQL the holy contract between client and server
GraphQL the holy contract between client and serverPavel Chertorogov
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013Laurent_VB
 

Similaire à GraphQL Bangkok Meetup 2.0 (20)

A real-world Relay application in production - Stefano Masini - Codemotion Am...
A real-world Relay application in production - Stefano Masini - Codemotion Am...A real-world Relay application in production - Stefano Masini - Codemotion Am...
A real-world Relay application in production - Stefano Masini - Codemotion Am...
 
A Tour of Building Web Applications with R Shiny
A Tour of Building Web Applications with R Shiny A Tour of Building Web Applications with R Shiny
A Tour of Building Web Applications with R Shiny
 
How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platforms
 
NoSQL meets Microservices
NoSQL meets MicroservicesNoSQL meets Microservices
NoSQL meets Microservices
 
Implementation of GUI Framework part3
Implementation of GUI Framework part3Implementation of GUI Framework part3
Implementation of GUI Framework part3
 
Synchronize AD and OpenLDAP with LSC
Synchronize AD and OpenLDAP with LSCSynchronize AD and OpenLDAP with LSC
Synchronize AD and OpenLDAP with LSC
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hackstein
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Serverless Apps - droidcon london 2012
Serverless Apps - droidcon london 2012Serverless Apps - droidcon london 2012
Serverless Apps - droidcon london 2012
 
Data integration
Data integrationData integration
Data integration
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
GraphQL, Redux, and React
GraphQL, Redux, and ReactGraphQL, Redux, and React
GraphQL, Redux, and React
 
GraphQL the holy contract between client and server
GraphQL the holy contract between client and serverGraphQL the holy contract between client and server
GraphQL the holy contract between client and server
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 

Plus de Tobias Meixner

GraphQL Server - Single point of opportunities
GraphQL Server - Single point of opportunitiesGraphQL Server - Single point of opportunities
GraphQL Server - Single point of opportunitiesTobias Meixner
 
GraphQL Bangkok Meetup 6.0
GraphQL Bangkok Meetup 6.0GraphQL Bangkok Meetup 6.0
GraphQL Bangkok Meetup 6.0Tobias Meixner
 
BrikL - A GraphQL Native - GraphQL Asia 2019
BrikL - A GraphQL Native - GraphQL Asia 2019BrikL - A GraphQL Native - GraphQL Asia 2019
BrikL - A GraphQL Native - GraphQL Asia 2019Tobias Meixner
 
GraphQL Bangkok meetup 5.0
GraphQL Bangkok meetup 5.0GraphQL Bangkok meetup 5.0
GraphQL Bangkok meetup 5.0Tobias Meixner
 
GraphQL Meetup Bangkok 4.0
GraphQL Meetup Bangkok 4.0GraphQL Meetup Bangkok 4.0
GraphQL Meetup Bangkok 4.0Tobias Meixner
 
GraphQL Meetup Bangkok 3.0
GraphQL Meetup Bangkok 3.0GraphQL Meetup Bangkok 3.0
GraphQL Meetup Bangkok 3.0Tobias Meixner
 

Plus de Tobias Meixner (8)

Public GraphQL APIs
Public GraphQL APIsPublic GraphQL APIs
Public GraphQL APIs
 
GraphQL Server - Single point of opportunities
GraphQL Server - Single point of opportunitiesGraphQL Server - Single point of opportunities
GraphQL Server - Single point of opportunities
 
GraphQL Bangkok Meetup 6.0
GraphQL Bangkok Meetup 6.0GraphQL Bangkok Meetup 6.0
GraphQL Bangkok Meetup 6.0
 
BrikL - A GraphQL Native - GraphQL Asia 2019
BrikL - A GraphQL Native - GraphQL Asia 2019BrikL - A GraphQL Native - GraphQL Asia 2019
BrikL - A GraphQL Native - GraphQL Asia 2019
 
GraphQL Asia Speakers
GraphQL Asia SpeakersGraphQL Asia Speakers
GraphQL Asia Speakers
 
GraphQL Bangkok meetup 5.0
GraphQL Bangkok meetup 5.0GraphQL Bangkok meetup 5.0
GraphQL Bangkok meetup 5.0
 
GraphQL Meetup Bangkok 4.0
GraphQL Meetup Bangkok 4.0GraphQL Meetup Bangkok 4.0
GraphQL Meetup Bangkok 4.0
 
GraphQL Meetup Bangkok 3.0
GraphQL Meetup Bangkok 3.0GraphQL Meetup Bangkok 3.0
GraphQL Meetup Bangkok 3.0
 

Dernier

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 

Dernier (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

GraphQL Bangkok Meetup 2.0

  • 1. GraphQL BKK 2.0 Meetup, Bangkok, 27th September 2018
  • 2. Nice to meet you! Tobias  2 Lucas Junerey
  • 3. GraphQL BKK Roadmap 3 past 1.0 Setup Continuous Deployment Ongoing Meetups every 2 months GraphQL Asia Conference in Bangkok 2019
  • 4. Partnerships Apollo Prisma BrikL 4 GraphQL Day AppSync workshop coming up... You Your Company? Talk to Us Nimbl3 Gatsby
  • 5. ● GraphQL Introduction ● Nimbl3 ● Gatsby (Tony) ● Resolver patterns (Lucas) ● Connect, Talk, Hack until 10pm No breaks  5 ~ 8.30pm
  • 6. 6    1 2 3 Your GraphQL?
  • 8. GraphQL - A Query Language for APIs not databases 8 … and more … and more … and more
  • 9. 9 Declarative data fetching Exposes a single endpoint and responds to queries New API standard GraphQL
  • 10. 10
  • 11. GraphQL is NOT only for React Developers ● Facebook started using GraphQL in 2012 in their native mobile apps ● It can be used with any programming languages and framework 11 Everywhere where client communicates with API!
  • 12. REST ● Increased mobile usage creates need for efficient data loading ● Variety of different frontend frameworks and platforms ● Fast development expectation for rapid feature development 12 ?REST has been a popular way to expose data from a server
  • 14. 14
  • 15. 15 Get started? Apollo Boost + Apollo Launchpad ?
  • 16.
  • 19. Backend Tasks 19 - Authentication - Authorization - Database access - Caching - Tracing - Logging - Error handling
  • 20. 20  Middleware Route Controller Data Layer HTTP Request /payments HTTP Response REST isAuthenticated getUserPayments db.payments.find 1 request === 1 response Status Code 200, OK { data } [ { id: tr_10340J2eZvKYlo2Cg42HilbB, amount: 5687, arrival_date: 1386374400, automatic: true, balance_transaction: txn_19XJJ02eZvKYlo2ClwuJ1rbA, created: 1386212146, currency: usd, failure_balance_transaction: null, failure_code: null, method: standard, source_type: card, status: paid, type: bank_account }, { … } ] async function isAuthenticated(req, res, next) { const user = await getUserViaJWT(req.headers.authorization) if (!user){ return res.status(401).end() } // Inject user in the request object req.user = user next() // Call next middleware in the chain } app.post('/login’, controller.login) app.get('/payments', isAuthenticated, controller.getUserPayments)
  • 21. isAdmin 21  Middleware Route Controller Data Layer HTTP Request /users/:id/ban HTTP Response REST isAuthenticated banUser db.users.update 1 request === 1 response Status Code 200, OK { data } async function isAuthenticated(req, res, next) { … } async function isAdmin(req, res, next) { const user = req.user if (!user.roles.includes('admin')){ return res.status(401).end() } next() // Call next middleware in the chain } app.put('/users/:id/ban', [isAuthenticated, isAdmin], controller.banUser)
  • 22. 22  Resolver Data Layer HTTP Request /graphql HTTP Response GraphQL ... Status Code 200, OK { data } query { payments { id amount currency source_type status } } async function payments(parent, args, context, info) { const userId = context.user.id const payments = await context.db.getUserPayments({ userId }) return payments } { data: { payments: [ { id: tr_10340J2eZvKYlo2Cg42HilbB, amount: 5687, currency: usd, source_type: card, status: paid, }, { ... } ] }
  • 23. 23 query { payments { id amount currency source_type status } } { data: { payments: [ { id: tr_10340J2eZvKYlo2Cg42HilbB, amount: 5687, currency: usd, source_type: card, status: paid, }, { ... } ] } }
  • 24. 24 type Payment { id: UUID! amount: Float! currency: String! source_type: String! invoice: Invoice! } # Root Type type Query { payments(status: String): [Payment!]! } query { payments { id amount currency source_type status } } Schema Definition Execution Scalar Type # Schema definition ./src/schema.graphql scalar UUID # Root Resvolver ./src/resolvers/uuid.js const GraphQLUUID = new GraphQLScalarType({ name: 'UUID', description: 'The `UUID` scalar type represents UUID values as specified by [RFC 4122].', serialize: value = { if (!isUUID(value)) { throw new TypeError(`UUID cannot represent non-UUID value: ${value}`); } return value.toLowerCase(); }, parseValue: value = { if (!isUUID(value)) { throw new TypeError(`UUID cannot represent non-UUID value: ${value}`); }
  • 25. 25 type Payment { ... invoice: Invoice! } type Invoice { id: UUID! issued_at: DateTime! payment: Payment url: String! } type Query { … } query { payments { id status invoice { id issued_at url } } } Schema Definition Execution Field Type # Type resolver ./src/resolvers/payment.js export default { Payment: { invoice: async (parent, args, context, info) = { const invoice = await context.db.getInvoiceForPayment({ paymentId: parent.id }) return invoice } } } { data: { payments: [ { id: ..., status: paid, invoice: { id: ..., issued_at: Thu Sep 27 2018..., url: https://invoice/download }, }, ... }
  • 26. “ Each field in a GraphQL schema is backed by a resolver. 26
  • 27. 27 query { payments { id invoice { id payment { id invoice { payment { invoice { payment { invoice { id issued_at } } ...
  • 28. “GraphQL queries can traverse related objects and their fields, letting clients fetch lots of related data in one request, instead of making several roundtrips as one would need in a classic REST architecture. 28
  • 29. 29 ● Access control must be moved to resolver or data layer (no more middleware) 29 Challenges ● Free data traversing of types and relationships adds more complexity to access control and data fetching ● Request and response must be multiplex (query batching) query { payments(status: paid) { id status } subscribers { id firstName lastName subscribed_at } } { data: { payments: [{ id: ..., status: paid, }], subscribers: [{ id: ..., firstName: James, lastName: Porlante, subscribed_at: ..., }] } }
  • 30. 30 Context Injection async function payments(parent, args, context, info) { const userId = context.user.id const payments = await context.db.getUserPayments({ userId }) return payments } const resolvers = require('./resolvers') const repositories = require('./repositories') // - Data Layer const server = new GraphQLServer({ typeDefs: importSchema('./src/schema.graphql'), resolvers, context: (request) = ({ ...request, db: repositories, user: getUserViaJWT(req.headers.authorization), sentry: Sentry }) })
  • 31. 31 ● Clients don’t rely more on status code, so errors must be parsed and formatted for every query ● Code must be DRY 31 Challenges
  • 32. 32 Resolver Chain + Error Handling import { createResolver } from 'apollo-resolvers'; import { createError, isInstance } from 'apollo-errors'; const UnknownError = createError('UnknownError', { message: 'An unknown error has occurred! Please try again later' }); export const baseResolver = createResolver( //incoming requests will pass through this resolver like a no-op null, (root, args, context, error) = isInstance(error) ? error : new UnknownError() ); const ForbiddenError = createError('ForbiddenError', { message: 'You are not allowed to do this' }); const AuthenticationRequiredError = createError('AuthenticationRequiredError', { message: 'You must be logged in to do this' }); export const isAuthenticatedResolver = baseResolver.createResolver( (root, args, context, info) = { if (!context.user) throw new AuthenticationRequiredError(); } ); const isAdminResolver = isAuthenticatedResolver.createResolver( // Extract the user from the context (root, args, { user }, info) = { if (!user.roles.includes('admin')) throw new ForbiddenError(); } ) // ./src/resolvers/query.ts export default { subscribers: isAdminResolver.createResolver( (root, args, context, info) = { return context.db.getAllSubscribers() } }) }
  • 33. 33 graphql-middleware export const logInput = async (resolve, root, args, context, info) = { console.log(`1. logInput: ${JSON.stringify(args)}`) const result = await resolve(root, args, context, info) console.log(`5. logInput`) return result } export const logResult = async (resolve, root, args, context, info) = { console.log(`2. logResult`) const result = await resolve(root, args, context, info) console.log(`4. logResult: ${JSON.stringify(result)}`) return result } const { logInput, logOutput } = require('./middlewares') const server = new GraphQLServer({ typeDefs, resolvers, middlewares: [logInput, logResult], }) server.start(() = console.log('Server is running on http://localhost:4000'))
  • 34. 34 Schema Directives directive @rest(url: String) on FIELD_DEFINITION type Query { people: [Person] @rest(url: /api/v1/people) } class RestDirective extends SchemaDirectiveVisitor { public visitFieldDefinition(field) { const { url } = this.args; field.resolve = () = fetch(url); } } const schema = makeExecutableSchema({ typeDefs, schemaDirectives: { rest: RestDirective } });
  • 35. 35 Schema Directives from Prisma type Payment { id: ID! @unique status: @default(value: “not-paid”) invoice: Invoice! @relation(name: Payment_Invoice) }
  • 36. 36 Backend Database as a Service
  • 37. 37
  • 39. Patterns 39 ● Root resolvers ● Type Field resolvers ● Context injection ● Apollo Resolvers ● GraphQL Middleware ● Schema directives ● Database / Backend as a service A B S T R A C T I O N Personal flavour and opinion Legacy APIs Project size Complexity Apply depending on Use case 
  • 40. Packages to extend GraphQL native resolvers 40 ● graphql-tools ● apollo-server ● graphql-compose ● graphql-shield ● graphql-middleware ● graphql-sequelize ● mongoose-schema-to-graphql ● ...
  • 41. Resolver Cheat Sheet 41 Auth Authz ORM Datasource Logging Caching Tracing Type Field resolvers Modular resolvers Root resolvers GraphQL Middleware Context injection Schema directives DaaS / BaaS
  • 42. Resolver patterns @ BrikL 42 Auth Authz ORM Data Logging Caching Tracing Type Field resolvers Modular resolvers Root resolvers GraphQL Middleware Context injection Schema directives DaaS / BaaS
  • 43. Resolver patterns @ BrikL 43 Auth Authz ORM Data Logging Caching Tracing Type Field resolvers Modular resolvers Root resolvers GraphQL Middleware Context injection Schema directives DaaS / BaaS Schema
  • 44. Resolver patterns @ Envisioning 44 Auth Authz ORM Data Logging Caching Tracing Type Field resolvers Modular resolvers Root resolvers GraphQL Middleware Context injection Schema directives DaaS / BaaS
  • 45. 45 Thanks! Any questions? Connect, Talk, Hack until 10pm See you in November
  • 47. Credits (Slidetheme) Special thanks to all the people who made and released these awesome resources for free: ● Presentation template by SlidesCarnival ● Photographs by Unsplash 47