UNPKG

2.76 kBJavaScriptView Raw
1// addTypes uses toConfig to create a new schema with a new or replaced
2// type or directive. Rewiring is employed so that the replaced type can be
3// reconnected with the existing types.
4//
5// Rewiring is employed even for new types or directives as a convenience, so
6// that type references within the new type or directive do not have to be to
7// the identical objects within the original schema.
8//
9// In fact, the type references could even be stub types with entirely different
10// fields, as long as the type references share the same name as the desired
11// type within the original schema's type map.
12//
13// This makes it easy to perform simple schema operations (e.g. adding a new
14// type with a fiew fields removed from an existing type) that could normally be
15// performed by using toConfig directly, but is blocked if any intervening
16// more advanced schema operations have caused the types to be recreated via
17// rewiring.
18//
19// Type recreation happens, for example, with every use of mapSchema, as the
20// types are always rewired. If fields are selected and removed using
21// mapSchema, adding those fields to a new type can no longer be simply done
22// by toConfig, as the types are not the identical JavaScript objects, and
23// schema creation will fail with errors referencing multiple types with the
24// same names.
25//
26// enhanceSchema can fill this gap by adding an additional round of rewiring.
27//
28import { GraphQLSchema, isNamedType, isDirective } from 'graphql';
29import { getObjectTypeFromTypeMap } from './getObjectTypeFromTypeMap.js';
30import { rewireTypes } from './rewire.js';
31export function addTypes(schema, newTypesOrDirectives) {
32 const config = schema.toConfig();
33 const originalTypeMap = {};
34 for (const type of config.types) {
35 originalTypeMap[type.name] = type;
36 }
37 const originalDirectiveMap = {};
38 for (const directive of config.directives) {
39 originalDirectiveMap[directive.name] = directive;
40 }
41 for (const newTypeOrDirective of newTypesOrDirectives) {
42 if (isNamedType(newTypeOrDirective)) {
43 originalTypeMap[newTypeOrDirective.name] = newTypeOrDirective;
44 }
45 else if (isDirective(newTypeOrDirective)) {
46 originalDirectiveMap[newTypeOrDirective.name] = newTypeOrDirective;
47 }
48 }
49 const { typeMap, directives } = rewireTypes(originalTypeMap, Object.values(originalDirectiveMap));
50 return new GraphQLSchema({
51 ...config,
52 query: getObjectTypeFromTypeMap(typeMap, schema.getQueryType()),
53 mutation: getObjectTypeFromTypeMap(typeMap, schema.getMutationType()),
54 subscription: getObjectTypeFromTypeMap(typeMap, schema.getSubscriptionType()),
55 types: Object.values(typeMap),
56 directives,
57 });
58}