Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emit deprecation warnings with Apollo client

Background

We are working on a fairly large Apollo project. A very simplified version of our api looks like this:

type Operation {
    foo: String
    activity: Activity
}

type Activity {
    bar: String
    # Lots of fields here ...
}

We've realised splitting Operation and Activity does no benefit and adds complexity. We'd like to merge them. But there's a lot of queries that assume this structure in the code base. In order to make the transition gradual we add @deprecated directives:

type Operation {
    foo: String
    bar: String
    activity: Activity @deprecated
}

type Activity {
    bar: String @deprecated(reason: "Use Operation.bar instead")
    # Lots of fields here ...
}

Actual question

Is there some way to highlight those deprecations going forward? Preferably by printing a warning in the browser console when (in the test environment) running a query that uses a deprecated field?

like image 341
worldsayshi Avatar asked Nov 01 '17 14:11

worldsayshi


People also ask

How do you fix a deprecation warning?

To fix all deprecation warnings, follow the below steps: Replace update() with updateOne() , updateMany() , or replaceOne() Replace remove() with deleteOne() or deleteMany() . Replace count() with countDocuments() , unless you want to count how many documents are in the whole collection (no filter).

What are deprecation warnings?

Deprecation warnings are a common thing in our industry. They are warnings that notify us that a specific feature (e.g. a method) will be removed soon (usually in the next minor or major version) and should be replaced with something else.

How do I get error messages from GraphQL?

The standard error handling mechanism from GraphQL with return a JSON containing: a data key which contains the data corresponding to the GraphQL operation (query, mutation, subscription) invoked and. an errors key which contains an array of errors returned by the server, with a message and location.

How do you update the Apollo Client cache after a mutation?

If a mutation updates a single existing entity, Apollo Client can automatically update that entity's value in its cache when the mutation returns. To do so, the mutation must return the id of the modified entity, along with the values of the fields that were modified.


1 Answers

So coming back to GraphQL two years later I just found out that schema directives can be customized (nowadays?). So here's a solution:

import { SchemaDirectiveVisitor } from "graphql-tools"
import { defaultFieldResolver } from "graphql"
import { ApolloServer } from "apollo-server"


class DeprecatedDirective extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field ) {
    field.isDeprecated = true
    field.deprecationReason = this.args.reason

    const { resolve = defaultFieldResolver, } = field
    field.resolve = async function (...args) {
      const [_,__,___,info,] = args
      const { operation, } = info
      const queryName = operation.name.value
      // eslint-disable-next-line no-console
      console.warn(
      `Deprecation Warning:
        Query [${queryName}] used field [${field.name}]
        Deprecation reason: [${field.deprecationReason}]`)
      return resolve.apply(this, args)
    }
  }

  public visitEnumValue(value) {
    value.isDeprecated = true
    value.deprecationReason = this.args.reason
  }
}

new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    deprecated: DeprecatedDirective,
  },
}).listen().then(({ url, }) => {
  console.log(`🚀  Server ready at ${url}`)
})

This works on the server instead of the client. It should print all the info needed to track down the faulty query on the client though. And having it in the server logs seem preferable from a maintenance perspective.

like image 103
worldsayshi Avatar answered Oct 01 '22 02:10

worldsayshi