@ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml...

48
3/6/2018 Spectacle Presentation http://localhost:3000/#/6?export 1/48

Transcript of @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml...

Page 1: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 1/48

@chrisbiscardi

PARALLELIZINGPRODUCT DEVELOPMENT

WITH GRAPHQL

Page 2: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 2/48

�CHRISBISCARDI

honeycomb.iocoffee@chrisbiscardibiscarch

Page 3: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 3/48

APPLICATIONARCHITECTURE

Page 4: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 4/48

Page 5: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 5/48

Page 6: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 6/48

Page 7: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 7/48

Page 8: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 8/48

SCHEMA DEFINITION LANGUAGE

Page 9: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 9/48

Page 10: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 10/48

Queries

drafts

title

{

{

}

}

Page 11: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 11/48

Results

{

"data" {

"drafts": [{

"title": "Solving World Hunger"

}]

}

}

Page 12: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 12/48

blog schematype Post

String

String

DateTime

Int

Blog

type Blog

String

String

String

Post

{

id: !

title: !

publishedAt: !

likes: ! @default(value: 0)

blog: @relation(name: "Posts")

}

{

id: !

name: !

description: ,

posts: [ !]! @relation(name: "Posts")

}

Page 13: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 13/48

Arrays

Post

type Post { Stringid: ! Stringtitle: ! DateTimepublishedAt: ! Int likes: ! @default(value: 0) Blog blog: @relation(name: "Posts")}type Blog { Stringid: ! Stringname: ! Stringdescription: ,

}posts: [ !]! @relation(name: "Posts")

Page 14: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 14/48

DIRECTIVESEVERYTHING ELSE

Page 15: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 15/48

RESOLVERS

Page 16: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 16/48

Trivial ResolversHuman

obj args context

obj name

: {

name( , , ) {

return .

}

}

Page 17: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 17/48

Async Resolversobj args context

context db args id

userData userData

human( , , ) {

return . .loadHumanByID( . ).then(

=> new Human( )

)

}

Page 18: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 18/48

directive on FIELD_DEFINITION

type Query

String

Directive Resolvers@upper

{

hello: @upper

}

Page 19: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 19/48

next src args context

str

str

str

str

Directive Resolversupper( , , , ) {

return next().then(( ) => {

if (typeof( ) === 'string') {

return .toUpperCase();

}

return ;

});

}

Page 20: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 20/48

SCENARIO 1

A New Product

Page 21: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 21/48

Page 22: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 22/48

Page 23: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 23/48

mysql query

accounts

posts id authorId

id ${obj id}

isPublished

${args skip}

Resolving with SQLreturn . (`SELECT

"user"."id" AS "id",

"posts"."id" AS "postId",

"posts"."title" AS "postTitle",

"posts"."body" AS "postText",

"posts"."tags" AS "postTags",

"posts"."created" AS "postCreated",

FROM AS "user"

LEFT JOIN ON "user". = "posts".

WHERE "user". = .

AND = 1

LIMIT . , 1000`)

Page 24: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 24/48

obj args ctx info

ctx prisma query

where

author id obj id

isPublished

skip args skip

info

SQL with PrismapublicPosts( , , , ) {

return . . .posts(

: {

: { : . },

: true,

},

: . ,

// enables schema stitching

)

}

Page 25: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 25/48

prisma init➜ prisma init full-03

? How to set up a new Prisma service?

Minimal setup: database-only

❯ GraphQL server/fullstack boilerplate (recommended)

Page 26: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 26/48

prisma init➜ prisma init full-03

? How to set up a new Prisma service?

Running $ graphql create ...

? Choose GraphQL boilerplate project:

❯ node-basic Basic GraphQL server (incl.

database)

node-advanced GraphQL server (incl. database &

authentication)

typescript-basic Basic GraphQL server (incl.

database)

typescript-advanced GraphQL server (incl. database &

authentication)

react-fullstack-basic React app + GraphQL server (incl.

database )

Page 27: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 27/48

prisma deploy[graphql create] Running boilerplate install script...

Running $ prisma deploy...

? Please choose the cluster you want to deploy "full-03@dev"

to

prisma-eu1 Public development cluster

prisma-us1 Public development cluster

❯ local Local cluster (requires Docker)

Page 28: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 28/48

prisma deployChanges:

Post (Type)

