@graphql-tools/delegate 9.0.0-alpha-e2ab84c8.0 → 9.0.0-alpha-25204a2f.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 (61) hide show
  1. package/README.md +0 -2
  2. package/cjs/Subschema.js +22 -0
  3. package/cjs/Transformer.js +45 -0
  4. package/cjs/applySchemaTransforms.js +11 -0
  5. package/cjs/checkResultAndHandleErrors.js +77 -0
  6. package/cjs/createRequest.js +125 -0
  7. package/cjs/defaultMergedResolver.js +29 -0
  8. package/cjs/delegateToSchema.js +148 -0
  9. package/cjs/finalizeGatewayRequest.js +317 -0
  10. package/cjs/getDocumentMetadata.js +25 -0
  11. package/cjs/index.js +13 -0
  12. package/cjs/mergeFields.js +87 -0
  13. package/cjs/package.json +1 -0
  14. package/cjs/prepareGatewayDocument.js +311 -0
  15. package/cjs/resolveExternalValue.js +103 -0
  16. package/cjs/subschemaConfig.js +31 -0
  17. package/cjs/symbols.js +6 -0
  18. package/cjs/types.js +3 -0
  19. package/esm/Subschema.js +17 -0
  20. package/esm/Transformer.js +41 -0
  21. package/esm/applySchemaTransforms.js +7 -0
  22. package/esm/checkResultAndHandleErrors.js +72 -0
  23. package/esm/createRequest.js +120 -0
  24. package/esm/defaultMergedResolver.js +25 -0
  25. package/esm/delegateToSchema.js +143 -0
  26. package/esm/finalizeGatewayRequest.js +313 -0
  27. package/esm/getDocumentMetadata.js +21 -0
  28. package/esm/index.js +10 -0
  29. package/esm/mergeFields.js +79 -0
  30. package/esm/prepareGatewayDocument.js +307 -0
  31. package/esm/resolveExternalValue.js +99 -0
  32. package/esm/subschemaConfig.js +26 -0
  33. package/esm/symbols.js +3 -0
  34. package/esm/types.js +1 -0
  35. package/package.json +40 -18
  36. package/{Subschema.d.ts → typings/Subschema.d.ts} +7 -3
  37. package/{Transformer.d.ts → typings/Transformer.d.ts} +3 -3
  38. package/{applySchemaTransforms.d.ts → typings/applySchemaTransforms.d.ts} +2 -2
  39. package/typings/checkResultAndHandleErrors.d.ts +8 -0
  40. package/{createRequest.d.ts → typings/createRequest.d.ts} +1 -2
  41. package/{defaultMergedResolver.d.ts → typings/defaultMergedResolver.d.ts} +2 -4
  42. package/typings/delegateToSchema.d.ts +6 -0
  43. package/typings/finalizeGatewayRequest.d.ts +3 -0
  44. package/{getDocumentMetadata.d.ts → typings/getDocumentMetadata.d.ts} +0 -0
  45. package/typings/index.d.ts +10 -0
  46. package/typings/mergeFields.d.ts +8 -0
  47. package/{prepareGatewayDocument.d.ts → typings/prepareGatewayDocument.d.ts} +0 -0
  48. package/typings/resolveExternalValue.d.ts +3 -0
  49. package/{subschemaConfig.d.ts → typings/subschemaConfig.d.ts} +1 -1
  50. package/typings/symbols.d.ts +3 -0
  51. package/{types.d.ts → typings/types.d.ts} +21 -40
  52. package/delegateToSchema.d.ts +0 -9
  53. package/externalObjects.d.ts +0 -11
  54. package/externalValues.d.ts +0 -4
  55. package/finalizeGatewayRequest.d.ts +0 -3
  56. package/getMergedParent.d.ts +0 -9
  57. package/index.d.ts +0 -11
  58. package/index.js +0 -1624
  59. package/index.mjs +0 -1590
  60. package/mergeDataAndErrors.d.ts +0 -5
  61. package/symbols.d.ts +0 -7
