Anyone playing around with Nexus.js?

For those of you who haven’t checked it out, Nexus.js is a framework for composing a GraphQL API (types/queries/mutations) that is built to work nicely with Prisma. Nexus provides some nice features that I am enjoying:

  • It provides utility functions for common CRUD operations that eliminates the need to manually write/generate queries, mutations, input types, resolvers, etc. It’s truly magical.
  • It is built on TypeScript, so the code you do write is checked against your schema at compile time.

For the sake of comparison (and fun!) I decided to clone the Redwood Example Blog schema and expose it as a GraphQL API using Nexus.

Nexus allows you to define a query for posts with a single line of code. Here’s an example for the Post type:

t.crud.posts({pagination: true, filtering: true, ordering: true})

This single line of code provisions all the necessary artifacts to provide rich queries for users, including:

  1. Pagination (first, last, skip arguments)
  2. Filtering (Post where input type)
  3. Ordering (Post order by input type)

You can also define create, update and delete mutations easily:

t.crud.createOnePost()

Finally, it’s worth noting how robust these resolvers and input types are. For instance, that single line of code above made it possible for my to craft a mutation that created both a new Post and a new Tag at the same time:

mutation {
  createOnePost(data: {
    title: "Creating a Post and a Tag at the same time!"
    slug: "creating-a-post-and-tag"
    author: "Carter Rabasa"
    body: "Lorem Ipsum"
    tags: {
      create: {
        name: "A new Tag"
      }
    }
  }){
    id
    tags{
      id
      name
    }
  }
}

I have gone ahead and deployed this to Heroku and you can check-out the GraphQL Playground here so folks can poke around and check-out (via the Docs) all the nice bits that Nexus provisions:

https://ancient-island-61569.herokuapp.com/

You can find the code for my deployed Nexus app at the link below.

https://github.com/crtr0/nexus-test

I’d love to hear from anyone else who’s checking out Nexus and hear what you think. I’d especially love to hear if anyone has gotten it to deploy to Netlify!

@crabasa agreed this looks very interesting as I personally have no experience. Being able to have out the box Pagination, Filtering, and Ordering is very attractive. So curious to check out your implementation example. Thanks for sharing!

Question: is there anything in RWJS that Nexus replaces, e.g. Service files, SDL, etc.? I’m sure this will get answered once I look at your code.

Lastly, I know @peterp and @rob worked on integration Nexus with Redwood before my time. Rob especially has some opinions about why it wasn’t a good choice (for RWJS). Might be helpful info regarding tradeoffs and use cases.

I’m not sure “replacing” is the right word for the service/SDL files.

SDL

Nexus just has a different way to defining the GraphQL API that is served. So, instead of an SDL file like this:

export const schema = gql`
  type Tag {
    id: ID!
    name: String
  }

  type Query {
    tags: [Tag]
  }
`

You’d have some TypeScript like this:

schema.objectType({
  name: "Tag",
  definition(t) {
    t.model.id()
    t.model.name()
  }
})

schema.queryType({
  definition(t) {
    t.crud.tags({pagination: true, filtering: true, ordering: true})
  }
})

The benefit of Nexus here is that if you try to define a property for Tag that doesn’t exist in schema.prisma, you will get a compile/IDE errors.

Services

Similarly it doesn’t necessarily replace the service files. If you enjoy the utility of using a single line of code to implement the 4 basic CRUD resolvers, you can do that. But if you want to manually execute arbitrary resolvers for queries/mutations, you can do that too:

t.field('blogsLike', {
      type: 'Blog',
      list: true,
      args: {
        name: schema.stringArg(),
        viewCount: schema.intArg(),
      },
      resolve(_root, args, ctx) {
        return invokeRedwoodServiceFunction(args.name, args.viewCount)
      },
    })
1 Like

We started with Nexus but ended up pulling it out because it felt like it was too much abstraction over the SDL. It’s so nice being able to just read the raw SDL to see what the GraphQL API is. However, Nexus does offer some very nice features that would be great to have. I wonder if there is some way to keep the SDL format but add the power of Nexus’ generators and such with directives or some other syntax. That would be my preference. I just don’t feel like a good enough solution has been invented yet, but I would love to experiment and find one!

2 Likes

Hey @mojombo, thanks for the context.

One thing that might help in the short term is conforming to API that Nexus generates. So, for example, when you use their CRUD helper functions for the Post type , it generates the following SDL:

  type Post {...}

  type PostCreateInput {...}

  type PostUpdateInput {...}

  type PostWhereUniqueInput {...}

  type PostOrderByInput {...}

  type Query {
    post(where: UserWhereUniqueInput!): User
    posts(...): [User!]!
  }

  type Mutation {
    createOnePost(data: PostCreateInput!): Post!
    updateOnePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
    deleteOnePost(where: PostWhereUniqueInput!): Post
  }
`

Of course, it also wires all of that together with resolvers that call the prisma client with the appropriate methods and payloads. But that’s to be expected due to the close relationship between the two teams.

Even in the absence of Nexus, I really like the shape of this API and the flexibility it provides to craft queries and not need to fall back on creating on-off methods.

3 Likes