question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

API should support adding types to an already existing schema

See original GitHub issue

A user of the Python port of GraphQL.js recently came up with the following question, which I think should be better discussed here:

They are given a schema object that contains an interface (built using SDL). Now they want to programmatically (dynamically) add concrete types implementing this interface to the schema. How would they do that?

Of course, you could instead add the concrete types to the SDL and build the schema from that, or you could instead build a query type and the interface type programmatically, add the concrete types, and then build the schema from the query type. But it would be nice if you could also use the mixed approach, creating the schema first, and then adding the types.

However, adding the concrete types to an existing schema is tricky, because you need to do three things:

  1. Add the type to the _type_map.
    • Ok, this is simple, since you can access the _type_map with getTypeMap().
  2. Add the type to the _implementations_map for the interface.
    • This is is a problem because you cannot access the private _implementations_map or add a new key to this map. We have the getImplementations() method, but if the interface is not yet implemented in the given schema, the returned object cannot be used for updates, and there is no setImplementations() method.
  3. If the schema was already validated, reset the _sub_type_map cache.
    • This is also problematic because _sub_type_map is private and there is no official way to reset it.

So the question is:

  • Should we provide an add_type() method (caring for all of the above) or alternatively, a setImplementations() and some kind of reset() method that would reset the _sub_type_map, so that you can subsequently add types to an already existing schema?

To illustrate the problem, here is the code example from the original issue translated from Python to JavaScript:

// Create a schema with an interface via SDL

const sdl = `
enum Episode { NEWHOPE, EMPIRE, JEDI }

interface Character {
  id: String!
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Query {
  hero(episode: Episode): Character
}
`;

const schema = buildSchema(sdl);

// Add concrete types programmatically

const CHARACTERS = ["Human", "Droid", "Animal", "Fungus", "Alien"];

const characterInterface = schema.getType("Character");
const episodeClass = schema.getType("Episode");
const query = schema.getType("Query");

const const typeMap = schema.getTypeMap();
const implementations = { objects: [], interfaces: [] };
schema._implementationsMap[characterInterface.name] = implementations;

for (const character of CHARACTERS) {
  const concreteCharacter = new GraphQLObjectType({
    name: character,
    interfaces: [characterInterface],
    fields: {
      id: { type: new GraphQLNonNull(GraphQLString) },
      name: { type: GraphQLString },
      friends: { type: new GraphQLList(characterInterface) },
      appearsIn: { type: new GraphQLList(episodeClass) },
      primaryFunction: { type: GraphQLString },
    },
  });
  typeMap[character] = concreteCharacter;
  implementations.objects.push(concreteCharacter);
  const name = character.toLowerCase();
  query._fields[name] = {
    name,
    type: concreteCharacter,
    args: [{ name: "id", type: new GraphQLNonNull(GraphQLString) }],
  };
}

schema._subTypeMap = {};  // need to reset this because we added types

console.log(printSchema(schema));

The code above should print this result.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:3
  • Comments:9 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
yaacovCRcommented, Dec 23, 2021

If I understand correctly the example, however you don’t need mapSchema, you can just use schema.toConfig and recreate the schema with the addition of the new types. Adding concrete types to a Union would require Union type mapping, because unions hold references to their implementation while object and interface types hold references to the interfaces they implement

1reaction
yaacovCRcommented, Dec 23, 2021

The existing way to do that would seemingly be to use the toConfig methods to recreate a given schema programmatically, modified as necessary. Within graphql tools, we have a mapSchema method that provides an easier framework for that, basically a superset of @IvanGoncharov lexicographicallySortSchema .

i think dynamic schemas are very interesting, but I think in terms of the direction so far from the library, it seems like the idea has been to freeze schemas after creation.

maybe it’s to ensure validation can be taken for granted, although of course that flag could be reset as you mention.

would love to hear @IvanGoncharov thoughts!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Adding REST API Support For Custom Content Types
The REST API can create routes for custom post types and custom taxonomies inside of the wp/v2 namespace, using the same controllers as...
Read more >
Schema Registry API Reference | Confluent Documentation
The Schema Registry server can enforce certain compatibility rules when new schemas are registered in a subject. These are the compatibility types: BACKWARD...
Read more >
Editing a schema - IBM
You can edit schemas that have been previously created in various places in your ... OpenAPI 3.0 APIs are supported only with the...
Read more >
Specifying a schema | BigQuery - Google Cloud
Alternatively, you can use schema auto-detection for supported data formats ... Google Standard SQL lets you specify the following data types in your...
Read more >
RESTful web API design - Best Practices - Microsoft Learn
Service evolution. The web API should be able to evolve and add functionality independently from client applications. As the API evolves, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found