@@ -0,0 +1,120 @@
1
+ import { Kind, typeFromAST, } from 'graphql';
2
+ import { createVariableNameGenerator, serializeInputValue, updateArgument, } from '@graphql-tools/utils';
3
+ export function getDelegatingOperation(parentType, schema) {
4
+ if (parentType === schema.getMutationType()) {
5
+ return 'mutation';
6
+ }
7
+ else if (parentType === schema.getSubscriptionType()) {
8
+ return 'subscription';
9
+ }
10
+ return 'query';
11
+ }
12
+ export function createRequest({ sourceSchema, sourceParentType, sourceFieldName, fragments, variableDefinitions, variableValues, targetRootValue, targetOperationName, targetOperation, targetFieldName, selectionSet, fieldNodes, context, info, }) {
13
+ var _a, _b;
14
+ let newSelectionSet;
15
+ const argumentNodeMap = Object.create(null);
16
+ if (selectionSet != null) {
17
+ newSelectionSet = selectionSet;
18
+ }
19
+ else {
20
+ const selections = [];
21
+ for (const fieldNode of fieldNodes || []) {
22
+ if (fieldNode.selectionSet) {
23
+ for (const selection of fieldNode.selectionSet.selections) {
24
+ selections.push(selection);
25
+ }
26
+ }
27
+ }
28
+ newSelectionSet = selections.length
29
+ ? {
30
+ kind: Kind.SELECTION_SET,
31
+ selections,
32
+ }
33
+ : undefined;
34
+ const args = (_a = fieldNodes === null || fieldNodes === void 0 ? void 0 : fieldNodes[0]) === null || _a === void 0 ? void 0 : _a.arguments;
35
+ if (args) {
36
+ for (const argNode of args) {
37
+ argumentNodeMap[argNode.name.value] = argNode;
38
+ }
39
+ }
40
+ }
41
+ const newVariables = Object.create(null);
42
+ const variableDefinitionMap = Object.create(null);
43
+ if (sourceSchema != null && variableDefinitions != null) {
44
+ for (const def of variableDefinitions) {
45
+ const varName = def.variable.name.value;
46
+ variableDefinitionMap[varName] = def;
47
+ const varType = typeFromAST(sourceSchema, def.type);
48
+ const serializedValue = serializeInputValue(varType, variableValues === null || variableValues === void 0 ? void 0 : variableValues[varName]);
49
+ if (serializedValue !== undefined) {
50
+ newVariables[varName] = serializedValue;
51
+ }
52
+ }
53
+ }
54
+ if (sourceParentType != null && sourceFieldName != null) {
55
+ updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, newVariables);
56
+ }
57
+ const rootFieldName = targetFieldName !== null && targetFieldName !== void 0 ? targetFieldName : (_b = fieldNodes === null || fieldNodes === void 0 ? void 0 : fieldNodes[0]) === null || _b === void 0 ? void 0 : _b.name.value;
58
+ if (rootFieldName === undefined) {
59
+ throw new Error(`Either "targetFieldName" or a non empty "fieldNodes" array must be provided.`);
60
+ }
61
+ const rootfieldNode = {
62
+ kind: Kind.FIELD,
63
+ arguments: Object.values(argumentNodeMap),
64
+ name: {
65
+ kind: Kind.NAME,
66
+ value: rootFieldName,
67
+ },
68
+ selectionSet: newSelectionSet,
69
+ };
70
+ const operationName = targetOperationName
71
+ ? {
72
+ kind: Kind.NAME,
73
+ value: targetOperationName,
74
+ }
75
+ : undefined;
76
+ const operationDefinition = {
77
+ kind: Kind.OPERATION_DEFINITION,
78
+ name: operationName,
79
+ operation: targetOperation,
80
+ variableDefinitions: Object.values(variableDefinitionMap),
81
+ selectionSet: {
82
+ kind: Kind.SELECTION_SET,
83
+ selections: [rootfieldNode],
84
+ },
85
+ };
86
+ const definitions = [operationDefinition];
87
+ if (fragments != null) {
88
+ for (const fragmentName in fragments) {
89
+ const fragment = fragments[fragmentName];
90
+ definitions.push(fragment);
91
+ }
92
+ }
93
+ const document = {
94
+ kind: Kind.DOCUMENT,
95
+ definitions,
96
+ };
97
+ return {
98
+ document,
99
+ variables: newVariables,
100
+ rootValue: targetRootValue,
101
+ operationName: targetOperationName,
102
+ context,
103
+ info,
104
+ operationType: targetOperation,
105
+ };
106
+ }
107
+ function updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, variableValues) {
108
+ const generateVariableName = createVariableNameGenerator(variableDefinitionMap);
109
+ const sourceField = sourceParentType.getFields()[sourceFieldName];
110
+ for (const argument of sourceField.args) {
111
+ const argName = argument.name;
112
+ const sourceArgType = argument.type;
113
+ if (argumentNodeMap[argName] === undefined) {
114
+ const defaultValue = argument.defaultValue;
115
+ if (defaultValue !== undefined) {
116
+ updateArgument(argumentNodeMap, variableDefinitionMap, variableValues, argName, generateVariableName(argName), sourceArgType, serializeInputValue(sourceArgType, defaultValue));
117
+ }
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,25 @@
1
+ import { defaultFieldResolver } from 'graphql';
2
+ import { getResponseKeyFromInfo } from '@graphql-tools/utils';
3
+ import { resolveExternalValue } from './resolveExternalValue.js';
4
+ import { getSubschema, getUnpathedErrors, isExternalObject } from './mergeFields.js';
5
+ /**
6
+ * Resolver that knows how to:
7
+ * a) handle aliases for proxied schemas
8
+ * b) handle errors from proxied schemas
9
+ * c) handle external to internal enum conversion
10
+ */
11
+ export function defaultMergedResolver(parent, args, context, info) {
12
+ if (!parent) {
13
+ return null;
14
+ }
15
+ const responseKey = getResponseKeyFromInfo(info);
16
+ // check to see if parent is not a proxied result, i.e. if parent resolver was manually overwritten
17
+ // See https://github.com/ardatan/graphql-tools/issues/967
18
+ if (!isExternalObject(parent)) {
19
+ return defaultFieldResolver(parent, args, context, info);
20
+ }
21
+ const data = parent[responseKey];
22
+ const unpathedErrors = getUnpathedErrors(parent);
23
+ const subschema = getSubschema(parent, responseKey);
24
+ return resolveExternalValue(data, unpathedErrors, subschema, context, info);
25
+ }
@@ -0,0 +1,143 @@
1
+ import { validate, subscribe, execute, } from 'graphql';
2
+ import { ValueOrPromise } from 'value-or-promise';
3
+ import { getBatchingExecutor } from '@graphql-tools/batch-execute';
4
+ import { mapAsyncIterator, AggregateError, isAsyncIterable, getDefinedRootType, memoize1, getOperationASTFromRequest, } from '@graphql-tools/utils';
5
+ import { isSubschemaConfig } from './subschemaConfig.js';
6
+ import { Subschema } from './Subschema.js';
7
+ import { createRequest, getDelegatingOperation } from './createRequest.js';
8
+ import { Transformer } from './Transformer.js';
9
+ import { applySchemaTransforms } from './applySchemaTransforms.js';
10
+ export function delegateToSchema(options) {
11
+ var _a, _b;
12
+ const { info, schema, rootValue = (_a = schema.rootValue) !== null && _a !== void 0 ? _a : info.rootValue, operationName = (_b = info.operation.name) === null || _b === void 0 ? void 0 : _b.value, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes = info.fieldNodes, context, } = options;
13
+ const request = createRequest({
14
+ sourceSchema: info.schema,
15
+ sourceParentType: info.parentType,
16
+ sourceFieldName: info.fieldName,
17
+ fragments: info.fragments,
18
+ variableDefinitions: info.operation.variableDefinitions,
19
+ variableValues: info.variableValues,
20
+ targetRootValue: rootValue,
21
+ targetOperationName: operationName,
22
+ targetOperation: operation,
23
+ targetFieldName: fieldName,
24
+ selectionSet,
25
+ fieldNodes,
26
+ context,
27
+ info,
28
+ });
29
+ return delegateRequest({
30
+ ...options,
31
+ request,
32
+ });
33
+ }
34
+ function getDelegationReturnType(targetSchema, operation, fieldName) {
35
+ const rootType = getDefinedRootType(targetSchema, operation);
36
+ return rootType.getFields()[fieldName].type;
37
+ }
38
+ export function delegateRequest(options) {
39
+ const delegationContext = getDelegationContext(options);
40
+ const transformer = new Transformer(delegationContext);
41
+ const processedRequest = transformer.transformRequest(options.request);
42
+ if (options.validateRequest) {
43
+ validateRequest(delegationContext, processedRequest.document);
44
+ }
45
+ const executor = getExecutor(delegationContext);
46
+ return new ValueOrPromise(() => executor(processedRequest))
47
+ .then(originalResult => {
48
+ if (isAsyncIterable(originalResult)) {
49
+ const iterator = originalResult[Symbol.asyncIterator]();
50
+ // "subscribe" to the subscription result and map the result through the transforms
51
+ return mapAsyncIterator(iterator, result => transformer.transformResult(result));
52
+ }
53
+ return transformer.transformResult(originalResult);
54
+ })
55
+ .resolve();
56
+ }
57
+ function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema, skipTypeMerging = false, }) {
58
+ var _a, _b, _c, _d;
59
+ const operationDefinition = getOperationASTFromRequest(request);
60
+ let targetFieldName;
61
+ if (fieldName == null) {
62
+ targetFieldName = operationDefinition.selectionSet.selections[0].name.value;
63
+ }
64
+ else {
65
+ targetFieldName = fieldName;
66
+ }
67
+ const stitchingInfo = (_a = info === null || info === void 0 ? void 0 : info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
68
+ const subschemaOrSubschemaConfig = (_b = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.subschemaMap.get(schema)) !== null && _b !== void 0 ? _b : schema;
69
+ const operation = operationDefinition.operation;
70
+ if (isSubschemaConfig(subschemaOrSubschemaConfig)) {
71
+ const targetSchema = subschemaOrSubschemaConfig.schema;
72
+ return {
73
+ subschema: schema,
74
+ subschemaConfig: subschemaOrSubschemaConfig,
75
+ targetSchema,
76
+ operation,
77
+ fieldName: targetFieldName,
78
+ args,
79
+ context: request.context,
80
+ info,
81
+ returnType: (_c = returnType !== null && returnType !== void 0 ? returnType : info === null || info === void 0 ? void 0 : info.returnType) !== null && _c !== void 0 ? _c : getDelegationReturnType(targetSchema, operation, targetFieldName),
82
+ transforms: subschemaOrSubschemaConfig.transforms != null
83
+ ? subschemaOrSubschemaConfig.transforms.concat(transforms)
84
+ : transforms,
85
+ transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : (subschemaOrSubschemaConfig instanceof Subschema
86
+ ? subschemaOrSubschemaConfig.transformedSchema
87
+ : applySchemaTransforms(targetSchema, subschemaOrSubschemaConfig)),
88
+ skipTypeMerging,
89
+ };
90
+ }
91
+ return {
92
+ subschema: schema,
93
+ subschemaConfig: undefined,
94
+ targetSchema: subschemaOrSubschemaConfig,
95
+ operation,
96
+ fieldName: targetFieldName,
97
+ args,
98
+ context: request.context,
99
+ info,
100
+ returnType: (_d = returnType !== null && returnType !== void 0 ? returnType : info === null || info === void 0 ? void 0 : info.returnType) !== null && _d !== void 0 ? _d : getDelegationReturnType(subschemaOrSubschemaConfig, operation, targetFieldName),
101
+ transforms,
102
+ transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : subschemaOrSubschemaConfig,
103
+ skipTypeMerging,
104
+ };
105
+ }
106
+ function validateRequest(delegationContext, document) {
107
+ const errors = validate(delegationContext.targetSchema, document);
108
+ if (errors.length > 0) {
109
+ if (errors.length > 1) {
110
+ const combinedError = new AggregateError(errors, errors.map(error => error.message).join(', \n'));
111
+ throw combinedError;
112
+ }
113
+ const error = errors[0];
114
+ throw error.originalError || error;
115
+ }
116
+ }
117
+ const GLOBAL_CONTEXT = {};
118
+ function getExecutor(delegationContext) {
119
+ const { subschemaConfig, targetSchema, context } = delegationContext;
120
+ let executor = (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.executor) || createDefaultExecutor(targetSchema);
121
+ if (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batch) {
122
+ const batchingOptions = subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batchingOptions;
123
+ executor = getBatchingExecutor(context !== null && context !== void 0 ? context : GLOBAL_CONTEXT, executor, batchingOptions === null || batchingOptions === void 0 ? void 0 : batchingOptions.dataLoaderOptions, batchingOptions === null || batchingOptions === void 0 ? void 0 : batchingOptions.extensionsReducer);
124
+ }
125
+ return executor;
126
+ }
127
+ export const createDefaultExecutor = memoize1(function createDefaultExecutor(schema) {
128
+ return function defaultExecutor(request) {
129
+ const executionArgs = {
130
+ schema,
131
+ document: request.document,
132
+ rootValue: request.rootValue,
133
+ contextValue: request.context,
134
+ variableValues: request.variables,
135
+ operationName: request.operationName,
136
+ };
137
+ const operationType = request.operationType || getOperationASTFromRequest(request).operation;
138
+ if (operationType === 'subscription') {
139
+ return subscribe(executionArgs);
140
+ }
141
+ return execute(executionArgs);
142
+ };
143
+ });
@@ -0,0 +1,313 @@
1
+ import { getNamedType, isAbstractType, isInterfaceType, isObjectType, Kind, TypeInfo, TypeNameMetaFieldDef, versionInfo as graphqlVersionInfo, visit, visitWithTypeInfo, } from 'graphql';
2
+ import { getDefinedRootType, serializeInputValue, updateArgument, createVariableNameGenerator, implementsAbstractType, inspect, } from '@graphql-tools/utils';
3
+ import { getDocumentMetadata } from './getDocumentMetadata.js';
4
+ function finalizeGatewayDocument(targetSchema, fragments, operations) {
5
+ var _a;
6
+ let usedVariables = [];
7
+ let usedFragments = [];
8
+ const newOperations = [];
9
+ let newFragments = [];
10
+ const validFragments = [];
11
+ const validFragmentsWithType = Object.create(null);
12
+ for (const fragment of fragments) {
13
+ const typeName = fragment.typeCondition.name.value;
14
+ const type = targetSchema.getType(typeName);
15
+ if (type != null) {
16
+ validFragments.push(fragment);
17
+ validFragmentsWithType[fragment.name.value] = type;
18
+ }
19
+ }
20
+ let fragmentSet = Object.create(null);
21
+ for (const operation of operations) {
22
+ const type = getDefinedRootType(targetSchema, operation.operation);
23
+ const { selectionSet, usedFragments: operationUsedFragments, usedVariables: operationUsedVariables, } = finalizeSelectionSet(targetSchema, type, validFragmentsWithType, operation.selectionSet);
24
+ usedFragments = union(usedFragments, operationUsedFragments);
25
+ const { usedVariables: collectedUsedVariables, newFragments: collectedNewFragments, fragmentSet: collectedFragmentSet, } = collectFragmentVariables(targetSchema, fragmentSet, validFragments, validFragmentsWithType, usedFragments);
26
+ const operationOrFragmentVariables = union(operationUsedVariables, collectedUsedVariables);
27
+ usedVariables = union(usedVariables, operationOrFragmentVariables);
28
+ newFragments = collectedNewFragments;
29
+ fragmentSet = collectedFragmentSet;
30
+ const variableDefinitions = ((_a = operation.variableDefinitions) !== null && _a !== void 0 ? _a : []).filter((variable) => operationOrFragmentVariables.indexOf(variable.variable.name.value) !== -1);
31
+ newOperations.push({
32
+ kind: Kind.OPERATION_DEFINITION,
33
+ operation: operation.operation,
34
+ name: operation.name,
35
+ directives: operation.directives,
36
+ variableDefinitions,
37
+ selectionSet,
38
+ });
39
+ }
40
+ const newDocument = {
41
+ kind: Kind.DOCUMENT,
42
+ definitions: [...newOperations, ...newFragments],
43
+ };
44
+ return {
45
+ usedVariables,
46
+ newDocument,
47
+ };
48
+ }
49
+ export function finalizeGatewayRequest(originalRequest, delegationContext) {
50
+ let { document, variables } = originalRequest;
51
+ let { operations, fragments } = getDocumentMetadata(document);
52
+ const { targetSchema, args } = delegationContext;
53
+ if (args) {
54
+ const requestWithNewVariables = addVariablesToRootFields(targetSchema, operations, args);
55
+ operations = requestWithNewVariables.newOperations;
56
+ variables = Object.assign({}, variables !== null && variables !== void 0 ? variables : {}, requestWithNewVariables.newVariables);
57
+ }
58
+ const { usedVariables, newDocument } = finalizeGatewayDocument(targetSchema, fragments, operations);
59
+ const newVariables = {};
60
+ if (variables != null) {
61
+ for (const variableName of usedVariables) {
62
+ const variableValue = variables[variableName];
63
+ if (variableValue !== undefined) {
64
+ newVariables[variableName] = variableValue;
65
+ }
66
+ }
67
+ }
68
+ return {
69
+ ...originalRequest,
70
+ document: newDocument,
71
+ variables: newVariables,
72
+ };
73
+ }
74
+ function addVariablesToRootFields(targetSchema, operations, args) {
75
+ const newVariables = Object.create(null);
76
+ const newOperations = operations.map((operation) => {
77
+ var _a, _b;
78
+ const variableDefinitionMap = ((_a = operation.variableDefinitions) !== null && _a !== void 0 ? _a : []).reduce((prev, def) => ({
79
+ ...prev,
80
+ [def.variable.name.value]: def,
81
+ }), {});
82
+ const type = getDefinedRootType(targetSchema, operation.operation);
83
+ const newSelections = [];
84
+ for (const selection of operation.selectionSet.selections) {
85
+ if (selection.kind === Kind.FIELD) {
86
+ const argumentNodes = (_b = selection.arguments) !== null && _b !== void 0 ? _b : [];
87
+ const argumentNodeMap = argumentNodes.reduce((prev, argument) => ({
88
+ ...prev,
89
+ [argument.name.value]: argument,
90
+ }), {});
91
+ const targetField = type.getFields()[selection.name.value];
92
+ // excludes __typename
93
+ if (targetField != null) {
94
+ updateArguments(targetField, argumentNodeMap, variableDefinitionMap, newVariables, args);
95
+ }
96
+ newSelections.push({
97
+ ...selection,
98
+ arguments: Object.values(argumentNodeMap),
99
+ });
100
+ }
101
+ else {
102
+ newSelections.push(selection);
103
+ }
104
+ }
105
+ const newSelectionSet = {
106
+ kind: Kind.SELECTION_SET,
107
+ selections: newSelections,
108
+ };
109
+ return {
110
+ ...operation,
111
+ variableDefinitions: Object.values(variableDefinitionMap),
112
+ selectionSet: newSelectionSet,
113
+ };
114
+ });
115
+ return {
116
+ newOperations,
117
+ newVariables,
118
+ };
119
+ }
120
+ function updateArguments(targetField, argumentNodeMap, variableDefinitionMap, variableValues, newArgs) {
121
+ const generateVariableName = createVariableNameGenerator(variableDefinitionMap);
122
+ for (const argument of targetField.args) {
123
+ const argName = argument.name;
124
+ const argType = argument.type;
125
+ if (argName in newArgs) {
126
+ updateArgument(argumentNodeMap, variableDefinitionMap, variableValues, argName, generateVariableName(argName), argType, serializeInputValue(argType, newArgs[argName]));
127
+ }
128
+ }
129
+ }
130
+ function collectFragmentVariables(targetSchema, fragmentSet, validFragments, validFragmentsWithType, usedFragments) {
131
+ let remainingFragments = usedFragments.slice();
132
+ let usedVariables = [];
133
+ const newFragments = [];
134
+ while (remainingFragments.length !== 0) {
135
+ const nextFragmentName = remainingFragments.pop();
136
+ const fragment = validFragments.find(fr => fr.name.value === nextFragmentName);
137
+ if (fragment != null) {
138
+ const name = nextFragmentName;
139
+ const typeName = fragment.typeCondition.name.value;
140
+ const type = targetSchema.getType(typeName);
141
+ if (type == null) {
142
+ throw new Error(`Fragment reference type "${typeName}", but the type is not contained within the target schema.`);
143
+ }
144
+ const { selectionSet, usedFragments: fragmentUsedFragments, usedVariables: fragmentUsedVariables, } = finalizeSelectionSet(targetSchema, type, validFragmentsWithType, fragment.selectionSet);
145
+ remainingFragments = union(remainingFragments, fragmentUsedFragments);
146
+ usedVariables = union(usedVariables, fragmentUsedVariables);
147
+ if (name && !(name in fragmentSet)) {
148
+ fragmentSet[name] = true;
149
+ newFragments.push({
150
+ kind: Kind.FRAGMENT_DEFINITION,
151
+ name: {
152
+ kind: Kind.NAME,
153
+ value: name,
154
+ },
155
+ typeCondition: fragment.typeCondition,
156
+ selectionSet,
157
+ });
158
+ }
159
+ }
160
+ }
161
+ return {
162
+ usedVariables,
163
+ newFragments,
164
+ fragmentSet,
165
+ };
166
+ }
167
+ const filteredSelectionSetVisitorKeys = {
168
+ SelectionSet: ['selections'],
169
+ Field: ['selectionSet'],
170
+ InlineFragment: ['selectionSet'],
171
+ FragmentDefinition: ['selectionSet'],
172
+ };
173
+ const variablesVisitorKeys = {
174
+ SelectionSet: ['selections'],
175
+ Field: ['arguments', 'directives', 'selectionSet'],
176
+ Argument: ['value'],
177
+ InlineFragment: ['directives', 'selectionSet'],
178
+ FragmentSpread: ['directives'],
179
+ FragmentDefinition: ['selectionSet'],
180
+ ObjectValue: ['fields'],
181
+ ObjectField: ['name', 'value'],
182
+ Directive: ['arguments'],
183
+ ListValue: ['values'],
184
+ };
185
+ function finalizeSelectionSet(schema, type, validFragments, selectionSet) {
186
+ const usedFragments = [];
187
+ const usedVariables = [];
188
+ const typeInfo = graphqlVersionInfo.major < 16 ? new TypeInfo(schema, undefined, type) : new TypeInfo(schema, type);
189
+ const filteredSelectionSet = visit(selectionSet, visitWithTypeInfo(typeInfo, {
190
+ [Kind.FIELD]: {
191
+ enter: node => {
192
+ const parentType = typeInfo.getParentType();
193
+ if (isObjectType(parentType) || isInterfaceType(parentType)) {
194
+ const fields = parentType.getFields();
195
+ const field = node.name.value === '__typename' ? TypeNameMetaFieldDef : fields[node.name.value];
196
+ if (!field) {
197
+ return null;
198
+ }
199
+ const args = field.args != null ? field.args : [];
200
+ const argsMap = Object.create(null);
201
+ for (const arg of args) {
202
+ argsMap[arg.name] = arg;
203
+ }
204
+ if (node.arguments != null) {
205
+ const newArgs = [];
206
+ for (const arg of node.arguments) {
207
+ if (arg.name.value in argsMap) {
208
+ newArgs.push(arg);
209
+ }
210
+ }
211
+ if (newArgs.length !== node.arguments.length) {
212
+ return {
213
+ ...node,
214
+ arguments: newArgs,
215
+ };
216
+ }
217
+ }
218
+ }
219
+ },
220
+ leave: node => {
221
+ const type = typeInfo.getType();
222
+ if (type == null) {
223
+ throw new Error(`No type was found for field node ${inspect(node)}.`);
224
+ }
225
+ const namedType = getNamedType(type);
226
+ if (!schema.getType(namedType.name) == null) {
227
+ return null;
228
+ }
229
+ if (isObjectType(namedType) || isInterfaceType(namedType)) {
230
+ const selections = node.selectionSet != null ? node.selectionSet.selections : null;
231
+ if (selections == null || selections.length === 0) {
232
+ return null;
233
+ }
234
+ }
235
+ },
236
+ },
237
+ [Kind.FRAGMENT_SPREAD]: {
238
+ enter: node => {
239
+ if (!(node.name.value in validFragments)) {
240
+ return null;
241
+ }
242
+ const parentType = typeInfo.getParentType();
243
+ const innerType = validFragments[node.name.value];
244
+ if (!implementsAbstractType(schema, parentType, innerType)) {
245
+ return null;
246
+ }
247
+ usedFragments.push(node.name.value);
248
+ },
249
+ },
250
+ [Kind.INLINE_FRAGMENT]: {
251
+ enter: node => {
252
+ if (node.typeCondition != null) {
253
+ const parentType = typeInfo.getParentType();
254
+ const innerType = schema.getType(node.typeCondition.name.value);
255
+ if (!implementsAbstractType(schema, parentType, innerType)) {
256
+ return null;
257
+ }
258
+ }
259
+ },
260
+ },
261
+ [Kind.SELECTION_SET]: {
262
+ leave: node => {
263
+ const parentType = typeInfo.getParentType();
264
+ if (parentType != null && isAbstractType(parentType)) {
265
+ const selections = node.selections.concat([
266
+ {
267
+ kind: Kind.FIELD,
268
+ name: {
269
+ kind: Kind.NAME,
270
+ value: '__typename',
271
+ },
272
+ },
273
+ ]);
274
+ return {
275
+ ...node,
276
+ selections,
277
+ };
278
+ }
279
+ },
280
+ },
281
+ }),
282
+ // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
283
+ // empty keys cannot be removed only because of typescript errors
284
+ // will hopefully be fixed in future version of graphql-js to be optional
285
+ filteredSelectionSetVisitorKeys);
286
+ visit(filteredSelectionSet, {
287
+ [Kind.VARIABLE]: variableNode => {
288
+ usedVariables.push(variableNode.name.value);
289
+ },
290
+ },
291
+ // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
292
+ // empty keys cannot be removed only because of typescript errors
293
+ // will hopefully be fixed in future version of graphql-js to be optional
294
+ variablesVisitorKeys);
295
+ return {
296
+ selectionSet: filteredSelectionSet,
297
+ usedFragments,
298
+ usedVariables,
299
+ };
300
+ }
301
+ function union(...arrays) {
302
+ const cache = Object.create(null);
303
+ const result = [];
304
+ for (const array of arrays) {
305
+ for (const item of array) {
306
+ if (!(item in cache)) {
307
+ cache[item] = true;
308
+ result.push(item);
309
+ }
310
+ }
311
+ }
312
+ return result;
313
+ }
@@ -0,0 +1,21 @@
1
+ import { Kind } from 'graphql';
2
+ export function getDocumentMetadata(document) {
3
+ const operations = [];
4
+ const fragments = [];
5
+ const fragmentNames = new Set();
6
+ for (let i = 0; i < document.definitions.length; i++) {
7
+ const def = document.definitions[i];
8
+ if (def.kind === Kind.FRAGMENT_DEFINITION) {
9
+ fragments.push(def);
10
+ fragmentNames.add(def.name.value);
11
+ }
12
+ else if (def.kind === Kind.OPERATION_DEFINITION) {
13
+ operations.push(def);
14
+ }
15
+ }
16
+ return {
17
+ operations,
18
+ fragments,
19
+ fragmentNames,
20
+ };
21
+ }
package/esm/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from './Subschema.js';
2
+ export * from './Transformer.js';
3
+ export * from './applySchemaTransforms.js';
4
+ export * from './createRequest.js';
5
+ export * from './defaultMergedResolver.js';
6
+ export * from './delegateToSchema.js';
7
+ export * from './mergeFields.js';
8
+ export * from './resolveExternalValue.js';
9
+ export * from './subschemaConfig.js';
10
+ export * from './types.js';