+ Created type `Post`

+ Created field `id` of type `GraphQLID!`

+ Created field `isPublished` of type `Boolean!`

+ Created field `title` of type `String!`

+ Created field `text` of type `String!`

+ Created field `updatedAt` of type `DateTime!`

+ Created field `createdAt` of type `DateTime!`

Applying changes 1.1s

Hooks:

Importing seed dataset from `seed.graphql` 498ms

Writing database schema to `src/generated/prisma.graphql`

0ms

Page 29: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 29/48

tree . �I node_modules➜ tree . -I node_modules

.

├── README.md ├── database │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated │ │ └── prisma.graphql │ ├── index.js │ └── schema.graphql └── yarn.lock

3 directories, 9 files

Page 30: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 30/48

Schematype Post

ID

Boolean

String

String

{

id: ! @unique

isPublished: ! @default(value: false)

title: !

text: !

}

Page 31: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 31/48

Seeds

createPost

id

createPost

id

createPost

id

mutation {

first: (data: {

title: "Hello World"

text: "This is my first blog post ever!"

isPublished: true

}) {

}

second: (data: {

title: "My Second Post"

text: "My first post was good, but this one is better!"

isPublished: true

}) {

}

third: (data: {

title: "Solving World Hunger"

text: "This is a draft..."

isPublished: false

}) {

}

}

Page 32: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 32/48

playground➜ yarn playground

yarn run v1.3.2

$ graphql playground

Serving playground at http://localhost:3000/playground

Page 33: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 33/48

playgroundbrew cask install graphql-playground

Page 34: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 34/48

Page 35: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 35/48

Updatingtype Post

ID

Boolean

String

String

String

{

id: ! @unique

isPublished: ! @default(value: false)

title: ! @deprecated

title2:

text: !

}

Page 36: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 36/48

Updating➜ yarn prisma deploy

Changes:

Post (Type)

+ Created field `title2` of type `String`

Applying changes 1.1s

Your GraphQL database endpoint is live:

HTTP: http://localhost:4466/full-03/dev

WS: ws://localhost:4466/full-03/dev

Page 37: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 37/48

SCENARIO 2

Frontend

Page 38: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 38/48

graphql-faker

Page 39: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 39/48

type Person

String firstName

String

Faker Directives{

name: @fake(type: )

gender: @examples(values: ["male", "female"])

}

Page 40: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 40/48

Page 41: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 41/48

Apollo Boostapollo-clientapollo-cache-inmemoryapollo-link-httpapollo-link-errorapollo-link-stategraphql-tag

Page 42: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 42/48

link-state withClientState

cache

stateLink

cache

resolvers

Mutation

updateNetworkStatus _ isConnected cache

data

networkStatus

__typename

isConnected

cache data

import { } from 'apollo-link-state';

// This is the same cache you pass into new ApolloClient

const = new InMemoryCache(...);

const = withClientState({

,

: {

: {

: ( , { }, { }) =>

{

const = {

: {

: 'NetworkStatus',

},

};

.writeData({ });

return null

},

},

}

});

Page 43: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 43/48

SCENARIO 3

Go is Awesome!

Page 44: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 44/48

src/schema.graphql

type Query

Post

Post

post ID Post

type Mutation

createDraft String String Post

deletePost ID Post

publish ID Post

# import Post from "./generated/prisma.graphql"

{

feed: [ !]!

drafts: [ !]!

(id: !):

}

{

(title: !, text: ):

(id: !):

(id: !):

}

Page 45: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 45/48

Query

PostsID

PostID

PostsConnectionID

NodeID

PostWhereInput

AND PostWhereInput

OR PostWhereInput

ID

Id_not

Id_in

Id_not_in

Id_lt

gqlgen -out generated.go -package maintype struct {

int

int

int

int

}

type struct {

[]

[]

*string

*string

[]string

[]string

*string

}

Page 46: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 46/48

Page 47: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 47/48

[presentation]: Spectacle[diagrams]: whimsical.co

CREDITS

Page 48: @ D 00 0%Y%5 - QCon London 2020€¦ · │ ├── datamodel.graphql │ ├── prisma.yml │ └── seed.graphql ├── package.json ├── src │ ├── generated

3/6/2018 Spectacle Presentation

http://localhost:3000/#/6?export 48/48

Q & A