UNPKG

17.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.addResolversToSchema = void 0;
4const graphql_1 = require("graphql");
5const utils_1 = require("@graphql-tools/utils");
6const checkForResolveTypeResolver_js_1 = require("./checkForResolveTypeResolver.js");
7const extendResolversFromInterfaces_js_1 = require("./extendResolversFromInterfaces.js");
8function addResolversToSchema({ schema, resolvers: inputResolvers, defaultFieldResolver, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, updateResolversInPlace = false, }) {
9 const { requireResolversToMatchSchema = 'error', requireResolversForResolveType } = resolverValidationOptions;
10 const resolvers = inheritResolversFromInterfaces
11 ? (0, extendResolversFromInterfaces_js_1.extendResolversFromInterfaces)(schema, inputResolvers)
12 : inputResolvers;
13 for (const typeName in resolvers) {
14 const resolverValue = resolvers[typeName];
15 const resolverType = typeof resolverValue;
16 if (resolverType !== 'object') {
17 throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". The resolver's value must be of type object.`);
18 }
19 const type = schema.getType(typeName);
20 if (type == null) {
21 if (requireResolversToMatchSchema === 'ignore') {
22 continue;
23 }
24 throw new Error(`"${typeName}" defined in resolvers, but not in schema`);
25 }
26 else if ((0, graphql_1.isSpecifiedScalarType)(type)) {
27 // allow -- without recommending -- overriding of specified scalar types
28 for (const fieldName in resolverValue) {
29 if (fieldName.startsWith('__')) {
30 type[fieldName.substring(2)] = resolverValue[fieldName];
31 }
32 else {
33 type[fieldName] = resolverValue[fieldName];
34 }
35 }
36 }
37 else if ((0, graphql_1.isEnumType)(type)) {
38 const values = type.getValues();
39 for (const fieldName in resolverValue) {
40 if (!fieldName.startsWith('__') &&
41 !values.some(value => value.name === fieldName) &&
42 requireResolversToMatchSchema &&
43 requireResolversToMatchSchema !== 'ignore') {
44 throw new Error(`${type.name}.${fieldName} was defined in resolvers, but not present within ${type.name}`);
45 }
46 }
47 }
48 else if ((0, graphql_1.isUnionType)(type)) {
49 for (const fieldName in resolverValue) {
50 if (!fieldName.startsWith('__') &&
51 requireResolversToMatchSchema &&
52 requireResolversToMatchSchema !== 'ignore') {
53 throw new Error(`${type.name}.${fieldName} was defined in resolvers, but ${type.name} is not an object or interface type`);
54 }
55 }
56 }
57 else if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type)) {
58 for (const fieldName in resolverValue) {
59 if (!fieldName.startsWith('__')) {
60 const fields = type.getFields();
61 const field = fields[fieldName];
62 if (field == null) {
63 // Field present in resolver but not in schema
64 if (requireResolversToMatchSchema && requireResolversToMatchSchema !== 'ignore') {
65 throw new Error(`${typeName}.${fieldName} defined in resolvers, but not in schema`);
66 }
67 }
68 else {
69 // Field present in both the resolver and schema
70 const fieldResolve = resolverValue[fieldName];
71 if (typeof fieldResolve !== 'function' && typeof fieldResolve !== 'object') {
72 throw new Error(`Resolver ${typeName}.${fieldName} must be object or function`);
73 }
74 }
75 }
76 }
77 }
78 }
79 schema = updateResolversInPlace
80 ? addResolversToExistingSchema(schema, resolvers, defaultFieldResolver)
81 : createNewSchemaWithResolvers(schema, resolvers, defaultFieldResolver);
82 if (requireResolversForResolveType && requireResolversForResolveType !== 'ignore') {
83 (0, checkForResolveTypeResolver_js_1.checkForResolveTypeResolver)(schema, requireResolversForResolveType);
84 }
85 return schema;
86}
87exports.addResolversToSchema = addResolversToSchema;
88function addResolversToExistingSchema(schema, resolvers, defaultFieldResolver) {
89 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
90 const typeMap = schema.getTypeMap();
91 for (const typeName in resolvers) {
92 const type = schema.getType(typeName);
93 const resolverValue = resolvers[typeName];
94 if ((0, graphql_1.isScalarType)(type)) {
95 for (const fieldName in resolverValue) {
96 if (fieldName.startsWith('__')) {
97 type[fieldName.substring(2)] = resolverValue[fieldName];
98 }
99 else if (fieldName === 'astNode' && type.astNode != null) {
100 type.astNode = {
101 ...type.astNode,
102 description: (_b = (_a = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : type.astNode.description,
103 directives: ((_c = type.astNode.directives) !== null && _c !== void 0 ? _c : []).concat((_e = (_d = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _d === void 0 ? void 0 : _d.directives) !== null && _e !== void 0 ? _e : []),
104 };
105 }
106 else if (fieldName === 'extensionASTNodes' && type.extensionASTNodes != null) {
107 type.extensionASTNodes = type.extensionASTNodes.concat((_f = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.extensionASTNodes) !== null && _f !== void 0 ? _f : []);
108 }
109 else if (fieldName === 'extensions' &&
110 type.extensions != null &&
111 resolverValue.extensions != null) {
112 type.extensions = Object.assign(Object.create(null), type.extensions, resolverValue.extensions);
113 }
114 else {
115 type[fieldName] = resolverValue[fieldName];
116 }
117 }
118 }
119 else if ((0, graphql_1.isEnumType)(type)) {
120 const config = type.toConfig();
121 const enumValueConfigMap = config.values;
122 for (const fieldName in resolverValue) {
123 if (fieldName.startsWith('__')) {
124 config[fieldName.substring(2)] = resolverValue[fieldName];
125 }
126 else if (fieldName === 'astNode' && config.astNode != null) {
127 config.astNode = {
128 ...config.astNode,
129 description: (_h = (_g = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _g === void 0 ? void 0 : _g.description) !== null && _h !== void 0 ? _h : config.astNode.description,
130 directives: ((_j = config.astNode.directives) !== null && _j !== void 0 ? _j : []).concat((_l = (_k = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _k === void 0 ? void 0 : _k.directives) !== null && _l !== void 0 ? _l : []),
131 };
132 }
133 else if (fieldName === 'extensionASTNodes' && config.extensionASTNodes != null) {
134 config.extensionASTNodes = config.extensionASTNodes.concat((_m = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.extensionASTNodes) !== null && _m !== void 0 ? _m : []);
135 }
136 else if (fieldName === 'extensions' &&
137 type.extensions != null &&
138 resolverValue.extensions != null) {
139 type.extensions = Object.assign(Object.create(null), type.extensions, resolverValue.extensions);
140 }
141 else if (enumValueConfigMap[fieldName]) {
142 enumValueConfigMap[fieldName].value = resolverValue[fieldName];
143 }
144 }
145 typeMap[typeName] = new graphql_1.GraphQLEnumType(config);
146 }
147 else if ((0, graphql_1.isUnionType)(type)) {
148 for (const fieldName in resolverValue) {
149 if (fieldName.startsWith('__')) {
150 type[fieldName.substring(2)] = resolverValue[fieldName];
151 }
152 }
153 }
154 else if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type)) {
155 for (const fieldName in resolverValue) {
156 if (fieldName.startsWith('__')) {
157 // this is for isTypeOf and resolveType and all the other stuff.
158 type[fieldName.substring(2)] = resolverValue[fieldName];
159 continue;
160 }
161 const fields = type.getFields();
162 const field = fields[fieldName];
163 if (field != null) {
164 const fieldResolve = resolverValue[fieldName];
165 if (typeof fieldResolve === 'function') {
166 // for convenience. Allows shorter syntax in resolver definition file
167 field.resolve = fieldResolve.bind(resolverValue);
168 }
169 else {
170 setFieldProperties(field, fieldResolve);
171 }
172 }
173 }
174 }
175 }
176 // serialize all default values prior to healing fields with new scalar/enum types.
177 (0, utils_1.forEachDefaultValue)(schema, utils_1.serializeInputValue);
178 // schema may have new scalar/enum types that require healing
179 (0, utils_1.healSchema)(schema);
180 // reparse all default values with new parsing functions.
181 (0, utils_1.forEachDefaultValue)(schema, utils_1.parseInputValue);
182 if (defaultFieldResolver != null) {
183 (0, utils_1.forEachField)(schema, field => {
184 if (!field.resolve) {
185 field.resolve = defaultFieldResolver;
186 }
187 });
188 }
189 return schema;
190}
191function createNewSchemaWithResolvers(schema, resolvers, defaultFieldResolver) {
192 schema = (0, utils_1.mapSchema)(schema, {
193 [utils_1.MapperKind.SCALAR_TYPE]: type => {
194 var _a, _b, _c, _d, _e, _f;
195 const config = type.toConfig();
196 const resolverValue = resolvers[type.name];
197 if (!(0, graphql_1.isSpecifiedScalarType)(type) && resolverValue != null) {
198 for (const fieldName in resolverValue) {
199 if (fieldName.startsWith('__')) {
200 config[fieldName.substring(2)] = resolverValue[fieldName];
201 }
202 else if (fieldName === 'astNode' && config.astNode != null) {
203 config.astNode = {
204 ...config.astNode,
205 description: (_b = (_a = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : config.astNode.description,
206 directives: ((_c = config.astNode.directives) !== null && _c !== void 0 ? _c : []).concat((_e = (_d = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _d === void 0 ? void 0 : _d.directives) !== null && _e !== void 0 ? _e : []),
207 };
208 }
209 else if (fieldName === 'extensionASTNodes' && config.extensionASTNodes != null) {
210 config.extensionASTNodes = config.extensionASTNodes.concat((_f = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.extensionASTNodes) !== null && _f !== void 0 ? _f : []);
211 }
212 else if (fieldName === 'extensions' &&
213 config.extensions != null &&
214 resolverValue.extensions != null) {
215 config.extensions = Object.assign(Object.create(null), type.extensions, resolverValue.extensions);
216 }
217 else {
218 config[fieldName] = resolverValue[fieldName];
219 }
220 }
221 return new graphql_1.GraphQLScalarType(config);
222 }
223 },
224 [utils_1.MapperKind.ENUM_TYPE]: type => {
225 var _a, _b, _c, _d, _e, _f;
226 const resolverValue = resolvers[type.name];
227 const config = type.toConfig();
228 const enumValueConfigMap = config.values;
229 if (resolverValue != null) {
230 for (const fieldName in resolverValue) {
231 if (fieldName.startsWith('__')) {
232 config[fieldName.substring(2)] = resolverValue[fieldName];
233 }
234 else if (fieldName === 'astNode' && config.astNode != null) {
235 config.astNode = {
236 ...config.astNode,
237 description: (_b = (_a = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : config.astNode.description,
238 directives: ((_c = config.astNode.directives) !== null && _c !== void 0 ? _c : []).concat((_e = (_d = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.astNode) === null || _d === void 0 ? void 0 : _d.directives) !== null && _e !== void 0 ? _e : []),
239 };
240 }
241 else if (fieldName === 'extensionASTNodes' && config.extensionASTNodes != null) {
242 config.extensionASTNodes = config.extensionASTNodes.concat((_f = resolverValue === null || resolverValue === void 0 ? void 0 : resolverValue.extensionASTNodes) !== null && _f !== void 0 ? _f : []);
243 }
244 else if (fieldName === 'extensions' &&
245 config.extensions != null &&
246 resolverValue.extensions != null) {
247 config.extensions = Object.assign(Object.create(null), type.extensions, resolverValue.extensions);
248 }
249 else if (enumValueConfigMap[fieldName]) {
250 enumValueConfigMap[fieldName].value = resolverValue[fieldName];
251 }
252 }
253 return new graphql_1.GraphQLEnumType(config);
254 }
255 },
256 [utils_1.MapperKind.UNION_TYPE]: type => {
257 const resolverValue = resolvers[type.name];
258 if (resolverValue != null) {
259 const config = type.toConfig();
260 if (resolverValue['__resolveType']) {
261 config.resolveType = resolverValue['__resolveType'];
262 }
263 return new graphql_1.GraphQLUnionType(config);
264 }
265 },
266 [utils_1.MapperKind.OBJECT_TYPE]: type => {
267 const resolverValue = resolvers[type.name];
268 if (resolverValue != null) {
269 const config = type.toConfig();
270 if (resolverValue['__isTypeOf']) {
271 config.isTypeOf = resolverValue['__isTypeOf'];
272 }
273 return new graphql_1.GraphQLObjectType(config);
274 }
275 },
276 [utils_1.MapperKind.INTERFACE_TYPE]: type => {
277 const resolverValue = resolvers[type.name];
278 if (resolverValue != null) {
279 const config = type.toConfig();
280 if (resolverValue['__resolveType']) {
281 config.resolveType = resolverValue['__resolveType'];
282 }
283 return new graphql_1.GraphQLInterfaceType(config);
284 }
285 },
286 [utils_1.MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName, typeName) => {
287 const resolverValue = resolvers[typeName];
288 if (resolverValue != null) {
289 const fieldResolve = resolverValue[fieldName];
290 if (fieldResolve != null) {
291 const newFieldConfig = { ...fieldConfig };
292 if (typeof fieldResolve === 'function') {
293 // for convenience. Allows shorter syntax in resolver definition file
294 newFieldConfig.resolve = fieldResolve.bind(resolverValue);
295 }
296 else {
297 setFieldProperties(newFieldConfig, fieldResolve);
298 }
299 return newFieldConfig;
300 }
301 }
302 },
303 });
304 if (defaultFieldResolver != null) {
305 schema = (0, utils_1.mapSchema)(schema, {
306 [utils_1.MapperKind.OBJECT_FIELD]: fieldConfig => ({
307 ...fieldConfig,
308 resolve: fieldConfig.resolve != null ? fieldConfig.resolve : defaultFieldResolver,
309 }),
310 });
311 }
312 return schema;
313}
314function setFieldProperties(field, propertiesObj) {
315 for (const propertyName in propertiesObj) {
316 field[propertyName] = propertiesObj[propertyName];
317 }
318}