Emit deprecation warnings with Apollo client
Asked Answered
L

1

10

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?

Lassa answered 1/11, 2017 at 14:10 Comment(4)
I'm thinking that it can be done in a apollo-client middleware?Lassa
I'm also interested in some kind of implementation or tool that does this :)Lampley
@Lampley Added solution below.Lassa
Someone built a pluginLassa
L
3

GraphQL schema directives can be customized. So below is a solution that prints a warning on the server (Edit 2023: And here's a plugin that propagates the warning to the client):

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}`)
})

Lassa answered 10/5, 2020 at 23:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.