@graphql-tools/merge 8.2.15 → 8.3.0-alpha-b76ec274.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.
Files changed (64) hide show
  1. package/cjs/extensions.js +132 -0
  2. package/cjs/index.js +6 -0
  3. package/cjs/merge-resolvers.js +67 -0
  4. package/cjs/package.json +1 -0
  5. package/cjs/typedefs-mergers/arguments.js +21 -0
  6. package/cjs/typedefs-mergers/directives.js +100 -0
  7. package/cjs/typedefs-mergers/enum-values.js +40 -0
  8. package/cjs/typedefs-mergers/enum.js +27 -0
  9. package/cjs/typedefs-mergers/fields.js +85 -0
  10. package/cjs/typedefs-mergers/index.js +17 -0
  11. package/cjs/typedefs-mergers/input-type.js +34 -0
  12. package/cjs/typedefs-mergers/interface.js +38 -0
  13. package/cjs/typedefs-mergers/merge-named-type-array.js +15 -0
  14. package/cjs/typedefs-mergers/merge-nodes.js +72 -0
  15. package/cjs/typedefs-mergers/merge-typedefs.js +121 -0
  16. package/cjs/typedefs-mergers/scalar.js +27 -0
  17. package/cjs/typedefs-mergers/schema-def.js +39 -0
  18. package/cjs/typedefs-mergers/type.js +36 -0
  19. package/cjs/typedefs-mergers/union.js +28 -0
  20. package/cjs/typedefs-mergers/utils.js +65 -0
  21. package/esm/extensions.js +125 -0
  22. package/esm/index.js +3 -0
  23. package/esm/merge-resolvers.js +63 -0
  24. package/esm/typedefs-mergers/arguments.js +17 -0
  25. package/esm/typedefs-mergers/directives.js +95 -0
  26. package/esm/typedefs-mergers/enum-values.js +36 -0
  27. package/esm/typedefs-mergers/enum.js +23 -0
  28. package/esm/typedefs-mergers/fields.js +81 -0
  29. package/esm/typedefs-mergers/index.js +14 -0
  30. package/esm/typedefs-mergers/input-type.js +30 -0
  31. package/esm/typedefs-mergers/interface.js +34 -0
  32. package/esm/typedefs-mergers/merge-named-type-array.js +11 -0
  33. package/esm/typedefs-mergers/merge-nodes.js +67 -0
  34. package/esm/typedefs-mergers/merge-typedefs.js +116 -0
  35. package/esm/typedefs-mergers/scalar.js +23 -0
  36. package/esm/typedefs-mergers/schema-def.js +35 -0
  37. package/esm/typedefs-mergers/type.js +32 -0
  38. package/esm/typedefs-mergers/union.js +24 -0
  39. package/esm/typedefs-mergers/utils.js +54 -0
  40. package/package.json +32 -11
  41. package/{extensions.d.ts → typings/extensions.d.ts} +0 -0
  42. package/typings/index.d.ts +3 -0
  43. package/{merge-resolvers.d.ts → typings/merge-resolvers.d.ts} +0 -0
  44. package/{typedefs-mergers → typings/typedefs-mergers}/arguments.d.ts +1 -1
  45. package/{typedefs-mergers → typings/typedefs-mergers}/directives.d.ts +1 -1
  46. package/{typedefs-mergers → typings/typedefs-mergers}/enum-values.d.ts +1 -1
  47. package/{typedefs-mergers → typings/typedefs-mergers}/enum.d.ts +1 -1
  48. package/{typedefs-mergers → typings/typedefs-mergers}/fields.d.ts +1 -1
  49. package/typings/typedefs-mergers/index.d.ts +14 -0
  50. package/{typedefs-mergers → typings/typedefs-mergers}/input-type.d.ts +1 -1
  51. package/{typedefs-mergers → typings/typedefs-mergers}/interface.d.ts +1 -1
  52. package/{typedefs-mergers → typings/typedefs-mergers}/merge-named-type-array.d.ts +1 -1
  53. package/{typedefs-mergers → typings/typedefs-mergers}/merge-nodes.d.ts +1 -1
  54. package/{typedefs-mergers → typings/typedefs-mergers}/merge-typedefs.d.ts +1 -1
  55. package/{typedefs-mergers → typings/typedefs-mergers}/scalar.d.ts +1 -1
  56. package/{typedefs-mergers → typings/typedefs-mergers}/schema-def.d.ts +1 -1
  57. package/{typedefs-mergers → typings/typedefs-mergers}/type.d.ts +1 -1
  58. package/{typedefs-mergers → typings/typedefs-mergers}/union.d.ts +1 -1
  59. package/{typedefs-mergers → typings/typedefs-mergers}/utils.d.ts +0 -0
  60. package/README.md +0 -5
  61. package/index.d.ts +0 -3
  62. package/index.js +0 -869
  63. package/index.mjs +0 -837
  64. package/typedefs-mergers/index.d.ts +0 -14
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeGraphQLTypes = exports.mergeTypeDefs = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const utils_js_1 = require("./utils.js");
6
+ const merge_nodes_js_1 = require("./merge-nodes.js");
7
+ const utils_1 = require("@graphql-tools/utils");
8
+ const schema_def_js_1 = require("./schema-def.js");
9
+ function mergeTypeDefs(typeSource, config) {
10
+ (0, utils_1.resetComments)();
11
+ const doc = {
12
+ kind: graphql_1.Kind.DOCUMENT,
13
+ definitions: mergeGraphQLTypes(typeSource, {
14
+ useSchemaDefinition: true,
15
+ forceSchemaDefinition: false,
16
+ throwOnConflict: false,
17
+ commentDescriptions: false,
18
+ ...config,
19
+ }),
20
+ };
21
+ let result;
22
+ if (config === null || config === void 0 ? void 0 : config.commentDescriptions) {
23
+ result = (0, utils_1.printWithComments)(doc);
24
+ }
25
+ else {
26
+ result = doc;
27
+ }
28
+ (0, utils_1.resetComments)();
29
+ return result;
30
+ }
31
+ exports.mergeTypeDefs = mergeTypeDefs;
32
+ function visitTypeSources(typeSource, options, allNodes = [], visitedTypeSources = new Set()) {
33
+ if (typeSource && !visitedTypeSources.has(typeSource)) {
34
+ visitedTypeSources.add(typeSource);
35
+ if (typeof typeSource === 'function') {
36
+ visitTypeSources(typeSource(), options, allNodes, visitedTypeSources);
37
+ }
38
+ else if (Array.isArray(typeSource)) {
39
+ for (const type of typeSource) {
40
+ visitTypeSources(type, options, allNodes, visitedTypeSources);
41
+ }
42
+ }
43
+ else if ((0, graphql_1.isSchema)(typeSource)) {
44
+ const documentNode = (0, utils_1.getDocumentNodeFromSchema)(typeSource, options);
45
+ visitTypeSources(documentNode.definitions, options, allNodes, visitedTypeSources);
46
+ }
47
+ else if ((0, utils_js_1.isStringTypes)(typeSource) || (0, utils_js_1.isSourceTypes)(typeSource)) {
48
+ const documentNode = (0, graphql_1.parse)(typeSource, options);
49
+ visitTypeSources(documentNode.definitions, options, allNodes, visitedTypeSources);
50
+ }
51
+ else if (typeof typeSource === 'object' && (0, graphql_1.isDefinitionNode)(typeSource)) {
52
+ allNodes.push(typeSource);
53
+ }
54
+ else if ((0, utils_1.isDocumentNode)(typeSource)) {
55
+ visitTypeSources(typeSource.definitions, options, allNodes, visitedTypeSources);
56
+ }
57
+ else {
58
+ throw new Error(`typeDefs must contain only strings, documents, schemas, or functions, got ${typeof typeSource}`);
59
+ }
60
+ }
61
+ return allNodes;
62
+ }
63
+ function mergeGraphQLTypes(typeSource, config) {
64
+ var _a, _b, _c;
65
+ (0, utils_1.resetComments)();
66
+ const allNodes = visitTypeSources(typeSource, config);
67
+ const mergedNodes = (0, merge_nodes_js_1.mergeGraphQLNodes)(allNodes, config);
68
+ if (config === null || config === void 0 ? void 0 : config.useSchemaDefinition) {
69
+ // XXX: right now we don't handle multiple schema definitions
70
+ const schemaDef = mergedNodes[merge_nodes_js_1.schemaDefSymbol] || {
71
+ kind: graphql_1.Kind.SCHEMA_DEFINITION,
72
+ operationTypes: [],
73
+ };
74
+ const operationTypes = schemaDef.operationTypes;
75
+ for (const opTypeDefNodeType in schema_def_js_1.DEFAULT_OPERATION_TYPE_NAME_MAP) {
76
+ const opTypeDefNode = operationTypes.find(operationType => operationType.operation === opTypeDefNodeType);
77
+ if (!opTypeDefNode) {
78
+ const possibleRootTypeName = schema_def_js_1.DEFAULT_OPERATION_TYPE_NAME_MAP[opTypeDefNodeType];
79
+ const existingPossibleRootType = mergedNodes[possibleRootTypeName];
80
+ if (existingPossibleRootType != null && existingPossibleRootType.name != null) {
81
+ operationTypes.push({
82
+ kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
83
+ type: {
84
+ kind: graphql_1.Kind.NAMED_TYPE,
85
+ name: existingPossibleRootType.name,
86
+ },
87
+ operation: opTypeDefNodeType,
88
+ });
89
+ }
90
+ }
91
+ }
92
+ if (((_a = schemaDef === null || schemaDef === void 0 ? void 0 : schemaDef.operationTypes) === null || _a === void 0 ? void 0 : _a.length) != null && schemaDef.operationTypes.length > 0) {
93
+ mergedNodes[merge_nodes_js_1.schemaDefSymbol] = schemaDef;
94
+ }
95
+ }
96
+ if ((config === null || config === void 0 ? void 0 : config.forceSchemaDefinition) && !((_c = (_b = mergedNodes[merge_nodes_js_1.schemaDefSymbol]) === null || _b === void 0 ? void 0 : _b.operationTypes) === null || _c === void 0 ? void 0 : _c.length)) {
97
+ mergedNodes[merge_nodes_js_1.schemaDefSymbol] = {
98
+ kind: graphql_1.Kind.SCHEMA_DEFINITION,
99
+ operationTypes: [
100
+ {
101
+ kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
102
+ operation: 'query',
103
+ type: {
104
+ kind: graphql_1.Kind.NAMED_TYPE,
105
+ name: {
106
+ kind: graphql_1.Kind.NAME,
107
+ value: 'Query',
108
+ },
109
+ },
110
+ },
111
+ ],
112
+ };
113
+ }
114
+ const mergedNodeDefinitions = Object.values(mergedNodes);
115
+ if (config === null || config === void 0 ? void 0 : config.sort) {
116
+ const sortFn = typeof config.sort === 'function' ? config.sort : utils_js_1.defaultStringComparator;
117
+ mergedNodeDefinitions.sort((a, b) => { var _a, _b; return sortFn((_a = a.name) === null || _a === void 0 ? void 0 : _a.value, (_b = b.name) === null || _b === void 0 ? void 0 : _b.value); });
118
+ }
119
+ return mergedNodeDefinitions;
120
+ }
121
+ exports.mergeGraphQLTypes = mergeGraphQLTypes;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeScalar = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const directives_js_1 = require("./directives.js");
6
+ function mergeScalar(node, existingNode, config) {
7
+ if (existingNode) {
8
+ return {
9
+ name: node.name,
10
+ description: node['description'] || existingNode['description'],
11
+ kind: (config === null || config === void 0 ? void 0 : config.convertExtensions) ||
12
+ node.kind === 'ScalarTypeDefinition' ||
13
+ existingNode.kind === 'ScalarTypeDefinition'
14
+ ? 'ScalarTypeDefinition'
15
+ : 'ScalarTypeExtension',
16
+ loc: node.loc,
17
+ directives: (0, directives_js_1.mergeDirectives)(node.directives, existingNode.directives, config),
18
+ };
19
+ }
20
+ return (config === null || config === void 0 ? void 0 : config.convertExtensions)
21
+ ? {
22
+ ...node,
23
+ kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
24
+ }
25
+ : node;
26
+ }
27
+ exports.mergeScalar = mergeScalar;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeSchemaDefs = exports.DEFAULT_OPERATION_TYPE_NAME_MAP = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const directives_js_1 = require("./directives.js");
6
+ exports.DEFAULT_OPERATION_TYPE_NAME_MAP = {
7
+ query: 'Query',
8
+ mutation: 'Mutation',
9
+ subscription: 'Subscription',
10
+ };
11
+ function mergeOperationTypes(opNodeList = [], existingOpNodeList = []) {
12
+ const finalOpNodeList = [];
13
+ for (const opNodeType in exports.DEFAULT_OPERATION_TYPE_NAME_MAP) {
14
+ const opNode = opNodeList.find(n => n.operation === opNodeType) || existingOpNodeList.find(n => n.operation === opNodeType);
15
+ if (opNode) {
16
+ finalOpNodeList.push(opNode);
17
+ }
18
+ }
19
+ return finalOpNodeList;
20
+ }
21
+ function mergeSchemaDefs(node, existingNode, config) {
22
+ if (existingNode) {
23
+ return {
24
+ kind: node.kind === graphql_1.Kind.SCHEMA_DEFINITION || existingNode.kind === graphql_1.Kind.SCHEMA_DEFINITION
25
+ ? graphql_1.Kind.SCHEMA_DEFINITION
26
+ : graphql_1.Kind.SCHEMA_EXTENSION,
27
+ description: node['description'] || existingNode['description'],
28
+ directives: (0, directives_js_1.mergeDirectives)(node.directives, existingNode.directives, config),
29
+ operationTypes: mergeOperationTypes(node.operationTypes, existingNode.operationTypes),
30
+ };
31
+ }
32
+ return ((config === null || config === void 0 ? void 0 : config.convertExtensions)
33
+ ? {
34
+ ...node,
35
+ kind: graphql_1.Kind.SCHEMA_DEFINITION,
36
+ }
37
+ : node);
38
+ }
39
+ exports.mergeSchemaDefs = mergeSchemaDefs;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeType = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const fields_js_1 = require("./fields.js");
6
+ const directives_js_1 = require("./directives.js");
7
+ const merge_named_type_array_js_1 = require("./merge-named-type-array.js");
8
+ function mergeType(node, existingNode, config) {
9
+ if (existingNode) {
10
+ try {
11
+ return {
12
+ name: node.name,
13
+ description: node['description'] || existingNode['description'],
14
+ kind: (config === null || config === void 0 ? void 0 : config.convertExtensions) ||
15
+ node.kind === 'ObjectTypeDefinition' ||
16
+ existingNode.kind === 'ObjectTypeDefinition'
17
+ ? 'ObjectTypeDefinition'
18
+ : 'ObjectTypeExtension',
19
+ loc: node.loc,
20
+ fields: (0, fields_js_1.mergeFields)(node, node.fields, existingNode.fields, config),
21
+ directives: (0, directives_js_1.mergeDirectives)(node.directives, existingNode.directives, config),
22
+ interfaces: (0, merge_named_type_array_js_1.mergeNamedTypeArray)(node.interfaces, existingNode.interfaces, config),
23
+ };
24
+ }
25
+ catch (e) {
26
+ throw new Error(`Unable to merge GraphQL type "${node.name.value}": ${e.message}`);
27
+ }
28
+ }
29
+ return (config === null || config === void 0 ? void 0 : config.convertExtensions)
30
+ ? {
31
+ ...node,
32
+ kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
33
+ }
34
+ : node;
35
+ }
36
+ exports.mergeType = mergeType;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeUnion = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const directives_js_1 = require("./directives.js");
6
+ const merge_named_type_array_js_1 = require("./merge-named-type-array.js");
7
+ function mergeUnion(first, second, config) {
8
+ if (second) {
9
+ return {
10
+ name: first.name,
11
+ description: first['description'] || second['description'],
12
+ // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
13
+ directives: (0, directives_js_1.mergeDirectives)(first.directives, second.directives, config),
14
+ kind: (config === null || config === void 0 ? void 0 : config.convertExtensions) || first.kind === 'UnionTypeDefinition' || second.kind === 'UnionTypeDefinition'
15
+ ? graphql_1.Kind.UNION_TYPE_DEFINITION
16
+ : graphql_1.Kind.UNION_TYPE_EXTENSION,
17
+ loc: first.loc,
18
+ types: (0, merge_named_type_array_js_1.mergeNamedTypeArray)(first.types, second.types, config),
19
+ };
20
+ }
21
+ return (config === null || config === void 0 ? void 0 : config.convertExtensions)
22
+ ? {
23
+ ...first,
24
+ kind: graphql_1.Kind.UNION_TYPE_DEFINITION,
25
+ }
26
+ : first;
27
+ }
28
+ exports.mergeUnion = mergeUnion;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultStringComparator = exports.CompareVal = exports.printTypeNode = exports.isNonNullTypeNode = exports.isListTypeNode = exports.isWrappingTypeNode = exports.extractType = exports.isSourceTypes = exports.isStringTypes = void 0;
4
+ const graphql_1 = require("graphql");
5
+ function isStringTypes(types) {
6
+ return typeof types === 'string';
7
+ }
8
+ exports.isStringTypes = isStringTypes;
9
+ function isSourceTypes(types) {
10
+ return types instanceof graphql_1.Source;
11
+ }
12
+ exports.isSourceTypes = isSourceTypes;
13
+ function extractType(type) {
14
+ let visitedType = type;
15
+ while (visitedType.kind === graphql_1.Kind.LIST_TYPE || visitedType.kind === 'NonNullType') {
16
+ visitedType = visitedType.type;
17
+ }
18
+ return visitedType;
19
+ }
20
+ exports.extractType = extractType;
21
+ function isWrappingTypeNode(type) {
22
+ return type.kind !== graphql_1.Kind.NAMED_TYPE;
23
+ }
24
+ exports.isWrappingTypeNode = isWrappingTypeNode;
25
+ function isListTypeNode(type) {
26
+ return type.kind === graphql_1.Kind.LIST_TYPE;
27
+ }
28
+ exports.isListTypeNode = isListTypeNode;
29
+ function isNonNullTypeNode(type) {
30
+ return type.kind === graphql_1.Kind.NON_NULL_TYPE;
31
+ }
32
+ exports.isNonNullTypeNode = isNonNullTypeNode;
33
+ function printTypeNode(type) {
34
+ if (isListTypeNode(type)) {
35
+ return `[${printTypeNode(type.type)}]`;
36
+ }
37
+ if (isNonNullTypeNode(type)) {
38
+ return `${printTypeNode(type.type)}!`;
39
+ }
40
+ return type.name.value;
41
+ }
42
+ exports.printTypeNode = printTypeNode;
43
+ var CompareVal;
44
+ (function (CompareVal) {
45
+ CompareVal[CompareVal["A_SMALLER_THAN_B"] = -1] = "A_SMALLER_THAN_B";
46
+ CompareVal[CompareVal["A_EQUALS_B"] = 0] = "A_EQUALS_B";
47
+ CompareVal[CompareVal["A_GREATER_THAN_B"] = 1] = "A_GREATER_THAN_B";
48
+ })(CompareVal = exports.CompareVal || (exports.CompareVal = {}));
49
+ function defaultStringComparator(a, b) {
50
+ if (a == null && b == null) {
51
+ return CompareVal.A_EQUALS_B;
52
+ }
53
+ if (a == null) {
54
+ return CompareVal.A_SMALLER_THAN_B;
55
+ }
56
+ if (b == null) {
57
+ return CompareVal.A_GREATER_THAN_B;
58
+ }
59
+ if (a < b)
60
+ return CompareVal.A_SMALLER_THAN_B;
61
+ if (a > b)
62
+ return CompareVal.A_GREATER_THAN_B;
63
+ return CompareVal.A_EQUALS_B;
64
+ }
65
+ exports.defaultStringComparator = defaultStringComparator;
@@ -0,0 +1,125 @@
1
+ import { isObjectType, isInterfaceType, isInputObjectType, isUnionType, isScalarType, isEnumType, isSpecifiedScalarType, isIntrospectionType, } from 'graphql';
2
+ import { mergeDeep } from '@graphql-tools/utils';
3
+ export function travelSchemaPossibleExtensions(schema, hooks) {
4
+ hooks.onSchema(schema);
5
+ const typesMap = schema.getTypeMap();
6
+ for (const [, type] of Object.entries(typesMap)) {
7
+ const isPredefinedScalar = isScalarType(type) && isSpecifiedScalarType(type);
8
+ const isIntrospection = isIntrospectionType(type);
9
+ if (isPredefinedScalar || isIntrospection) {
10
+ continue;
11
+ }
12
+ if (isObjectType(type)) {
13
+ hooks.onObjectType(type);
14
+ const fields = type.getFields();
15
+ for (const [, field] of Object.entries(fields)) {
16
+ hooks.onObjectField(type, field);
17
+ const args = field.args || [];
18
+ for (const arg of args) {
19
+ hooks.onObjectFieldArg(type, field, arg);
20
+ }
21
+ }
22
+ }
23
+ else if (isInterfaceType(type)) {
24
+ hooks.onInterface(type);
25
+ const fields = type.getFields();
26
+ for (const [, field] of Object.entries(fields)) {
27
+ hooks.onInterfaceField(type, field);
28
+ const args = field.args || [];
29
+ for (const arg of args) {
30
+ hooks.onInterfaceFieldArg(type, field, arg);
31
+ }
32
+ }
33
+ }
34
+ else if (isInputObjectType(type)) {
35
+ hooks.onInputType(type);
36
+ const fields = type.getFields();
37
+ for (const [, field] of Object.entries(fields)) {
38
+ hooks.onInputFieldType(type, field);
39
+ }
40
+ }
41
+ else if (isUnionType(type)) {
42
+ hooks.onUnion(type);
43
+ }
44
+ else if (isScalarType(type)) {
45
+ hooks.onScalar(type);
46
+ }
47
+ else if (isEnumType(type)) {
48
+ hooks.onEnum(type);
49
+ for (const value of type.getValues()) {
50
+ hooks.onEnumValue(type, value);
51
+ }
52
+ }
53
+ }
54
+ }
55
+ export function mergeExtensions(extensions) {
56
+ return mergeDeep(extensions);
57
+ }
58
+ function applyExtensionObject(obj, extensions) {
59
+ if (!obj) {
60
+ return;
61
+ }
62
+ obj.extensions = mergeDeep([obj.extensions || {}, extensions || {}]);
63
+ }
64
+ export function applyExtensions(schema, extensions) {
65
+ applyExtensionObject(schema, extensions.schemaExtensions);
66
+ for (const [typeName, data] of Object.entries(extensions.types || {})) {
67
+ const type = schema.getType(typeName);
68
+ if (type) {
69
+ applyExtensionObject(type, data.extensions);
70
+ if (data.type === 'object' || data.type === 'interface') {
71
+ for (const [fieldName, fieldData] of Object.entries(data.fields)) {
72
+ const field = type.getFields()[fieldName];
73
+ if (field) {
74
+ applyExtensionObject(field, fieldData.extensions);
75
+ for (const [arg, argData] of Object.entries(fieldData.arguments)) {
76
+ applyExtensionObject(field.args.find(a => a.name === arg), argData);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ else if (data.type === 'input') {
82
+ for (const [fieldName, fieldData] of Object.entries(data.fields)) {
83
+ const field = type.getFields()[fieldName];
84
+ applyExtensionObject(field, fieldData.extensions);
85
+ }
86
+ }
87
+ else if (data.type === 'enum') {
88
+ for (const [valueName, valueData] of Object.entries(data.values)) {
89
+ const value = type.getValue(valueName);
90
+ applyExtensionObject(value, valueData);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return schema;
96
+ }
97
+ export function extractExtensionsFromSchema(schema) {
98
+ const result = {
99
+ schemaExtensions: {},
100
+ types: {},
101
+ };
102
+ travelSchemaPossibleExtensions(schema, {
103
+ onSchema: schema => (result.schemaExtensions = schema.extensions || {}),
104
+ onObjectType: type => (result.types[type.name] = { fields: {}, type: 'object', extensions: type.extensions || {} }),
105
+ onObjectField: (type, field) => (result.types[type.name].fields[field.name] = {
106
+ arguments: {},
107
+ extensions: field.extensions || {},
108
+ }),
109
+ onObjectFieldArg: (type, field, arg) => (result.types[type.name].fields[field.name].arguments[arg.name] = arg.extensions || {}),
110
+ onInterface: type => (result.types[type.name] = { fields: {}, type: 'interface', extensions: type.extensions || {} }),
111
+ onInterfaceField: (type, field) => (result.types[type.name].fields[field.name] = {
112
+ arguments: {},
113
+ extensions: field.extensions || {},
114
+ }),
115
+ onInterfaceFieldArg: (type, field, arg) => (result.types[type.name].fields[field.name].arguments[arg.name] =
116
+ arg.extensions || {}),
117
+ onEnum: type => (result.types[type.name] = { values: {}, type: 'enum', extensions: type.extensions || {} }),
118
+ onEnumValue: (type, value) => (result.types[type.name].values[value.name] = value.extensions || {}),
119
+ onScalar: type => (result.types[type.name] = { type: 'scalar', extensions: type.extensions || {} }),
120
+ onUnion: type => (result.types[type.name] = { type: 'union', extensions: type.extensions || {} }),
121
+ onInputType: type => (result.types[type.name] = { fields: {}, type: 'input', extensions: type.extensions || {} }),
122
+ onInputFieldType: (type, field) => (result.types[type.name].fields[field.name] = { extensions: field.extensions || {} }),
123
+ });
124
+ return result;
125
+ }
package/esm/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './merge-resolvers.js';
2
+ export * from './typedefs-mergers/index.js';
3
+ export * from './extensions.js';
@@ -0,0 +1,63 @@
1
+ import { mergeDeep } from '@graphql-tools/utils';
2
+ /**
3
+ * Deep merges multiple resolver definition objects into a single definition.
4
+ * @param resolversDefinitions Resolver definitions to be merged
5
+ * @param options Additional options
6
+ *
7
+ * ```js
8
+ * const { mergeResolvers } = require('@graphql-tools/merge');
9
+ * const clientResolver = require('./clientResolver');
10
+ * const productResolver = require('./productResolver');
11
+ *
12
+ * const resolvers = mergeResolvers([
13
+ * clientResolver,
14
+ * productResolver,
15
+ * ]);
16
+ * ```
17
+ *
18
+ * If you don't want to manually create the array of resolver objects, you can
19
+ * also use this function along with loadFiles:
20
+ *
21
+ * ```js
22
+ * const path = require('path');
23
+ * const { mergeResolvers } = require('@graphql-tools/merge');
24
+ * const { loadFilesSync } = require('@graphql-tools/load-files');
25
+ *
26
+ * const resolversArray = loadFilesSync(path.join(__dirname, './resolvers'));
27
+ *
28
+ * const resolvers = mergeResolvers(resolversArray)
29
+ * ```
30
+ */
31
+ export function mergeResolvers(resolversDefinitions, options) {
32
+ if (!resolversDefinitions || (Array.isArray(resolversDefinitions) && resolversDefinitions.length === 0)) {
33
+ return {};
34
+ }
35
+ if (!Array.isArray(resolversDefinitions)) {
36
+ return resolversDefinitions;
37
+ }
38
+ if (resolversDefinitions.length === 1) {
39
+ return resolversDefinitions[0] || {};
40
+ }
41
+ const resolvers = new Array();
42
+ for (let resolversDefinition of resolversDefinitions) {
43
+ if (Array.isArray(resolversDefinition)) {
44
+ resolversDefinition = mergeResolvers(resolversDefinition);
45
+ }
46
+ if (typeof resolversDefinition === 'object' && resolversDefinition) {
47
+ resolvers.push(resolversDefinition);
48
+ }
49
+ }
50
+ const result = mergeDeep(resolvers, true);
51
+ if (options === null || options === void 0 ? void 0 : options.exclusions) {
52
+ for (const exclusion of options.exclusions) {
53
+ const [typeName, fieldName] = exclusion.split('.');
54
+ if (!fieldName || fieldName === '*') {
55
+ delete result[typeName];
56
+ }
57
+ else if (result[typeName]) {
58
+ delete result[typeName][fieldName];
59
+ }
60
+ }
61
+ }
62
+ return result;
63
+ }
@@ -0,0 +1,17 @@
1
+ import { compareNodes, isSome } from '@graphql-tools/utils';
2
+ export function mergeArguments(args1, args2, config) {
3
+ const result = deduplicateArguments([...args2, ...args1].filter(isSome));
4
+ if (config && config.sort) {
5
+ result.sort(compareNodes);
6
+ }
7
+ return result;
8
+ }
9
+ function deduplicateArguments(args) {
10
+ return args.reduce((acc, current) => {
11
+ const dup = acc.find(arg => arg.name.value === current.name.value);
12
+ if (!dup) {
13
+ return acc.concat([current]);
14
+ }
15
+ return acc;
16
+ }, []);
17
+ }
@@ -0,0 +1,95 @@
1
+ import { print } from 'graphql';
2
+ import { isSome } from '@graphql-tools/utils';
3
+ function directiveAlreadyExists(directivesArr, otherDirective) {
4
+ return !!directivesArr.find(directive => directive.name.value === otherDirective.name.value);
5
+ }
6
+ function nameAlreadyExists(name, namesArr) {
7
+ return namesArr.some(({ value }) => value === name.value);
8
+ }
9
+ function mergeArguments(a1, a2) {
10
+ const result = [...a2];
11
+ for (const argument of a1) {
12
+ const existingIndex = result.findIndex(a => a.name.value === argument.name.value);
13
+ if (existingIndex > -1) {
14
+ const existingArg = result[existingIndex];
15
+ if (existingArg.value.kind === 'ListValue') {
16
+ const source = existingArg.value.values;
17
+ const target = argument.value.values;
18
+ // merge values of two lists
19
+ existingArg.value.values = deduplicateLists(source, target, (targetVal, source) => {
20
+ const value = targetVal.value;
21
+ return !value || !source.some((sourceVal) => sourceVal.value === value);
22
+ });
23
+ }
24
+ else {
25
+ existingArg.value = argument.value;
26
+ }
27
+ }
28
+ else {
29
+ result.push(argument);
30
+ }
31
+ }
32
+ return result;
33
+ }
34
+ function deduplicateDirectives(directives) {
35
+ return directives
36
+ .map((directive, i, all) => {
37
+ const firstAt = all.findIndex(d => d.name.value === directive.name.value);
38
+ if (firstAt !== i) {
39
+ const dup = all[firstAt];
40
+ directive.arguments = mergeArguments(directive.arguments, dup.arguments);
41
+ return null;
42
+ }
43
+ return directive;
44
+ })
45
+ .filter(isSome);
46
+ }
47
+ export function mergeDirectives(d1 = [], d2 = [], config) {
48
+ const reverseOrder = config && config.reverseDirectives;
49
+ const asNext = reverseOrder ? d1 : d2;
50
+ const asFirst = reverseOrder ? d2 : d1;
51
+ const result = deduplicateDirectives([...asNext]);
52
+ for (const directive of asFirst) {
53
+ if (directiveAlreadyExists(result, directive)) {
54
+ const existingDirectiveIndex = result.findIndex(d => d.name.value === directive.name.value);
55
+ const existingDirective = result[existingDirectiveIndex];
56
+ result[existingDirectiveIndex].arguments = mergeArguments(directive.arguments || [], existingDirective.arguments || []);
57
+ }
58
+ else {
59
+ result.push(directive);
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ function validateInputs(node, existingNode) {
65
+ const printedNode = print({
66
+ ...node,
67
+ description: undefined,
68
+ });
69
+ const printedExistingNode = print({
70
+ ...existingNode,
71
+ description: undefined,
72
+ });
73
+ // eslint-disable-next-line
74
+ const leaveInputs = new RegExp('(directive @w*d*)|( on .*$)', 'g');
75
+ const sameArguments = printedNode.replace(leaveInputs, '') === printedExistingNode.replace(leaveInputs, '');
76
+ if (!sameArguments) {
77
+ throw new Error(`Unable to merge GraphQL directive "${node.name.value}". \nExisting directive: \n\t${printedExistingNode} \nReceived directive: \n\t${printedNode}`);
78
+ }
79
+ }
80
+ export function mergeDirective(node, existingNode) {
81
+ if (existingNode) {
82
+ validateInputs(node, existingNode);
83
+ return {
84
+ ...node,
85
+ locations: [
86
+ ...existingNode.locations,
87
+ ...node.locations.filter(name => !nameAlreadyExists(name, existingNode.locations)),
88
+ ],
89
+ };
90
+ }
91
+ return node;
92
+ }
93
+ function deduplicateLists(source, target, filterFn) {
94
+ return source.concat(target.filter(val => filterFn(val, source)));
95
+ }
@@ -0,0 +1,36 @@
1
+ import { mergeDirectives } from './directives.js';
2
+ import { compareNodes } from '@graphql-tools/utils';
3
+ export function mergeEnumValues(first, second, config) {
4
+ if (config === null || config === void 0 ? void 0 : config.consistentEnumMerge) {
5
+ const reversed = [];
6
+ if (first) {
7
+ reversed.push(...first);
8
+ }
9
+ first = second;
10
+ second = reversed;
11
+ }
12
+ const enumValueMap = new Map();
13
+ if (first) {
14
+ for (const firstValue of first) {
15
+ enumValueMap.set(firstValue.name.value, firstValue);
16
+ }
17
+ }
18
+ if (second) {
19
+ for (const secondValue of second) {
20
+ const enumValue = secondValue.name.value;
21
+ if (enumValueMap.has(enumValue)) {
22
+ const firstValue = enumValueMap.get(enumValue);
23
+ firstValue.description = secondValue.description || firstValue.description;
24
+ firstValue.directives = mergeDirectives(secondValue.directives, firstValue.directives);
25
+ }
26
+ else {
27
+ enumValueMap.set(enumValue, secondValue);
28
+ }
29
+ }
30
+ }
31
+ const result = [...enumValueMap.values()];
32
+ if (config && config.sort) {
33
+ result.sort(compareNodes);
34
+ }
35
+ return result;
36
+ }