GitHub Africa/GraphQL Berlin Meetup + a raffle! 🎁

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello friends and welcome to this special edition of the graphql berlin meetup this is a special edition because we joined forces with github africa to bring you this session my host alex and today we have two speakers very special uh speaker speakers will be eli perkins this presentation unlocking static type superpowers with graphql introspection and myself uh on a top type safe graphql apis with prisma and nexus and we had another speaker lined up for you today kudakwashe however he was feeling unwell and wouldn't be able to join this meetup but stay tuned and host him in future so this meetup we have a raffle and we'll be giving out a copy of designing data intensive applications by martin klepman if you would like to participate and win this a copy of this book submit your in the form that will be dropped in the production so without others time to introduce our first speaker eli so eli is a mobile engineer working on github africa github for ios sorry for that mishap eli has been working with ios since 2010 and has a passion for pixel perfection and loves to teach computers to solve problems so that humans don't have to when he's not writing swift graphql or ruby you will probably find eli brewing coffee and hanging out with his chatty sammy's cut without any further delay i bring you eli hey how's it going y'all um it's good how are you doing well doing well happy to give this talk i'm super excited to chat a little bit more about how we've been using graphql introspection on github to build some really great tools uh and to ship really great awesome uh products to our our developers awesome i'm looking forward to the talk are you ready to present i believe so let me share my screen real quick and we'll get started cool adding it to the stream awesome check it away awesome let's do it well thanks for joining me y'all this talk's called unlocking static type superpowers with graphql introspection i'm eli perkins like alex mentioned i work on github for ios i'm on the mobile tv at github i've been here about a little over two years now and i'm excited to talk a little bit more about some of the fun things that we've been working on graphql has really enabled folks to build some fantastic products by allowing developers to query for just the properties that they need when they need them we often learn how to work with a given graphql server by using tools like graphical to explore the schema or downloading the schema directly to use locally with other tools like apollo's code gen or graphql code generator but what is it that we're really downloading how is it that graphical or apollo explorer or other tools know exactly what fields are available on each type when we download a graphql schema how did the server put together that schema for us what is it that it actually did there and how do the types from a graphql schema get turned into types in say typescript or in swift or in kotlin or in java or other type safe languages and if folks other folks have built cool things like these in the past what cool things can i build with a little bit more knowledge about graphql schemas about graphql types and more at github we really enjoy digging into the nitty gritty of graphql we use graphql to power how developers across the globe connect whether that's on github.com or on github mobile or through third-party developers like you who use our graphql api to build new technologies and new technologies and communities today i want to dig into a really interesting topic taking a look at graphql introspection and how the type system defined within graphql can be leveraged to solve problems in a unique way we'll dig briefly into how github cli uses introspection at runtime to serve not only our customers on github.com but our github enterprise users as well and lastly we'll take a peek at how using introspection and graphql schemas as an input to other tooling helps our mobile team ship new features to many customers automatically so let's dig in what is graphql introspection graphql introspection is how we ask a given server about its schema and how we ask that schema about its types its queries its mutations subscriptions directives and more introspection quite literally means examining or observing within so with graphql introspecting is no different we look within to see what's inside of a given server what's inside of a given schema or what's inside of a given type there are two main ways to do introspection with graphql and both of them involve querying a graphql server directly schema is how we introspect graphql server from the root of the server think queries and mutations while type is how we ask a graphql server about one specific object or one specific interface at a time note how these two fields are prefixed with two underscores indicating their almost private nature let's start by taking a look at the schema field the schema field gives us an entry point into our graph asking the graphql server for its query type will offer up the type that our whole schema can be queried against this might seem obvious at first we write a lot of our queries starting with the query field similar fields for mutations and subscriptions also exist defining the core groups of ways that any given developer can interact with a graphql server the schema field also allows for asking a graphql server for all of the types that it has to offer this is the bread and butter of graphql after all defining the types along the graph this is what gives us our type safety as we're developing applications further information beyond just queries and mutations can also be fetched from the via introspection as well perhaps your server defines some unique directives that can be used within your graphql queries the directives field on the schema will let you know exactly what directives are available for you to use with a given server here's an example of hitting the github graphql server to get the include or skip directives knowing that we can execute these against the github api server that's just a brief overview of some of the properties that exist on the schema type now that we've grabbed a list of all of the types that our server support supports let's look a little at one single type using the type field type allows for querying one specific type given that you know the name of that type already in this example we can query against the repository type and see what is the description of that specific type types include fields as well now we're starting to see how the graph is actually built up here we've queried for all of the fields available on the repository type it even let us know which fields will be non-nullable or knowable as well beyond just the scalar type that backs that field types can also include descriptions this is how graphql is able to self-document the types in the field that it exposes by baking the document documentation into the query language itself so that's our two minute tour of the two and two of the entry points into graphql introspection but there's one more introspection field that you might already be familiar with and might be using today and that's type name type name exists on every object within the graphql schema you might have used this in the past to determine what the concrete typo is of an object that you've received perhaps from a union or from an interface fun fact since schemas are a type as well we can query for the schema field that we started taking a look at with the type field as well supplying that underscore underscore schema for the type name here brings us right back to the type that we started looking at i could dig more into each of these types going field by field but i'm not here to read documentation to you i want to show you some of the cool things that you can actually do with introspection now that we know a little bit more about how to ask a server for its types let's come up with some questions that to have about a graphql schema itself given that we can query for all types against the given schema that a server supports let's ask the github graphql api how many different types that it exposes as of this talk that number was right around 1182 this is using the github cli to query against this a great way to execute queries quickly from your command line or perhaps that you want to dump an entire graphql server's schema you can build graphical 2.0 or perhaps an app to explore graphql schemas in vr we could write a request a recursive query ourself to ask every type for all of its fields and all of those types of fields and all of those fields types and all of those types fields and so on and so on but much of the graphql community has set along this specific query for introspecting the entire graphql schema within the graphql js reference implementation on graphql.org the query itself isn't too complex honestly coming in at about 100 lines of code give or take a few conditionals executing this query will give you all information about every type every mutation every query every directive everything about a graphql schema running it against github's graphql api is no joke this introspection query takes on takes returns a lot of information maybe too much for a human but now that we've seen all of this let's start putting this type system these type definitions this data to use using computers here's one of my favorite classic examples of how we're using graphql introspection at github to help our developers out we add things to our graphql schema tweak things deprecate things a bunch sometimes weekly sometimes even more one way that we help keep developers informed about these changes are through the change log published on our docs page this calls out new graphql fields that get added as soon as they're deployed so how does this work the process for this is publicly accessible within our docs repo and is essentially a two-step process every day our docs repo kicks off the github action workflow to run this process it starts by downloading the current inspection introspection from our graphql api and comparing it to the previous one that the workflow last ran against it uses the dip of these two schemas the previous one and the current one to find additions deprecations to indicate feature previews or other upcoming changes all of this is powered by dumping the graphql schema via graphql introspection since graphql schemas are data and types that we can work with determining the difference between two schemas is no different than diffing two objects or two json structures with a little bit of code we can teach machines how to help us humans how to build better products with graphql so far we've looked at how you can query a graphql server for its whole schema or how a developer might poke at a specific type we might be familiar with downloading whole schemas to do some work on with them but let's dig in a little bit more let's take a deeper look at some other ways that graphql introspection might be helpful as a more precise tool during the runtime of an app github cli brings github right to your terminal a good chunk of github cli relies on graphql to fetch the data that you need about a given pull request or a submitted review for that pull request that you just reviewed from your terminal at github we love graphql and the cli gives me my favorite way to access our graphql api with ease it's one of my favorite ways to quickly query our graphql api handling authentication for me or even giving me an inconv even giving me a convenient way to connect connect graphql api requests or other data within command line tools that i use on my day-to-day one feature of the cli that's quite neat is the ability to see the status of all pull requests on a repo this includes things like showing the status check state whether my ci checks are failing as well as indicating prs that are open as seen in green here or in draft as seen in in gray here as well a graphql query to fetch this information is pretty straightforward we can ask the graph for some properties pulling out the draft status as well as pr status status checks from the commit these features were able to be added to our cli quickly and efficiently thanks to graphql and github's graphql api by adding the is draft field to our query i've got just the data i need to get going however if i ask our graphql api for some field that doesn't exist things start to get ugly perhaps i want to see if dark mode is enabled for a given pr if this field doesn't exist on the on my type in my schema my query is not going to be happy errors like this lead to no data coming back as the query cannot even be processed by our servers meaning our resolvers don't even get a chance to run this can lead to really tough issues for our users if we as developers write invalid graphql queries our users will end up with blank screens errors or even crashes at runtime issues like this aren't so uncommon for us here at github but we've looked on how to try to fix these when we develop new features it's often easiest for hubbers to develop against github.com or what we lovingly call the monolith or dot com using code spaces any developer can get their own mini github.com up and running to develop against emulating a similar environment as to what will end up in production however github enterprise is one of the best ways to bring the to bring developers to bring experienced developers that experience that developers know and love to enterprise scale companies who need more security like vpn access or on-site databases just because a new feature we've built works against github.com doesn't mean that it will work against github enterprise right out of the box this product has a different release cycle and some enterprise organizations might not upgrade their own servers very often as such we need to build our apps that talk to github graphql apis with a long tail of releases in mind supporting all of our customers not just those on github.com so how can we leverage graphql introspection to do that one awesome way that our cli team came up with is dynamic queries by executing a graphql introspection request for only specific types our cli is able to determine if a given server supports a specific feature or not it can dynamically change the query that's executed in order not to throw errors at runtime by removing fields that are unsupported by a given graphql server we can avoid executing queries that we know will fail at runtime this also has the upside of supporting future versions of github enterprise as well which might support these fields in the future within the cli a request for the fields of a specific type are requested using the type field on our schema in this case we've asked the commit and the pull request types a little bit more about the fields that they support we can check to see if isdraft is in here or if the status check rollup field exists as well since this returns all fields that these types support we can look for specific ones that we're about to query for in the list of fields that are returned on github.com these fields should always exist so we can query for them no problem and on github enterprise we can omit these fields from our query allowing this query to be executed against these servers without throwing errors for undefined fields where before these fields might cause errors using dynamic queries and introspection we can omit them if the server does not support them and allow our queries to succeed without error there are several different commands within the github cli that use this approach today using introspection as feature detection enabling the cli to gracefully degrade its feature set when a given graphql server might not support that feature it's a really great concept and i encourage you to go take a look at it so we've talked a little bit about how a schema from introspection can be used directly and about how introspection can be used at runtime as feature detection but i want to talk about one more thing that we've actively been working on within the mobile team github mobile is the perfect use case for graphql by requesting just the information needed by the app we can save our users bandwidth and cell phone batteries with graphql executing slim efficient queries our mobile team loves graphql too here's a quick overview of all of the queries mutations fragments in the ios app the lines between fragments are shared between queries you can see there's a lot of fragments shared within our code base mainly due to core components like user list items or repo list items appearing in many places within the app that's a lot of graphql here and similarly to the cli our codebase supports github enterprise server as well our original implementation of this within the mobile apps was to support github enterprise server a bit naively we duplicated queries as needed for github enterprise however at times this meant duplicating entire trees of queries and fragments which created a lot of code maybe too much code our mobile team has been using apollo on both ios and android to help turn our graphql queries fragments and mutations into executable swift and kotlin code the type safety that apollo gives our code bases has allowed us to build features rapidly and safely but it hasn't been without its downsides let's take a look at one specific example using apollo for ios within the code base looks something like this a developer writes a query for their feature using plain old graphql syntax in a graphql file apollo's codegen tool uses the graphql schema to turn that query document into swift types allowing that query to be executed and parsed with type safety our developers then use the code generated by apollo to build their features pretty straightforward however if we end up targeting multiple graphql schemas and have multiple graphql documents for each schema then we end up with not only multiple graphql files too but also multiple swift types which them themselves can sometimes be duplicated this leads to developers hacking together some sort of semblance of versioning by appending version names to the query it's not great it worked fine for us to get the initial support of github enterprise out to our customers and unblock them from using the mobile app but i think we can do better just like our cli counterparts we had to consider how to gracefully degrade the app when a given github enterprise server didn't support fields that we might be querying for on github.com however unlike our cli counterparts given the number of queries that our app makes and how our codebase utilizes fragments to co-locate data requirements for their views doing introspection checks at runtime from our users mobile devices on mobile networks didn't seem like a scalable solution we'd be spending a lot of battery and a lot of our customers data on their mobile devices to do these runtime checks we reached through a tool to help us one that we had already been using internally for github for some time and that's graphql ruby graphql ruby is a ruby gem with a fantastic set of bindings around graphql asts resolvers craftql primitives and other graphql utilities graphql ruby is what we use to power the graphql github graphql api ever fired up a graphql request to a github graphql api yup that response was powered by graphql ruby and our approach looks something like this to use graphql ruby we wanted developers to be able to write one graphql query for all schemas we took a look at the different ways that graphql changes might affect our app and came up with an approach to use graphql introspection allowing users to write one query for all schemas from here we would code gen separate graphql queries for each schema this meant that one graphql query could turn into n number of graphql queries in our case one query for github.com one query for github enterprise 3.0 one query for github enterprise 3.1 from here we would then cogen one specific interface for any schema that our app supports making building features for github.com and github enterprise quick and easy this meant that product engineers only had to consume one interface rather than n number of interfaces or three different interfaces let's take a look let's try to visualize this pipeline a little bit and see how this might look so starting with our graphql documents and all of the different schemas that we support we built a tool with graphql ruby ruby to build what we call our graphql pipeline starting with a single set of graphql documents and multiple schema definitions we can use graphql ruby to begin to rewrite queries for each different server that we support using the results of graphql introspection and a little bit of ahead of time graphql ast parsing we can decide which fields are supported by each schema before the code is ever run on our user's devices however this approach still leaves us in a similar place as before if we execute apollo against each schema we'll generate three different sets of swift files too which doesn't make consuming these queries any easier for our product engineers and that's where the last step comes in using a little bit more tooling we created a swift tool that parses the code generated by apollo and creates one umbrella module for accessing any query for a given graphql server this allows developer to consume only one interface rather than needing to worry about three distinct ones let's quickly illustrate this with an example let's take this query beginning with a simple query let's say that users can only enable automerge on github.com and only upload videos on github.com and ghes 3.1 our query rewrite on rewriter will use the introspection of each schema along with a bit of ast parsing to write out three separate graphql documents the result is three separate queries each of which are guaranteed to succeed for each of these different github api versions from here we can execute apollo's swift code gen which will turn our graphql documents into three separate swift types and files that our app can then execute we see there's a bit of duplication here so let's see how we can fix that to make this easier for our product engineers our type gen then creates a generic anonymous interface for all three of these types exposing optional values for those which might not be available in all graphql schemas that our app supports this approach means that our team can create queries that work for any github graphql api without needing to write explicit introspection checks at runtime the end result is a much better product for our customers this approach is still something that we're iterating on today but we've found the results to be quite promising just another example of how graphql introspection can be used to build better products so let's recap we took a look at what graphql introspection is which is looking within we took a look at introspection at runtime how we can execute queries to decide which features to enable or disable to prevent errors from our queries at runtime and lastly we took a look at introspection as an input to other tooling how we might use graphql asts and graphql types to build type safety for all of our products i want you to kind of consider these part of your tool belt don't reach for graphql introspection to solve every problem but realize how you can use graphql introspection to build better tools and to build better products if you want to learn anything more about what we talked about today go check out these different uh links here in our slides there's some really great tools that are out there to use graphql introspection and do some really awesome things and i want to say thank you so much for having me today it's been a pleasure talking thank you thank you eli that was really insightful i enjoyed that yeah and learning all about i got really taken a deeper look into it and this was like the perfect opportunity so i'll go ahead and if there are any questions in the chat i'll go ahead and forward them to you but at the moment it's they are none um [Music] yeah so far no questions for it but thank you for your talk it was very insightful awesome thank you so much for having me alex and i'm really looking forward to your talk as well anytime yeah uh cool i'll go ahead and take you off the screen share my slides [Music] hopefully they're more and cross fingers crossed that that goes well so yeah so let's get started in this presentation we'll be talking safe graphql api prisma and nexus and i will it is split into three different sections graphql schemas and then the last section is nexus and prisma so let's get started graphql server is made up of two components the server or the graphql server which is responsible for serving the api to your end users and the schema which is responsible for describing the shape of your data and all the operations that are going to go in it and take a keen a look at the graphql schema which is made up of two more things it seems that this is going to be a list oriented sort of talk but what the rest of it has in store for us so it's composed of type definitions and resolvers the type definitions describe the operations and shape of your data while resolvers at the actual implementation of your type definitions so what would a graphql schema look like in this example we have two type definitions the user type which contains two fields which is the i type id the exclamation mark denotes that it is non-nullable and the name field which is of type string that is nullable we also have a query type with with a user query that returns an array of users it's important to note that eeps have their own resolver functions that will be responsible for fetching and returning the data so what do you like about graphql is that it encourages a schema driven development that that pushes you to think understand the shape of your data and then you can implement the functionality for them so when you're working with graphql there are mostly there are two common appro defining your schemas we have the schema first approach in which you define your schema using natural language which you'd have and in this approach is beginner friendly and fairly easy or easy to get started with you can read it and you can understand it the downside however is that it's error prone because you'd have to keep your definitions and your resolvers in sync which can also be tedious and you sometimes difficult to debug and the second approach is the code first of having your type definition separate from your resolvers you would define the resolvers in the same spot as your code which would eventually generate the schema or the yeah your ski belt returns for you so when adding database access to your graphic you would have two schemas which you would have to keep in sync the first one is the graphql schematics and the database schema another challenge that comes up from this is that you would have to hide some fields that you wouldn't like to be exposed in your graphql schema such as the passwords fields so so how would you manage them so we'll cover a basic introduction of prisma and what it is and prisma is a next generation types of ram for node.js and works with javascript and typescript we have a go version that is also in preview it works with sqlite mysql a sql server and mongodb that are in the preview and prisma has two value propositions to boost your productivity by letting developers query data in natural and familiar ways and increase the confidence with type safety auto completion and a robust api prisma consists of three components rather the prismaclient migrate and studio prismaclient is auto-generated rm migrate prisma migrate is a declaration and migrations tool and it allows you to allows prismas prisma migrate uses prisma schema changes to auto generate a fully customizable sql with schema migrations and finally prisma studio modern intuitive and easy to use some graphical user interface for your database so with prisma we have schema which is a whole single source of truth for your database schema and application models it's almost simply resembles the graphql schema but it is not a graphql schema it enables intuitive and declarative data modeling and provides the foundation for type safety that prisma provides so in this model we are going to have a user the user model is the one that is going to map to a table name in your database in this model we will also have the id field which is an of type integer and the id tag for getting the actual name right now is a primary key that will will auto increment the value and we'll also have an email field which will be of type string and nick index and finally a name field that is optional and denoted by the question mark uh so this sql migration that would be generated on running prisma migrate dev would be this exactly and this will create a database schema in your database and yeah that that would map in your database so let's take a look at how relate would be modeled using prisma so uh in this example we're going to define a one-to-many relationship between the user and posts it means this that a single user can have many posts or many posts can belong to a single user a couple of things to note in this example is that the author id represents a foreign and all posts in user and author in post are relation fields that are used to access the relations they're not created you can think of them as virtual fields because they're edited in the database because only the auth id is necessary in this example so with the relation defined you can generate the following migration using prism and you can do this using the prisma migrates dev command is sorry for jumping too quickly but this is this sql that is generated based on the prisma schema that we just did so the following shows a prismarine that will be that creates a use to a related post and as i mentioned before prisma provides two propositions the autocompletion and the queries that are not classes to avoid modeling objects the plant exposes that return plain old objects we it it provides a type sales query that can be validated at so you may notice that they attempt to set the email to an integer which immediately creates a type error and this also clearly denotes you feedback using so and with prisma studio you can simply type npx prisma studio in your terminal to have a graphical user interp interface for your database that you can now create edits and rows in your data so here the example snippet shows you how you can related posts edit a post and create a new post that is also associated to that user so and the final bit is going to be merging graphql with prisma so it's a good time to introduce nexus what is nexus nexus provides you a way to define your schema using the code first approach in the node.js ecosystem could also mention that nexus isn't the only library that you can use we have other tools like type graphql prisma and that are pretty good alternatives to this so but nexus is just for this talk um nexus is data agnostic and you can use it with any data access layer and works with your graphql server of choice whether that would be fastify with mercurius apollo express i mean happy name it and it will be able to it should be what so when getting started with graphql there's usually a lot of cognitive overhead to learn about the tool so with the schema fast approach you would have to rely on the tooling for each of these problems so for example some of the challenges that you may exhibit you may face is that you don't get the feedback when defining your schema like you may make a typo and it won't be picked up in the resolvers when when defining a resolver or you may make a field and in the resolver it's available so this creates some inconsistency and sort of difficult to solve when using the schema fast approach so nexus is typesif as i mentioned out of the box and i think i can go ahead and present a demo of how it works give me a moment to share reshare my screen as it's a live demo hoping everything break yeah so i'll go ahead and share the screen so in this example i will go ahead and stop the server and have to start the server and indexes this example i have a mutation that is called a sign up user and in this mutation we it returns it's of an unnulable type that returns a user i find a user up here not exactly there we've defined the user type that contain a few fields the id field which is not nullable the name that's nullable that's not nullable and also the post to denote the relations so in our mutation i made an intentional typo to call this email is not sorry um the email field which is from prisma the email field is a typo and as we can see here the property here i think email is missing a contact error sometimes typescript errors are a little um verbose so in this case if i modify this to email and which from the type safety from prisma it works and we have a graphql server running and this is sort of from the major of nexus and prisma where you get the types from prisma that are also used when you work with nexus nexus works is that it provides a mix schema function i'm going to jump to it a mix schema function that works in um go ahead and stop screen and reshare my slide [Music] so how it works is that nexus has a concept called reflection what this refers to is that when make schema is called which was at the bottom when creating generating the where we put together all the types and the graphql types and maybe typescript types is that it generates a couple of artifacts one is graphql schema and secondly it generates the typescript types that are picked up by vs code and used to formation and type safety so it didn't show you the sdl file that is generated but that is also created when you use nexus and the next the mix schema function is responsible for this so i uh sorry for the demo this was a little disorganized sorry so that was so you can also uh when i change the email field i'm forgetting the name of the error that we made the email field email the type area was resolved you can go ahead a step ahead further and use nexus prisma however it's currently in preview and not completely complete not it's still in preview so you can't really use it in production but it would help you automate defining your graphql type definitions for example the post and the user so uh that is the end of my talk i will be receiving any questions and i hope you found the talk useful [Music] so yeah so uh do we have any questions in the chat so far i can't see any yet so yeah and as we mentioned we have had a raffle and go ahead and present the slides again for the raffle sorry trying to get my screens in order so sharing now [Music] so and the lucky winner of our raffle is adesola adeshina congratulations we will get in touch with you with the email pro email address you provided in the type form and that is all see you in the next meet up [Music] cool uh oh we have a question so how do nexus and type graphql compare so nexus follows sort of like a functional approach towards defining a schema while type graphql uses an object-oriented approach using decorators to define your schema to annotate your schema yes any further i hope that answers your question oh thank you are there any further questions cool um that will be all for today folks see you on the next one
Info
Channel: Prisma
Views: 185
Rating: undefined out of 5
Keywords:
Id: 0MErEyuibXM
Channel Id: undefined
Length: 45min 14sec (2714 seconds)
Published: Mon Nov 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.