@graphql-tools/schema 8.4.0 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{index.js → cjs/addResolversToSchema.js} +39 -260
- package/cjs/assertResolversPresent.js +47 -0
- package/cjs/chainResolvers.js +13 -0
- package/cjs/checkForResolveTypeResolver.js +23 -0
- package/cjs/extendResolversFromInterfaces.js +35 -0
- package/cjs/index.js +17 -0
- package/cjs/makeExecutableSchema.js +96 -0
- package/cjs/merge-schemas.js +29 -0
- package/cjs/package.json +1 -0
- package/cjs/types.js +2 -0
- package/{index.mjs → esm/addResolversToSchema.js} +5 -220
- package/esm/assertResolversPresent.js +43 -0
- package/esm/chainResolvers.js +9 -0
- package/esm/checkForResolveTypeResolver.js +19 -0
- package/esm/extendResolversFromInterfaces.js +31 -0
- package/esm/index.js +8 -0
- package/esm/makeExecutableSchema.js +92 -0
- package/esm/merge-schemas.js +25 -0
- package/esm/types.js +1 -0
- package/package.json +33 -12
- package/{addResolversToSchema.d.ts → typings/addResolversToSchema.d.ts} +0 -0
- package/{assertResolversPresent.d.ts → typings/assertResolversPresent.d.ts} +0 -0
- package/{chainResolvers.d.ts → typings/chainResolvers.d.ts} +0 -0
- package/{checkForResolveTypeResolver.d.ts → typings/checkForResolveTypeResolver.d.ts} +0 -0
- package/{extendResolversFromInterfaces.d.ts → typings/extendResolversFromInterfaces.d.ts} +0 -0
- package/typings/index.d.ts +8 -0
- package/{makeExecutableSchema.d.ts → typings/makeExecutableSchema.d.ts} +1 -1
- package/{merge-schemas.d.ts → typings/merge-schemas.d.ts} +1 -1
- package/{types.d.ts → typings/types.d.ts} +0 -0
- package/index.d.ts +0 -8
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeExecutableSchema = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
6
|
+
const addResolversToSchema_js_1 = require("./addResolversToSchema.js");
|
|
7
|
+
const assertResolversPresent_js_1 = require("./assertResolversPresent.js");
|
|
8
|
+
const merge_1 = require("@graphql-tools/merge");
|
|
9
|
+
/**
|
|
10
|
+
* Builds a schema from the provided type definitions and resolvers.
|
|
11
|
+
*
|
|
12
|
+
* The type definitions are written using Schema Definition Language (SDL). They
|
|
13
|
+
* can be provided as a string, a `DocumentNode`, a function, or an array of any
|
|
14
|
+
* of these. If a function is provided, it will be passed no arguments and
|
|
15
|
+
* should return an array of strings or `DocumentNode`s.
|
|
16
|
+
*
|
|
17
|
+
* Note: You can use `graphql-tag` to not only parse a string into a
|
|
18
|
+
* `DocumentNode` but also to provide additional syntax highlighting in your
|
|
19
|
+
* editor (with the appropriate editor plugin).
|
|
20
|
+
*
|
|
21
|
+
* ```js
|
|
22
|
+
* const typeDefs = gql`
|
|
23
|
+
* type Query {
|
|
24
|
+
* posts: [Post]
|
|
25
|
+
* author(id: Int!): Author
|
|
26
|
+
* }
|
|
27
|
+
* `;
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* The `resolvers` object should be a map of type names to nested object, which
|
|
31
|
+
* themselves map the type's fields to their appropriate resolvers.
|
|
32
|
+
* See the [Resolvers](/docs/resolvers) section of the documentation for more details.
|
|
33
|
+
*
|
|
34
|
+
* ```js
|
|
35
|
+
* const resolvers = {
|
|
36
|
+
* Query: {
|
|
37
|
+
* posts: (obj, args, ctx, info) => getAllPosts(),
|
|
38
|
+
* author: (obj, args, ctx, info) => getAuthorById(args.id)
|
|
39
|
+
* }
|
|
40
|
+
* };
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Once you've defined both the `typeDefs` and `resolvers`, you can create your
|
|
44
|
+
* schema:
|
|
45
|
+
*
|
|
46
|
+
* ```js
|
|
47
|
+
* const schema = makeExecutableSchema({
|
|
48
|
+
* typeDefs,
|
|
49
|
+
* resolvers,
|
|
50
|
+
* })
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
function makeExecutableSchema({ typeDefs, resolvers = {}, resolverValidationOptions = {}, parseOptions = {}, inheritResolversFromInterfaces = false, pruningOptions, updateResolversInPlace = false, schemaExtensions, }) {
|
|
54
|
+
// Validate and clean up arguments
|
|
55
|
+
if (typeof resolverValidationOptions !== 'object') {
|
|
56
|
+
throw new Error('Expected `resolverValidationOptions` to be an object');
|
|
57
|
+
}
|
|
58
|
+
if (!typeDefs) {
|
|
59
|
+
throw new Error('Must provide typeDefs');
|
|
60
|
+
}
|
|
61
|
+
let schema;
|
|
62
|
+
if ((0, graphql_1.isSchema)(typeDefs)) {
|
|
63
|
+
schema = typeDefs;
|
|
64
|
+
}
|
|
65
|
+
else if (parseOptions === null || parseOptions === void 0 ? void 0 : parseOptions.commentDescriptions) {
|
|
66
|
+
const mergedTypeDefs = (0, merge_1.mergeTypeDefs)(typeDefs, {
|
|
67
|
+
...parseOptions,
|
|
68
|
+
commentDescriptions: true,
|
|
69
|
+
});
|
|
70
|
+
schema = (0, graphql_1.buildSchema)(mergedTypeDefs, parseOptions);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const mergedTypeDefs = (0, merge_1.mergeTypeDefs)(typeDefs, parseOptions);
|
|
74
|
+
schema = (0, graphql_1.buildASTSchema)(mergedTypeDefs, parseOptions);
|
|
75
|
+
}
|
|
76
|
+
if (pruningOptions) {
|
|
77
|
+
schema = (0, utils_1.pruneSchema)(schema);
|
|
78
|
+
}
|
|
79
|
+
// We allow passing in an array of resolver maps, in which case we merge them
|
|
80
|
+
schema = (0, addResolversToSchema_js_1.addResolversToSchema)({
|
|
81
|
+
schema,
|
|
82
|
+
resolvers: (0, merge_1.mergeResolvers)(resolvers),
|
|
83
|
+
resolverValidationOptions,
|
|
84
|
+
inheritResolversFromInterfaces,
|
|
85
|
+
updateResolversInPlace,
|
|
86
|
+
});
|
|
87
|
+
if (Object.keys(resolverValidationOptions).length > 0) {
|
|
88
|
+
(0, assertResolversPresent_js_1.assertResolversPresent)(schema, resolverValidationOptions);
|
|
89
|
+
}
|
|
90
|
+
if (schemaExtensions) {
|
|
91
|
+
schemaExtensions = (0, merge_1.mergeExtensions)((0, utils_1.asArray)(schemaExtensions));
|
|
92
|
+
(0, merge_1.applyExtensions)(schema, schemaExtensions);
|
|
93
|
+
}
|
|
94
|
+
return schema;
|
|
95
|
+
}
|
|
96
|
+
exports.makeExecutableSchema = makeExecutableSchema;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeSchemas = void 0;
|
|
4
|
+
const merge_1 = require("@graphql-tools/merge");
|
|
5
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
6
|
+
const makeExecutableSchema_js_1 = require("./makeExecutableSchema.js");
|
|
7
|
+
/**
|
|
8
|
+
* Synchronously merges multiple schemas, typeDefinitions and/or resolvers into a single schema.
|
|
9
|
+
* @param config Configuration object
|
|
10
|
+
*/
|
|
11
|
+
function mergeSchemas(config) {
|
|
12
|
+
const extractedTypeDefs = (0, utils_1.asArray)(config.typeDefs || []);
|
|
13
|
+
const extractedResolvers = (0, utils_1.asArray)(config.resolvers || []);
|
|
14
|
+
const extractedSchemaExtensions = (0, utils_1.asArray)(config.schemaExtensions || []);
|
|
15
|
+
const schemas = config.schemas || [];
|
|
16
|
+
for (const schema of schemas) {
|
|
17
|
+
extractedTypeDefs.push(schema);
|
|
18
|
+
extractedResolvers.push((0, utils_1.getResolversFromSchema)(schema, true));
|
|
19
|
+
extractedSchemaExtensions.push((0, merge_1.extractExtensionsFromSchema)(schema));
|
|
20
|
+
}
|
|
21
|
+
return (0, makeExecutableSchema_js_1.makeExecutableSchema)({
|
|
22
|
+
parseOptions: config,
|
|
23
|
+
...config,
|
|
24
|
+
typeDefs: extractedTypeDefs,
|
|
25
|
+
resolvers: extractedResolvers,
|
|
26
|
+
schemaExtensions: extractedSchemaExtensions,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.mergeSchemas = mergeSchemas;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
package/cjs/types.js
ADDED
|
@@ -1,110 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
function
|
|
6
|
-
const { requireResolversForArgs, requireResolversForNonScalar, requireResolversForAllFields } = resolverValidationOptions;
|
|
7
|
-
if (requireResolversForAllFields && (requireResolversForArgs || requireResolversForNonScalar)) {
|
|
8
|
-
throw new TypeError('requireResolversForAllFields takes precedence over the more specific assertions. ' +
|
|
9
|
-
'Please configure either requireResolversForAllFields or requireResolversForArgs / ' +
|
|
10
|
-
'requireResolversForNonScalar, but not a combination of them.');
|
|
11
|
-
}
|
|
12
|
-
forEachField(schema, (field, typeName, fieldName) => {
|
|
13
|
-
// requires a resolver for *every* field.
|
|
14
|
-
if (requireResolversForAllFields) {
|
|
15
|
-
expectResolver('requireResolversForAllFields', requireResolversForAllFields, field, typeName, fieldName);
|
|
16
|
-
}
|
|
17
|
-
// requires a resolver on every field that has arguments
|
|
18
|
-
if (requireResolversForArgs && field.args.length > 0) {
|
|
19
|
-
expectResolver('requireResolversForArgs', requireResolversForArgs, field, typeName, fieldName);
|
|
20
|
-
}
|
|
21
|
-
// requires a resolver on every field that returns a non-scalar type
|
|
22
|
-
if (requireResolversForNonScalar !== 'ignore' && !isScalarType(getNamedType(field.type))) {
|
|
23
|
-
expectResolver('requireResolversForNonScalar', requireResolversForNonScalar, field, typeName, fieldName);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function expectResolver(validator, behavior, field, typeName, fieldName) {
|
|
28
|
-
if (!field.resolve) {
|
|
29
|
-
const message = `Resolver missing for "${typeName}.${fieldName}".
|
|
30
|
-
To disable this validator, use:
|
|
31
|
-
resolverValidationOptions: {
|
|
32
|
-
${validator}: 'ignore'
|
|
33
|
-
}`;
|
|
34
|
-
if (behavior === 'error') {
|
|
35
|
-
throw new Error(message);
|
|
36
|
-
}
|
|
37
|
-
if (behavior === 'warn') {
|
|
38
|
-
console.warn(message);
|
|
39
|
-
}
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (typeof field.resolve !== 'function') {
|
|
43
|
-
throw new Error(`Resolver "${typeName}.${fieldName}" must be a function`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function chainResolvers(resolvers) {
|
|
48
|
-
return (root, args, ctx, info) => resolvers.reduce((prev, curResolver) => {
|
|
49
|
-
if (curResolver != null) {
|
|
50
|
-
return curResolver(prev, args, ctx, info);
|
|
51
|
-
}
|
|
52
|
-
return defaultFieldResolver(prev, args, ctx, info);
|
|
53
|
-
}, root);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// If we have any union or interface types throw if no there is no resolveType resolver
|
|
57
|
-
function checkForResolveTypeResolver(schema, requireResolversForResolveType) {
|
|
58
|
-
mapSchema(schema, {
|
|
59
|
-
[MapperKind.ABSTRACT_TYPE]: type => {
|
|
60
|
-
if (!type.resolveType) {
|
|
61
|
-
const message = `Type "${type.name}" is missing a "__resolveType" resolver. Pass 'ignore' into ` +
|
|
62
|
-
'"resolverValidationOptions.requireResolversForResolveType" to disable this error.';
|
|
63
|
-
if (requireResolversForResolveType === 'error') {
|
|
64
|
-
throw new Error(message);
|
|
65
|
-
}
|
|
66
|
-
if (requireResolversForResolveType === 'warn') {
|
|
67
|
-
console.warn(message);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return undefined;
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function extendResolversFromInterfaces(schema, resolvers) {
|
|
76
|
-
const extendedResolvers = {};
|
|
77
|
-
const typeMap = schema.getTypeMap();
|
|
78
|
-
for (const typeName in typeMap) {
|
|
79
|
-
const type = typeMap[typeName];
|
|
80
|
-
if ('getInterfaces' in type) {
|
|
81
|
-
extendedResolvers[typeName] = {};
|
|
82
|
-
for (const iFace of type.getInterfaces()) {
|
|
83
|
-
if (resolvers[iFace.name]) {
|
|
84
|
-
for (const fieldName in resolvers[iFace.name]) {
|
|
85
|
-
if (fieldName === '__isTypeOf' || !fieldName.startsWith('__')) {
|
|
86
|
-
extendedResolvers[typeName][fieldName] = resolvers[iFace.name][fieldName];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const typeResolvers = resolvers[typeName];
|
|
92
|
-
extendedResolvers[typeName] = {
|
|
93
|
-
...extendedResolvers[typeName],
|
|
94
|
-
...typeResolvers,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
const typeResolvers = resolvers[typeName];
|
|
99
|
-
if (typeResolvers != null) {
|
|
100
|
-
extendedResolvers[typeName] = typeResolvers;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return extendedResolvers;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function addResolversToSchema(schemaOrOptions, legacyInputResolvers, legacyInputValidationOptions) {
|
|
1
|
+
import { GraphQLEnumType, isSchema, GraphQLScalarType, GraphQLUnionType, GraphQLInterfaceType, GraphQLObjectType, isSpecifiedScalarType, isScalarType, isEnumType, isUnionType, isInterfaceType, isObjectType, } from 'graphql';
|
|
2
|
+
import { mapSchema, MapperKind, forEachDefaultValue, serializeInputValue, healSchema, parseInputValue, forEachField, } from '@graphql-tools/utils';
|
|
3
|
+
import { checkForResolveTypeResolver } from './checkForResolveTypeResolver.js';
|
|
4
|
+
import { extendResolversFromInterfaces } from './extendResolversFromInterfaces.js';
|
|
5
|
+
export function addResolversToSchema(schemaOrOptions, legacyInputResolvers, legacyInputValidationOptions) {
|
|
108
6
|
const options = isSchema(schemaOrOptions)
|
|
109
7
|
? {
|
|
110
8
|
schema: schemaOrOptions,
|
|
@@ -422,116 +320,3 @@ function setFieldProperties(field, propertiesObj) {
|
|
|
422
320
|
field[propertyName] = propertiesObj[propertyName];
|
|
423
321
|
}
|
|
424
322
|
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Builds a schema from the provided type definitions and resolvers.
|
|
428
|
-
*
|
|
429
|
-
* The type definitions are written using Schema Definition Language (SDL). They
|
|
430
|
-
* can be provided as a string, a `DocumentNode`, a function, or an array of any
|
|
431
|
-
* of these. If a function is provided, it will be passed no arguments and
|
|
432
|
-
* should return an array of strings or `DocumentNode`s.
|
|
433
|
-
*
|
|
434
|
-
* Note: You can use `graphql-tag` to not only parse a string into a
|
|
435
|
-
* `DocumentNode` but also to provide additional syntax highlighting in your
|
|
436
|
-
* editor (with the appropriate editor plugin).
|
|
437
|
-
*
|
|
438
|
-
* ```js
|
|
439
|
-
* const typeDefs = gql`
|
|
440
|
-
* type Query {
|
|
441
|
-
* posts: [Post]
|
|
442
|
-
* author(id: Int!): Author
|
|
443
|
-
* }
|
|
444
|
-
* `;
|
|
445
|
-
* ```
|
|
446
|
-
*
|
|
447
|
-
* The `resolvers` object should be a map of type names to nested object, which
|
|
448
|
-
* themselves map the type's fields to their appropriate resolvers.
|
|
449
|
-
* See the [Resolvers](/docs/resolvers) section of the documentation for more details.
|
|
450
|
-
*
|
|
451
|
-
* ```js
|
|
452
|
-
* const resolvers = {
|
|
453
|
-
* Query: {
|
|
454
|
-
* posts: (obj, args, ctx, info) => getAllPosts(),
|
|
455
|
-
* author: (obj, args, ctx, info) => getAuthorById(args.id)
|
|
456
|
-
* }
|
|
457
|
-
* };
|
|
458
|
-
* ```
|
|
459
|
-
*
|
|
460
|
-
* Once you've defined both the `typeDefs` and `resolvers`, you can create your
|
|
461
|
-
* schema:
|
|
462
|
-
*
|
|
463
|
-
* ```js
|
|
464
|
-
* const schema = makeExecutableSchema({
|
|
465
|
-
* typeDefs,
|
|
466
|
-
* resolvers,
|
|
467
|
-
* })
|
|
468
|
-
* ```
|
|
469
|
-
*/
|
|
470
|
-
function makeExecutableSchema({ typeDefs, resolvers = {}, resolverValidationOptions = {}, parseOptions = {}, inheritResolversFromInterfaces = false, pruningOptions, updateResolversInPlace = false, schemaExtensions, }) {
|
|
471
|
-
// Validate and clean up arguments
|
|
472
|
-
if (typeof resolverValidationOptions !== 'object') {
|
|
473
|
-
throw new Error('Expected `resolverValidationOptions` to be an object');
|
|
474
|
-
}
|
|
475
|
-
if (!typeDefs) {
|
|
476
|
-
throw new Error('Must provide typeDefs');
|
|
477
|
-
}
|
|
478
|
-
let schema;
|
|
479
|
-
if (isSchema(typeDefs)) {
|
|
480
|
-
schema = typeDefs;
|
|
481
|
-
}
|
|
482
|
-
else if (parseOptions === null || parseOptions === void 0 ? void 0 : parseOptions.commentDescriptions) {
|
|
483
|
-
const mergedTypeDefs = mergeTypeDefs(typeDefs, {
|
|
484
|
-
...parseOptions,
|
|
485
|
-
commentDescriptions: true,
|
|
486
|
-
});
|
|
487
|
-
schema = buildSchema(mergedTypeDefs, parseOptions);
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
const mergedTypeDefs = mergeTypeDefs(typeDefs, parseOptions);
|
|
491
|
-
schema = buildASTSchema(mergedTypeDefs, parseOptions);
|
|
492
|
-
}
|
|
493
|
-
if (pruningOptions) {
|
|
494
|
-
schema = pruneSchema(schema);
|
|
495
|
-
}
|
|
496
|
-
// We allow passing in an array of resolver maps, in which case we merge them
|
|
497
|
-
schema = addResolversToSchema({
|
|
498
|
-
schema,
|
|
499
|
-
resolvers: mergeResolvers(resolvers),
|
|
500
|
-
resolverValidationOptions,
|
|
501
|
-
inheritResolversFromInterfaces,
|
|
502
|
-
updateResolversInPlace,
|
|
503
|
-
});
|
|
504
|
-
if (Object.keys(resolverValidationOptions).length > 0) {
|
|
505
|
-
assertResolversPresent(schema, resolverValidationOptions);
|
|
506
|
-
}
|
|
507
|
-
if (schemaExtensions) {
|
|
508
|
-
schemaExtensions = mergeExtensions(asArray(schemaExtensions));
|
|
509
|
-
applyExtensions(schema, schemaExtensions);
|
|
510
|
-
}
|
|
511
|
-
return schema;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* Synchronously merges multiple schemas, typeDefinitions and/or resolvers into a single schema.
|
|
516
|
-
* @param config Configuration object
|
|
517
|
-
*/
|
|
518
|
-
function mergeSchemas(config) {
|
|
519
|
-
const extractedTypeDefs = asArray(config.typeDefs || []);
|
|
520
|
-
const extractedResolvers = asArray(config.resolvers || []);
|
|
521
|
-
const extractedSchemaExtensions = asArray(config.schemaExtensions || []);
|
|
522
|
-
const schemas = config.schemas || [];
|
|
523
|
-
for (const schema of schemas) {
|
|
524
|
-
extractedTypeDefs.push(schema);
|
|
525
|
-
extractedResolvers.push(getResolversFromSchema(schema, true));
|
|
526
|
-
extractedSchemaExtensions.push(extractExtensionsFromSchema(schema));
|
|
527
|
-
}
|
|
528
|
-
return makeExecutableSchema({
|
|
529
|
-
parseOptions: config,
|
|
530
|
-
...config,
|
|
531
|
-
typeDefs: extractedTypeDefs,
|
|
532
|
-
resolvers: extractedResolvers,
|
|
533
|
-
schemaExtensions: extractedSchemaExtensions,
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
export { addResolversToSchema, assertResolversPresent, chainResolvers, checkForResolveTypeResolver, extendResolversFromInterfaces, makeExecutableSchema, mergeSchemas };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getNamedType, isScalarType } from 'graphql';
|
|
2
|
+
import { forEachField } from '@graphql-tools/utils';
|
|
3
|
+
export function assertResolversPresent(schema, resolverValidationOptions = {}) {
|
|
4
|
+
const { requireResolversForArgs, requireResolversForNonScalar, requireResolversForAllFields } = resolverValidationOptions;
|
|
5
|
+
if (requireResolversForAllFields && (requireResolversForArgs || requireResolversForNonScalar)) {
|
|
6
|
+
throw new TypeError('requireResolversForAllFields takes precedence over the more specific assertions. ' +
|
|
7
|
+
'Please configure either requireResolversForAllFields or requireResolversForArgs / ' +
|
|
8
|
+
'requireResolversForNonScalar, but not a combination of them.');
|
|
9
|
+
}
|
|
10
|
+
forEachField(schema, (field, typeName, fieldName) => {
|
|
11
|
+
// requires a resolver for *every* field.
|
|
12
|
+
if (requireResolversForAllFields) {
|
|
13
|
+
expectResolver('requireResolversForAllFields', requireResolversForAllFields, field, typeName, fieldName);
|
|
14
|
+
}
|
|
15
|
+
// requires a resolver on every field that has arguments
|
|
16
|
+
if (requireResolversForArgs && field.args.length > 0) {
|
|
17
|
+
expectResolver('requireResolversForArgs', requireResolversForArgs, field, typeName, fieldName);
|
|
18
|
+
}
|
|
19
|
+
// requires a resolver on every field that returns a non-scalar type
|
|
20
|
+
if (requireResolversForNonScalar !== 'ignore' && !isScalarType(getNamedType(field.type))) {
|
|
21
|
+
expectResolver('requireResolversForNonScalar', requireResolversForNonScalar, field, typeName, fieldName);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function expectResolver(validator, behavior, field, typeName, fieldName) {
|
|
26
|
+
if (!field.resolve) {
|
|
27
|
+
const message = `Resolver missing for "${typeName}.${fieldName}".
|
|
28
|
+
To disable this validator, use:
|
|
29
|
+
resolverValidationOptions: {
|
|
30
|
+
${validator}: 'ignore'
|
|
31
|
+
}`;
|
|
32
|
+
if (behavior === 'error') {
|
|
33
|
+
throw new Error(message);
|
|
34
|
+
}
|
|
35
|
+
if (behavior === 'warn') {
|
|
36
|
+
console.warn(message);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (typeof field.resolve !== 'function') {
|
|
41
|
+
throw new Error(`Resolver "${typeName}.${fieldName}" must be a function`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defaultFieldResolver } from 'graphql';
|
|
2
|
+
export function chainResolvers(resolvers) {
|
|
3
|
+
return (root, args, ctx, info) => resolvers.reduce((prev, curResolver) => {
|
|
4
|
+
if (curResolver != null) {
|
|
5
|
+
return curResolver(prev, args, ctx, info);
|
|
6
|
+
}
|
|
7
|
+
return defaultFieldResolver(prev, args, ctx, info);
|
|
8
|
+
}, root);
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MapperKind, mapSchema } from '@graphql-tools/utils';
|
|
2
|
+
// If we have any union or interface types throw if no there is no resolveType resolver
|
|
3
|
+
export function checkForResolveTypeResolver(schema, requireResolversForResolveType) {
|
|
4
|
+
mapSchema(schema, {
|
|
5
|
+
[MapperKind.ABSTRACT_TYPE]: type => {
|
|
6
|
+
if (!type.resolveType) {
|
|
7
|
+
const message = `Type "${type.name}" is missing a "__resolveType" resolver. Pass 'ignore' into ` +
|
|
8
|
+
'"resolverValidationOptions.requireResolversForResolveType" to disable this error.';
|
|
9
|
+
if (requireResolversForResolveType === 'error') {
|
|
10
|
+
throw new Error(message);
|
|
11
|
+
}
|
|
12
|
+
if (requireResolversForResolveType === 'warn') {
|
|
13
|
+
console.warn(message);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function extendResolversFromInterfaces(schema, resolvers) {
|
|
2
|
+
const extendedResolvers = {};
|
|
3
|
+
const typeMap = schema.getTypeMap();
|
|
4
|
+
for (const typeName in typeMap) {
|
|
5
|
+
const type = typeMap[typeName];
|
|
6
|
+
if ('getInterfaces' in type) {
|
|
7
|
+
extendedResolvers[typeName] = {};
|
|
8
|
+
for (const iFace of type.getInterfaces()) {
|
|
9
|
+
if (resolvers[iFace.name]) {
|
|
10
|
+
for (const fieldName in resolvers[iFace.name]) {
|
|
11
|
+
if (fieldName === '__isTypeOf' || !fieldName.startsWith('__')) {
|
|
12
|
+
extendedResolvers[typeName][fieldName] = resolvers[iFace.name][fieldName];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const typeResolvers = resolvers[typeName];
|
|
18
|
+
extendedResolvers[typeName] = {
|
|
19
|
+
...extendedResolvers[typeName],
|
|
20
|
+
...typeResolvers,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const typeResolvers = resolvers[typeName];
|
|
25
|
+
if (typeResolvers != null) {
|
|
26
|
+
extendedResolvers[typeName] = typeResolvers;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return extendedResolvers;
|
|
31
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { assertResolversPresent } from './assertResolversPresent.js';
|
|
2
|
+
export { chainResolvers } from './chainResolvers.js';
|
|
3
|
+
export { addResolversToSchema } from './addResolversToSchema.js';
|
|
4
|
+
export { checkForResolveTypeResolver } from './checkForResolveTypeResolver.js';
|
|
5
|
+
export { extendResolversFromInterfaces } from './extendResolversFromInterfaces.js';
|
|
6
|
+
export * from './makeExecutableSchema.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './merge-schemas.js';
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { buildASTSchema, buildSchema, isSchema } from 'graphql';
|
|
2
|
+
import { asArray, pruneSchema } from '@graphql-tools/utils';
|
|
3
|
+
import { addResolversToSchema } from './addResolversToSchema.js';
|
|
4
|
+
import { assertResolversPresent } from './assertResolversPresent.js';
|
|
5
|
+
import { applyExtensions, mergeExtensions, mergeResolvers, mergeTypeDefs } from '@graphql-tools/merge';
|
|
6
|
+
/**
|
|
7
|
+
* Builds a schema from the provided type definitions and resolvers.
|
|
8
|
+
*
|
|
9
|
+
* The type definitions are written using Schema Definition Language (SDL). They
|
|
10
|
+
* can be provided as a string, a `DocumentNode`, a function, or an array of any
|
|
11
|
+
* of these. If a function is provided, it will be passed no arguments and
|
|
12
|
+
* should return an array of strings or `DocumentNode`s.
|
|
13
|
+
*
|
|
14
|
+
* Note: You can use `graphql-tag` to not only parse a string into a
|
|
15
|
+
* `DocumentNode` but also to provide additional syntax highlighting in your
|
|
16
|
+
* editor (with the appropriate editor plugin).
|
|
17
|
+
*
|
|
18
|
+
* ```js
|
|
19
|
+
* const typeDefs = gql`
|
|
20
|
+
* type Query {
|
|
21
|
+
* posts: [Post]
|
|
22
|
+
* author(id: Int!): Author
|
|
23
|
+
* }
|
|
24
|
+
* `;
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* The `resolvers` object should be a map of type names to nested object, which
|
|
28
|
+
* themselves map the type's fields to their appropriate resolvers.
|
|
29
|
+
* See the [Resolvers](/docs/resolvers) section of the documentation for more details.
|
|
30
|
+
*
|
|
31
|
+
* ```js
|
|
32
|
+
* const resolvers = {
|
|
33
|
+
* Query: {
|
|
34
|
+
* posts: (obj, args, ctx, info) => getAllPosts(),
|
|
35
|
+
* author: (obj, args, ctx, info) => getAuthorById(args.id)
|
|
36
|
+
* }
|
|
37
|
+
* };
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Once you've defined both the `typeDefs` and `resolvers`, you can create your
|
|
41
|
+
* schema:
|
|
42
|
+
*
|
|
43
|
+
* ```js
|
|
44
|
+
* const schema = makeExecutableSchema({
|
|
45
|
+
* typeDefs,
|
|
46
|
+
* resolvers,
|
|
47
|
+
* })
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function makeExecutableSchema({ typeDefs, resolvers = {}, resolverValidationOptions = {}, parseOptions = {}, inheritResolversFromInterfaces = false, pruningOptions, updateResolversInPlace = false, schemaExtensions, }) {
|
|
51
|
+
// Validate and clean up arguments
|
|
52
|
+
if (typeof resolverValidationOptions !== 'object') {
|
|
53
|
+
throw new Error('Expected `resolverValidationOptions` to be an object');
|
|
54
|
+
}
|
|
55
|
+
if (!typeDefs) {
|
|
56
|
+
throw new Error('Must provide typeDefs');
|
|
57
|
+
}
|
|
58
|
+
let schema;
|
|
59
|
+
if (isSchema(typeDefs)) {
|
|
60
|
+
schema = typeDefs;
|
|
61
|
+
}
|
|
62
|
+
else if (parseOptions === null || parseOptions === void 0 ? void 0 : parseOptions.commentDescriptions) {
|
|
63
|
+
const mergedTypeDefs = mergeTypeDefs(typeDefs, {
|
|
64
|
+
...parseOptions,
|
|
65
|
+
commentDescriptions: true,
|
|
66
|
+
});
|
|
67
|
+
schema = buildSchema(mergedTypeDefs, parseOptions);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const mergedTypeDefs = mergeTypeDefs(typeDefs, parseOptions);
|
|
71
|
+
schema = buildASTSchema(mergedTypeDefs, parseOptions);
|
|
72
|
+
}
|
|
73
|
+
if (pruningOptions) {
|
|
74
|
+
schema = pruneSchema(schema);
|
|
75
|
+
}
|
|
76
|
+
// We allow passing in an array of resolver maps, in which case we merge them
|
|
77
|
+
schema = addResolversToSchema({
|
|
78
|
+
schema,
|
|
79
|
+
resolvers: mergeResolvers(resolvers),
|
|
80
|
+
resolverValidationOptions,
|
|
81
|
+
inheritResolversFromInterfaces,
|
|
82
|
+
updateResolversInPlace,
|
|
83
|
+
});
|
|
84
|
+
if (Object.keys(resolverValidationOptions).length > 0) {
|
|
85
|
+
assertResolversPresent(schema, resolverValidationOptions);
|
|
86
|
+
}
|
|
87
|
+
if (schemaExtensions) {
|
|
88
|
+
schemaExtensions = mergeExtensions(asArray(schemaExtensions));
|
|
89
|
+
applyExtensions(schema, schemaExtensions);
|
|
90
|
+
}
|
|
91
|
+
return schema;
|
|
92
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { extractExtensionsFromSchema } from '@graphql-tools/merge';
|
|
2
|
+
import { asArray, getResolversFromSchema } from '@graphql-tools/utils';
|
|
3
|
+
import { makeExecutableSchema } from './makeExecutableSchema.js';
|
|
4
|
+
/**
|
|
5
|
+
* Synchronously merges multiple schemas, typeDefinitions and/or resolvers into a single schema.
|
|
6
|
+
* @param config Configuration object
|
|
7
|
+
*/
|
|
8
|
+
export function mergeSchemas(config) {
|
|
9
|
+
const extractedTypeDefs = asArray(config.typeDefs || []);
|
|
10
|
+
const extractedResolvers = asArray(config.resolvers || []);
|
|
11
|
+
const extractedSchemaExtensions = asArray(config.schemaExtensions || []);
|
|
12
|
+
const schemas = config.schemas || [];
|
|
13
|
+
for (const schema of schemas) {
|
|
14
|
+
extractedTypeDefs.push(schema);
|
|
15
|
+
extractedResolvers.push(getResolversFromSchema(schema, true));
|
|
16
|
+
extractedSchemaExtensions.push(extractExtensionsFromSchema(schema));
|
|
17
|
+
}
|
|
18
|
+
return makeExecutableSchema({
|
|
19
|
+
parseOptions: config,
|
|
20
|
+
...config,
|
|
21
|
+
typeDefs: extractedTypeDefs,
|
|
22
|
+
resolvers: extractedResolvers,
|
|
23
|
+
schemaExtensions: extractedSchemaExtensions,
|
|
24
|
+
});
|
|
25
|
+
}
|
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/schema",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.0",
|
|
4
4
|
"description": "A set of utils for faster development of GraphQL tools",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@graphql-tools/merge": "8.
|
|
11
|
-
"@graphql-tools/utils": "8.
|
|
10
|
+
"@graphql-tools/merge": "8.3.0",
|
|
11
|
+
"@graphql-tools/utils": "8.8.0",
|
|
12
12
|
"tslib": "^2.4.0",
|
|
13
13
|
"value-or-promise": "1.0.11"
|
|
14
14
|
},
|
|
@@ -18,21 +18,42 @@
|
|
|
18
18
|
"directory": "packages/schema"
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
21
|
-
"main": "index.js",
|
|
22
|
-
"module": "index.
|
|
23
|
-
"typings": "index.d.ts",
|
|
21
|
+
"main": "cjs/index.js",
|
|
22
|
+
"module": "esm/index.js",
|
|
23
|
+
"typings": "typings/index.d.ts",
|
|
24
24
|
"typescript": {
|
|
25
|
-
"definition": "index.d.ts"
|
|
25
|
+
"definition": "typings/index.d.ts"
|
|
26
26
|
},
|
|
27
|
+
"type": "module",
|
|
27
28
|
"exports": {
|
|
28
29
|
".": {
|
|
29
|
-
"require":
|
|
30
|
-
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./typings/index.d.ts",
|
|
32
|
+
"default": "./cjs/index.js"
|
|
33
|
+
},
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./typings/index.d.ts",
|
|
36
|
+
"default": "./esm/index.js"
|
|
37
|
+
},
|
|
38
|
+
"default": {
|
|
39
|
+
"types": "./typings/index.d.ts",
|
|
40
|
+
"default": "./esm/index.js"
|
|
41
|
+
}
|
|
31
42
|
},
|
|
32
43
|
"./*": {
|
|
33
|
-
"require":
|
|
34
|
-
|
|
44
|
+
"require": {
|
|
45
|
+
"types": "./typings/*.d.ts",
|
|
46
|
+
"default": "./cjs/*.js"
|
|
47
|
+
},
|
|
48
|
+
"import": {
|
|
49
|
+
"types": "./typings/*.d.ts",
|
|
50
|
+
"default": "./esm/*.js"
|
|
51
|
+
},
|
|
52
|
+
"default": {
|
|
53
|
+
"types": "./typings/*.d.ts",
|
|
54
|
+
"default": "./esm/*.js"
|
|
55
|
+
}
|
|
35
56
|
},
|
|
36
57
|
"./package.json": "./package.json"
|
|
37
58
|
}
|
|
38
|
-
}
|
|
59
|
+
}
|
|
File without changes
|