# Introducing GraphQL Nexus: Code-First GraphQL Server Development URL: https://www.prisma.io/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5 Published: 2019-02-07 Authors: Tim Griesser Series: Code-first GraphQL server development with Nexus Description: Meet GraphQL Nexus, a code-first library for building GraphQL servers with type-safe schemas and a better developer workflow. In our last post, we outlined the issues with SDL-first GraphQL server development. This week, we're excited to announce [GraphQL Nexus](https://nexusjs.org/), a code-first GraphQL library. A guest post by [Tim Griesser](https://twitter.com/tgriesser). ## Recap: The issues with SDL-first development [#recap-the-issues-with-sdl-first-development] As outlined in the [previous post](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3), SDL-first GraphQL server development has a number of challenges, such as *keeping SDL and resolvers in sync*, *modularizing your GraphQL schema*, and *achieving great IDE support*. Most of the problems *can* be solved, but only at the cost of learning, using and integrating a myriad of additional tools. Today we are introducing a library that implements the code-first approach for GraphQL server development: [**GraphQL Nexus**](https://nexusjs.org/). *** ## Introducing GraphQL Nexus [#introducing-graphql-nexus] ### The best of both worlds: Schema-first & code-first [#the-best-of-both-worlds-schema-first--code-first] In the last article, we developed an understanding for *schema*-first, *SDL*-first, and *code*-first approaches for building GraphQL servers: * **Schema-first**: Upfront schema design is a crucial part of the development process * **SDL-first**: SDL-version of the GraphQL schema is the *source of truth* for the API * **Code-first**: The GraphQL schema is constructed programmatically While being a code-first framework, GraphQL Nexus can still be used for schema-first development. Schema-first and code-first are not opposing approaches: they become even more useful when combined. With Nexus, the GraphQL schema is defined and implemented programmatically. It therefore follows proven approaches of GraphQL servers in other languages, such as [`sangria-graphql`](https://github.com/sangria-graphql/sangria) (Scala), [`graphlq-ruby`](https://github.com/rmosolgo/graphql-ruby) or [`graphene`](https://graphene-python.org) (Python). ### Type-safe, compatible with GraphQL ecosystem & data-agnostic [#type-safe-compatible-with-graphql-ecosystem--data-agnostic] GraphQL Nexus was designed with TypeScript/JavaScript intellisense in mind. It combines TypeScript generics, conditional types, and type merging to provide full auto-generated type coverage. A core design goal of Nexus is to have the best possible type coverage with the least possible manual type annotation. ![Type-safe, compatible with GraphQL ecosystem & data-agnostic](https://www.prisma.io/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/imgs/KMUm6rd.png) Nexus builds upon the primitives of `graphql-js` which makes it largely compatible with the current GraphQL ecosystem. ### Defining and implementing a GraphQL schema with Nexus [#defining-and-implementing-a-graphql-schema-with-nexus] The API of Nexus exposes a number of functions that let you define and implement the building blocks for your GraphQL schema, such as [object types](https://nexusjs.org/docs/api-objecttype), [unions](https://nexusjs.org/docs/api-uniontype) & [interfaces](https://nexusjs.org/docs/api-interfacetype), [enums](https://nexusjs.org/docs/api-enumtype) and everything else you find in [GraphQL's type system](https://spec.graphql.org/June2018/#sec-Type-System): ```ts const User = objectType({ name: 'User', definition(t) { t.int('id', { description: 'Id of the user' }) t.string('fullName', { description: 'Full name of the user' }) t.list.field('posts', { type: Post, // or "Post" resolve(root, args, ctx) { return ctx.getUser(root.id).posts() }, }) }, }) const Post = objectType({ name: 'Post', definition(t) { t.int('id') t.string('title') }, }) ``` ```ts const MediaType = unionType({ name: 'MediaType', description: 'Any container type that can be rendered into the feed', definition(t) { t.members('Post', 'Image', 'Card') t.resolveType(item => item.name) }, }) ``` ```ts const Node = interfaceType({ name: 'Node', definition(t) { t.id('id', { description: 'GUID for a resource' }) }, }) const User = objectType({ name: 'User', definition(t) { t.implements('Node') }, }) ``` ```ts const InputType = inputObjectType({ name: 'InputType', definition(t) { t.string('key', { required: true }) t.int('answer') }, }) ``` ```ts // Definining as an array of enum values: const Episode = enumType({ name: 'Episode', members: ['NEWHOPE', 'EMPIRE', 'JEDI'], description: 'The first Star Wars episodes released', }) // As an object, with a simple mapping of enum values to internal values: const Episode = enumType({ name: 'Episode', members: { NEWHOPE: 4, EMPIRE: 5, JEDI: 6, }, }) ``` ```ts const DateScalar = scalarType({ name: "Date", asNexusMethod: "date" description: "Date custom scalar type", parseValue(value) { return new Date(value) }, serialize(value) { return value.getTime() }, parseLiteral(ast) { if (ast.kind === Kind.INT) { return new Date(ast.value) } return null }, }) ``` The `Query` and `Mutation` types are the so-called *root types* in a GraphQL schema. Nexus provides a shorthand API to define those: ```ts const Query = queryType({ definition(t) { t.field('user', { type: User, nullable: true, args: { id: idArg({ nullable: false }) }, resolve: (parent, { id }) => fetchUserById(id), }) }, }) ``` ```ts const Mutation = mutationType({ definition(t) { t.field('createUser', { type: User, args: { name: stringArg() }, resolve: (parent, { name }) => createUser(name), }) }, }) ``` Once you have defined all of the types for your GraphQL schema, you can use the [`makeSchema`](https://nexusjs.org/docs/api-makeschema) function to create a [`GraphQLSchema`](https://graphql.org/graphql-js/type/#graphqlschema) instance that will be the foundation for your GraphQL server (e.g. `graphql-yoga` or `apollo-server`): ```ts const schema = makeSchema({ // The programmatically defined building blocks of your GraphQL schema types: [User, Query, Mutation], // Specify where the generated TS typings and SDL should be located outputs: { typegen: __dirname + '/generated/typings.ts', schema: __dirname + '/generated/schema.graphql', }, // All input arguments and return types are non-null by default nonNullDefaults: { input: true, output: true, }, }) // ... feed the `schema` into your GraphQL server (e.g. apollo-server or graphql-yoga) ``` `makeSchema` also lets you provide a [prettier configuration](https://prettier.io/docs/en/configuration.html) so that the generated code adheres to your style guidelines 💅 ## Getting started with GraphQL Nexus [#getting-started-with-graphql-nexus] The fastest way to get started with Nexus is by exploring the official [examples](https://github.com/prisma/nexus/tree/develop/examples) or by using the online [Playground](https://nexusjs.org/playground). ### 1) Installation [#1-installation] Since GraphQL Nexus heavily depends on `graphql-js`, it is required as a [peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/) for the installation: ```shell npm install --save nexus graphql ``` ```shell yarn add nexus graphql ``` ### 2) Configuration & best practices [#2-configuration--best-practices] The [best practices](https://nexusjs.org/docs/best-practices) section in the docs contains many instructions regarding the ideal editor setup and hints for structuring Nexus projects. As GraphQL Nexus generates typings *on the fly*, the best developer experience is achieved with a development server that's running in the background as you code. Whenever you save a file, it takes care of updating the generated typings. ### Configuring the development server for TypeScript When using TypeScript, one possible setup is to use [`ts-node-dev`](https://github.com/whitecolor/ts-node-dev) for the development server: ```js npm install --save-dev ts-node-dev ``` ```js yarn add -D ts-node-dev ``` You can then configure an npm script for development in `package.json`: ```json { // ... "scripts": { "start": "...", "dev": "ts-node-dev --no-notify --transpileOnly --respawn ./src" } } ``` ### Configuring the development server for JavaScript When using JavaScript, you can use [`nodemon`](https://github.com/remy/nodemon): ```js npm install --save-dev nodemon ``` ```js yarn add -D nodemon ``` You can then configure an npm script for development in `package.json`: ```json { // ... "scripts": { "start": "...", "dev": "nodemon ./src/index.js" } } ``` ### 3) "Hello World" with `graphql-yoga` [#3-hello-world-with-graphql-yoga] Once you're done with your editor setup, you can start building out your GraphQL schema. Here's what a "Hello World" app with `graphql-yoga` looks like: ```ts import { queryType, stringArg, makeSchema } from 'nexus' import { GraphQLServer } from 'graphql-yoga' const Query = queryType({ definition(t) { t.string('hello', { args: { name: stringArg({ nullable: true }) }, resolve: (parent, { name }) => `Hello ${name || 'World'}!`, }) }, }) const schema = makeSchema({ types: [Query], outputs: { schema: __dirname + '/generated/schema.graphql', typegen: __dirname + '/generated/typings.ts', }, }) const server = new GraphQLServer({ schema, }) server.start(() => `Server is running on http://localhost:4000`) ``` ### 4) Migrating from your SDL-first API [#4-migrating-from-your-sdl-first-api] The [SDL converter](https://nexusjs.org/converter) lets you provide an SDL schema definition and outputs the corresponding Nexus code (without any resolvers): ![SDL converter](https://www.prisma.io/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/imgs/AbkFWNO.png) *** ## Striving for great developer experience [#striving-for-great-developer-experience] The Nexus API has been designed with special attention to developer experience. Some core design goals are: * Type-safety by default * Readability * Developer ergonomics * Easy integration with [Prettier](https://prettier.io) The development server that's running as you build your API ensures that you always get auto-completion and error checks for the schema changes you just introduced. With the new [schema polling feature](https://medium.com/novvum/6c9da4bbd552) in the GraphQL Playground, you GraphQL API will reload instantly as you adjust the schema as well. *** ## Let us know what you think [#let-us-know-what-you-think] We are super excited about [GraphQL Nexus](https://github.com/prisma/nexus/) and hope that you will be too. Feel free to try out Nexus by exploring the official [examples](https://github.com/prisma/nexus/tree/develop/examples) or following the ["Getting Started"-instructions](https://nexusjs.org/docs/getting-started) in the docs. If you encounter any problems, please [open a GitHub issue](https://github.com/prisma/nexus/issues/new) or reach out in our [Slack](https://slack.prisma.io).