@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.
- package/README.md +0 -2
- package/cjs/Subschema.js +22 -0
- package/cjs/Transformer.js +45 -0
- package/cjs/applySchemaTransforms.js +11 -0
- package/cjs/checkResultAndHandleErrors.js +77 -0
- package/cjs/createRequest.js +125 -0
- package/cjs/defaultMergedResolver.js +29 -0
- package/cjs/delegateToSchema.js +148 -0
- package/cjs/finalizeGatewayRequest.js +317 -0
- package/cjs/getDocumentMetadata.js +25 -0
- package/cjs/index.js +13 -0
- package/cjs/mergeFields.js +87 -0
- package/cjs/package.json +1 -0
- package/cjs/prepareGatewayDocument.js +311 -0
- package/cjs/resolveExternalValue.js +103 -0
- package/cjs/subschemaConfig.js +31 -0
- package/cjs/symbols.js +6 -0
- package/cjs/types.js +3 -0
- package/esm/Subschema.js +17 -0
- package/esm/Transformer.js +41 -0
- package/esm/applySchemaTransforms.js +7 -0
- package/esm/checkResultAndHandleErrors.js +72 -0
- package/esm/createRequest.js +120 -0
- package/esm/defaultMergedResolver.js +25 -0
- package/esm/delegateToSchema.js +143 -0
- package/esm/finalizeGatewayRequest.js +313 -0
- package/esm/getDocumentMetadata.js +21 -0
- package/esm/index.js +10 -0
- package/esm/mergeFields.js +79 -0
- package/esm/prepareGatewayDocument.js +307 -0
- package/esm/resolveExternalValue.js +99 -0
- package/esm/subschemaConfig.js +26 -0
- package/esm/symbols.js +3 -0
- package/esm/types.js +1 -0
- package/package.json +40 -18
- package/{Subschema.d.ts → typings/Subschema.d.ts} +7 -3
- package/{Transformer.d.ts → typings/Transformer.d.ts} +3 -3
- package/{applySchemaTransforms.d.ts → typings/applySchemaTransforms.d.ts} +2 -2
- package/typings/checkResultAndHandleErrors.d.ts +8 -0
- package/{createRequest.d.ts → typings/createRequest.d.ts} +1 -2
- package/{defaultMergedResolver.d.ts → typings/defaultMergedResolver.d.ts} +2 -4
- package/typings/delegateToSchema.d.ts +6 -0
- package/typings/finalizeGatewayRequest.d.ts +3 -0
- package/{getDocumentMetadata.d.ts → typings/getDocumentMetadata.d.ts} +0 -0
- package/typings/index.d.ts +10 -0
- package/typings/mergeFields.d.ts +8 -0
- package/{prepareGatewayDocument.d.ts → typings/prepareGatewayDocument.d.ts} +0 -0
- package/typings/resolveExternalValue.d.ts +3 -0
- package/{subschemaConfig.d.ts → typings/subschemaConfig.d.ts} +1 -1
- package/typings/symbols.d.ts +3 -0
- package/{types.d.ts → typings/types.d.ts} +21 -40
- package/delegateToSchema.d.ts +0 -9
- package/externalObjects.d.ts +0 -11
- package/externalValues.d.ts +0 -4
- package/finalizeGatewayRequest.d.ts +0 -3
- package/getMergedParent.d.ts +0 -9
- package/index.d.ts +0 -11
- package/index.js +0 -1624
- package/index.mjs +0 -1590
- package/mergeDataAndErrors.d.ts +0 -5
- package/symbols.d.ts +0 -7
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { responsePathAsArray, GraphQLError, locatedError, } from 'graphql';
|
|
2
|
+
import { collectFields, relocatedError } from '@graphql-tools/utils';
|
|
3
|
+
import { FIELD_SUBSCHEMA_MAP_SYMBOL, OBJECT_SUBSCHEMA_SYMBOL, UNPATHED_ERRORS_SYMBOL } from './symbols.js';
|
|
4
|
+
export function isExternalObject(data) {
|
|
5
|
+
return data[UNPATHED_ERRORS_SYMBOL] !== undefined;
|
|
6
|
+
}
|
|
7
|
+
export function annotateExternalObject(object, errors, subschema, subschemaMap) {
|
|
8
|
+
Object.defineProperties(object, {
|
|
9
|
+
[OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema },
|
|
10
|
+
[FIELD_SUBSCHEMA_MAP_SYMBOL]: { value: subschemaMap },
|
|
11
|
+
[UNPATHED_ERRORS_SYMBOL]: { value: errors },
|
|
12
|
+
});
|
|
13
|
+
return object;
|
|
14
|
+
}
|
|
15
|
+
export function getSubschema(object, responseKey) {
|
|
16
|
+
var _a;
|
|
17
|
+
return (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL][responseKey]) !== null && _a !== void 0 ? _a : object[OBJECT_SUBSCHEMA_SYMBOL];
|
|
18
|
+
}
|
|
19
|
+
export function getUnpathedErrors(object) {
|
|
20
|
+
return object[UNPATHED_ERRORS_SYMBOL];
|
|
21
|
+
}
|
|
22
|
+
const EMPTY_ARRAY = [];
|
|
23
|
+
const EMPTY_OBJECT = Object.create(null);
|
|
24
|
+
export async function mergeFields(mergedTypeInfo, object, sourceSubschema, context, info) {
|
|
25
|
+
var _a;
|
|
26
|
+
const delegationMaps = mergedTypeInfo.delegationPlanBuilder(info.schema, sourceSubschema, info.variableValues != null && Object.keys(info.variableValues).length > 0 ? info.variableValues : EMPTY_OBJECT, info.fragments != null && Object.keys(info.fragments).length > 0 ? info.fragments : EMPTY_OBJECT, ((_a = info.fieldNodes) === null || _a === void 0 ? void 0 : _a.length) ? info.fieldNodes : EMPTY_ARRAY);
|
|
27
|
+
for (const delegationMap of delegationMaps) {
|
|
28
|
+
await executeDelegationStage(mergedTypeInfo, delegationMap, object, context, info);
|
|
29
|
+
}
|
|
30
|
+
return object;
|
|
31
|
+
}
|
|
32
|
+
async function executeDelegationStage(mergedTypeInfo, delegationMap, object, context, info) {
|
|
33
|
+
const combinedErrors = object[UNPATHED_ERRORS_SYMBOL];
|
|
34
|
+
const path = responsePathAsArray(info.path);
|
|
35
|
+
const combinedFieldSubschemaMap = object[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
36
|
+
await Promise.all([...delegationMap.entries()].map(async ([subschema, selectionSet]) => {
|
|
37
|
+
var _a;
|
|
38
|
+
const schema = subschema.transformedSchema || info.schema;
|
|
39
|
+
const type = schema.getType(object.__typename);
|
|
40
|
+
const resolver = mergedTypeInfo.resolvers.get(subschema);
|
|
41
|
+
if (resolver) {
|
|
42
|
+
let source;
|
|
43
|
+
try {
|
|
44
|
+
source = await resolver(object, context, info, subschema, selectionSet, undefined, type);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
source = error;
|
|
48
|
+
}
|
|
49
|
+
if (source instanceof Error || source == null) {
|
|
50
|
+
const fieldNodeResponseKeyMap = collectFields(schema, EMPTY_OBJECT, EMPTY_OBJECT, type, selectionSet, new Map(), new Set());
|
|
51
|
+
const nullResult = {};
|
|
52
|
+
for (const [responseKey, fieldNodes] of fieldNodeResponseKeyMap) {
|
|
53
|
+
const combinedPath = [...path, responseKey];
|
|
54
|
+
if (source instanceof GraphQLError) {
|
|
55
|
+
nullResult[responseKey] = relocatedError(source, combinedPath);
|
|
56
|
+
}
|
|
57
|
+
else if (source instanceof Error) {
|
|
58
|
+
nullResult[responseKey] = locatedError(source, fieldNodes, combinedPath);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
nullResult[responseKey] = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
source = nullResult;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (source[UNPATHED_ERRORS_SYMBOL]) {
|
|
68
|
+
combinedErrors.push(...source[UNPATHED_ERRORS_SYMBOL]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const objectSubschema = source[OBJECT_SUBSCHEMA_SYMBOL];
|
|
72
|
+
const fieldSubschemaMap = source[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
73
|
+
for (const responseKey in source) {
|
|
74
|
+
object[responseKey] = source[responseKey];
|
|
75
|
+
combinedFieldSubschemaMap[responseKey] = (_a = fieldSubschemaMap === null || fieldSubschemaMap === void 0 ? void 0 : fieldSubschemaMap[responseKey]) !== null && _a !== void 0 ? _a : objectSubschema;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { Kind, TypeInfo, getNamedType, isAbstractType, isInterfaceType, visit, visitWithTypeInfo, isObjectType, } from 'graphql';
|
|
2
|
+
import { implementsAbstractType, getRootTypeNames, memoize2 } from '@graphql-tools/utils';
|
|
3
|
+
import { getDocumentMetadata } from './getDocumentMetadata.js';
|
|
4
|
+
export function prepareGatewayDocument(originalDocument, transformedSchema, returnType, infoSchema) {
|
|
5
|
+
const wrappedConcreteTypesDocument = wrapConcreteTypes(returnType, transformedSchema, originalDocument);
|
|
6
|
+
if (infoSchema == null) {
|
|
7
|
+
return wrappedConcreteTypesDocument;
|
|
8
|
+
}
|
|
9
|
+
const { possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField, } = getSchemaMetaData(infoSchema, transformedSchema);
|
|
10
|
+
const { operations, fragments, fragmentNames } = getDocumentMetadata(wrappedConcreteTypesDocument);
|
|
11
|
+
const { expandedFragments, fragmentReplacements } = getExpandedFragments(fragments, fragmentNames, possibleTypesMap);
|
|
12
|
+
const typeInfo = new TypeInfo(transformedSchema);
|
|
13
|
+
const expandedDocument = {
|
|
14
|
+
kind: Kind.DOCUMENT,
|
|
15
|
+
definitions: [...operations, ...fragments, ...expandedFragments],
|
|
16
|
+
};
|
|
17
|
+
const visitorKeyMap = {
|
|
18
|
+
Document: ['definitions'],
|
|
19
|
+
OperationDefinition: ['selectionSet'],
|
|
20
|
+
SelectionSet: ['selections'],
|
|
21
|
+
Field: ['selectionSet'],
|
|
22
|
+
InlineFragment: ['selectionSet'],
|
|
23
|
+
FragmentDefinition: ['selectionSet'],
|
|
24
|
+
};
|
|
25
|
+
return visit(expandedDocument, visitWithTypeInfo(typeInfo, {
|
|
26
|
+
[Kind.SELECTION_SET]: node => visitSelectionSet(node, fragmentReplacements, transformedSchema, typeInfo, possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField),
|
|
27
|
+
}),
|
|
28
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
29
|
+
// empty keys cannot be removed only because of typescript errors
|
|
30
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
31
|
+
visitorKeyMap);
|
|
32
|
+
}
|
|
33
|
+
function visitSelectionSet(node, fragmentReplacements, schema, typeInfo, possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const newSelections = new Set();
|
|
36
|
+
const maybeType = typeInfo.getParentType();
|
|
37
|
+
if (maybeType != null) {
|
|
38
|
+
const parentType = getNamedType(maybeType);
|
|
39
|
+
const parentTypeName = parentType.name;
|
|
40
|
+
const fieldNodes = fieldNodesByType[parentTypeName];
|
|
41
|
+
if (fieldNodes) {
|
|
42
|
+
for (const fieldNode of fieldNodes) {
|
|
43
|
+
newSelections.add(fieldNode);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const interfaceExtensions = interfaceExtensionsMap[parentType.name];
|
|
47
|
+
const interfaceExtensionFields = [];
|
|
48
|
+
for (const selection of node.selections) {
|
|
49
|
+
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
50
|
+
if (selection.typeCondition != null) {
|
|
51
|
+
const possibleTypes = possibleTypesMap[selection.typeCondition.name.value];
|
|
52
|
+
if (possibleTypes == null) {
|
|
53
|
+
newSelections.add(selection);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
for (const possibleTypeName of possibleTypes) {
|
|
57
|
+
const maybePossibleType = schema.getType(possibleTypeName);
|
|
58
|
+
if (maybePossibleType != null && implementsAbstractType(schema, parentType, maybePossibleType)) {
|
|
59
|
+
newSelections.add(generateInlineFragment(possibleTypeName, selection.selectionSet));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
65
|
+
const fragmentName = selection.name.value;
|
|
66
|
+
if (!fragmentReplacements[fragmentName]) {
|
|
67
|
+
newSelections.add(selection);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
for (const replacement of fragmentReplacements[fragmentName]) {
|
|
71
|
+
const typeName = replacement.typeName;
|
|
72
|
+
const maybeReplacementType = schema.getType(typeName);
|
|
73
|
+
if (maybeReplacementType != null && implementsAbstractType(schema, parentType, maybeType)) {
|
|
74
|
+
newSelections.add({
|
|
75
|
+
kind: Kind.FRAGMENT_SPREAD,
|
|
76
|
+
name: {
|
|
77
|
+
kind: Kind.NAME,
|
|
78
|
+
value: replacement.fragmentName,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const fieldName = selection.name.value;
|
|
86
|
+
const fieldNodes = (_a = fieldNodesByField[parentTypeName]) === null || _a === void 0 ? void 0 : _a[fieldName];
|
|
87
|
+
if (fieldNodes != null) {
|
|
88
|
+
for (const fieldNode of fieldNodes) {
|
|
89
|
+
newSelections.add(fieldNode);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const dynamicSelectionSets = (_b = dynamicSelectionSetsByField[parentTypeName]) === null || _b === void 0 ? void 0 : _b[fieldName];
|
|
93
|
+
if (dynamicSelectionSets != null) {
|
|
94
|
+
for (const selectionSetFn of dynamicSelectionSets) {
|
|
95
|
+
const selectionSet = selectionSetFn(selection);
|
|
96
|
+
if (selectionSet != null) {
|
|
97
|
+
for (const selection of selectionSet.selections) {
|
|
98
|
+
newSelections.add(selection);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (interfaceExtensions === null || interfaceExtensions === void 0 ? void 0 : interfaceExtensions[fieldName]) {
|
|
104
|
+
interfaceExtensionFields.push(selection);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
newSelections.add(selection);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (reversePossibleTypesMap[parentType.name]) {
|
|
112
|
+
newSelections.add({
|
|
113
|
+
kind: Kind.FIELD,
|
|
114
|
+
name: {
|
|
115
|
+
kind: Kind.NAME,
|
|
116
|
+
value: '__typename',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (interfaceExtensionFields.length) {
|
|
121
|
+
const possibleTypes = possibleTypesMap[parentType.name];
|
|
122
|
+
if (possibleTypes != null) {
|
|
123
|
+
for (const possibleType of possibleTypes) {
|
|
124
|
+
newSelections.add(generateInlineFragment(possibleType, {
|
|
125
|
+
kind: Kind.SELECTION_SET,
|
|
126
|
+
selections: interfaceExtensionFields,
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
...node,
|
|
133
|
+
selections: Array.from(newSelections),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return node;
|
|
137
|
+
}
|
|
138
|
+
function generateInlineFragment(typeName, selectionSet) {
|
|
139
|
+
return {
|
|
140
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
141
|
+
typeCondition: {
|
|
142
|
+
kind: Kind.NAMED_TYPE,
|
|
143
|
+
name: {
|
|
144
|
+
kind: Kind.NAME,
|
|
145
|
+
value: typeName,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
selectionSet,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const getSchemaMetaData = memoize2((sourceSchema, targetSchema) => {
|
|
152
|
+
var _a, _b, _c, _d;
|
|
153
|
+
const typeMap = sourceSchema.getTypeMap();
|
|
154
|
+
const targetTypeMap = targetSchema.getTypeMap();
|
|
155
|
+
const possibleTypesMap = Object.create(null);
|
|
156
|
+
const interfaceExtensionsMap = Object.create(null);
|
|
157
|
+
for (const typeName in typeMap) {
|
|
158
|
+
const type = typeMap[typeName];
|
|
159
|
+
if (isAbstractType(type)) {
|
|
160
|
+
const targetType = targetTypeMap[typeName];
|
|
161
|
+
if (isInterfaceType(type) && isInterfaceType(targetType)) {
|
|
162
|
+
const targetTypeFields = targetType.getFields();
|
|
163
|
+
const sourceTypeFields = type.getFields();
|
|
164
|
+
const extensionFields = Object.create(null);
|
|
165
|
+
let isExtensionFieldsEmpty = true;
|
|
166
|
+
for (const fieldName in sourceTypeFields) {
|
|
167
|
+
if (!targetTypeFields[fieldName]) {
|
|
168
|
+
extensionFields[fieldName] = true;
|
|
169
|
+
isExtensionFieldsEmpty = false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (!isExtensionFieldsEmpty) {
|
|
173
|
+
interfaceExtensionsMap[typeName] = extensionFields;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (interfaceExtensionsMap[typeName] || !isAbstractType(targetType)) {
|
|
177
|
+
const implementations = sourceSchema.getPossibleTypes(type);
|
|
178
|
+
possibleTypesMap[typeName] = [];
|
|
179
|
+
for (const impl of implementations) {
|
|
180
|
+
if (targetTypeMap[impl.name]) {
|
|
181
|
+
possibleTypesMap[typeName].push(impl.name);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const stitchingInfo = (_a = sourceSchema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
188
|
+
return {
|
|
189
|
+
possibleTypesMap,
|
|
190
|
+
reversePossibleTypesMap: reversePossibleTypesMap(possibleTypesMap),
|
|
191
|
+
interfaceExtensionsMap,
|
|
192
|
+
fieldNodesByType: (_b = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.fieldNodesByType) !== null && _b !== void 0 ? _b : {},
|
|
193
|
+
fieldNodesByField: (_c = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.fieldNodesByField) !== null && _c !== void 0 ? _c : {},
|
|
194
|
+
dynamicSelectionSetsByField: (_d = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.dynamicSelectionSetsByField) !== null && _d !== void 0 ? _d : {},
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
function reversePossibleTypesMap(possibleTypesMap) {
|
|
198
|
+
const result = Object.create(null);
|
|
199
|
+
for (const typeName in possibleTypesMap) {
|
|
200
|
+
const toTypeNames = possibleTypesMap[typeName];
|
|
201
|
+
for (const toTypeName of toTypeNames) {
|
|
202
|
+
if (!result[toTypeName]) {
|
|
203
|
+
result[toTypeName] = [];
|
|
204
|
+
}
|
|
205
|
+
result[toTypeName].push(typeName);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
function getExpandedFragments(fragments, fragmentNames, possibleTypesMap) {
|
|
211
|
+
let fragmentCounter = 0;
|
|
212
|
+
function generateFragmentName(typeName) {
|
|
213
|
+
let fragmentName;
|
|
214
|
+
do {
|
|
215
|
+
fragmentName = `_${typeName}_Fragment${fragmentCounter.toString()}`;
|
|
216
|
+
fragmentCounter++;
|
|
217
|
+
} while (fragmentNames.has(fragmentName));
|
|
218
|
+
return fragmentName;
|
|
219
|
+
}
|
|
220
|
+
const expandedFragments = [];
|
|
221
|
+
const fragmentReplacements = Object.create(null);
|
|
222
|
+
for (const fragment of fragments) {
|
|
223
|
+
const possibleTypes = possibleTypesMap[fragment.typeCondition.name.value];
|
|
224
|
+
if (possibleTypes != null) {
|
|
225
|
+
const fragmentName = fragment.name.value;
|
|
226
|
+
fragmentReplacements[fragmentName] = [];
|
|
227
|
+
for (const possibleTypeName of possibleTypes) {
|
|
228
|
+
const name = generateFragmentName(possibleTypeName);
|
|
229
|
+
fragmentNames.add(name);
|
|
230
|
+
expandedFragments.push({
|
|
231
|
+
kind: Kind.FRAGMENT_DEFINITION,
|
|
232
|
+
name: {
|
|
233
|
+
kind: Kind.NAME,
|
|
234
|
+
value: name,
|
|
235
|
+
},
|
|
236
|
+
typeCondition: {
|
|
237
|
+
kind: Kind.NAMED_TYPE,
|
|
238
|
+
name: {
|
|
239
|
+
kind: Kind.NAME,
|
|
240
|
+
value: possibleTypeName,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
selectionSet: fragment.selectionSet,
|
|
244
|
+
});
|
|
245
|
+
fragmentReplacements[fragmentName].push({
|
|
246
|
+
fragmentName: name,
|
|
247
|
+
typeName: possibleTypeName,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
expandedFragments,
|
|
254
|
+
fragmentReplacements,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function wrapConcreteTypes(returnType, targetSchema, document) {
|
|
258
|
+
const namedType = getNamedType(returnType);
|
|
259
|
+
if (!isObjectType(namedType)) {
|
|
260
|
+
return document;
|
|
261
|
+
}
|
|
262
|
+
const rootTypeNames = getRootTypeNames(targetSchema);
|
|
263
|
+
const typeInfo = new TypeInfo(targetSchema);
|
|
264
|
+
const visitorKeys = {
|
|
265
|
+
Document: ['definitions'],
|
|
266
|
+
OperationDefinition: ['selectionSet'],
|
|
267
|
+
SelectionSet: ['selections'],
|
|
268
|
+
InlineFragment: ['selectionSet'],
|
|
269
|
+
FragmentDefinition: ['selectionSet'],
|
|
270
|
+
};
|
|
271
|
+
return visit(document, visitWithTypeInfo(typeInfo, {
|
|
272
|
+
[Kind.FRAGMENT_DEFINITION]: (node) => {
|
|
273
|
+
const typeName = node.typeCondition.name.value;
|
|
274
|
+
if (!rootTypeNames.has(typeName)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
[Kind.FIELD]: (node) => {
|
|
279
|
+
const type = typeInfo.getType();
|
|
280
|
+
if (type != null && isAbstractType(getNamedType(type))) {
|
|
281
|
+
return {
|
|
282
|
+
...node,
|
|
283
|
+
selectionSet: {
|
|
284
|
+
kind: Kind.SELECTION_SET,
|
|
285
|
+
selections: [
|
|
286
|
+
{
|
|
287
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
288
|
+
typeCondition: {
|
|
289
|
+
kind: Kind.NAMED_TYPE,
|
|
290
|
+
name: {
|
|
291
|
+
kind: Kind.NAME,
|
|
292
|
+
value: namedType.name,
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
selectionSet: node.selectionSet,
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
}),
|
|
303
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
304
|
+
// empty keys cannot be removed only because of typescript errors
|
|
305
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
306
|
+
visitorKeys);
|
|
307
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { getNullableType, isCompositeType, isListType, isAbstractType, locatedError, } from 'graphql';
|
|
2
|
+
import { AggregateError } from '@graphql-tools/utils';
|
|
3
|
+
import { annotateExternalObject, isExternalObject, mergeFields } from './mergeFields.js';
|
|
4
|
+
export function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType(info), skipTypeMerging) {
|
|
5
|
+
const type = getNullableType(returnType);
|
|
6
|
+
if (result instanceof Error) {
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
if (result == null) {
|
|
10
|
+
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
11
|
+
}
|
|
12
|
+
if ('parseValue' in type) {
|
|
13
|
+
return type.parseValue(result);
|
|
14
|
+
}
|
|
15
|
+
else if (isCompositeType(type)) {
|
|
16
|
+
return resolveExternalObject(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
17
|
+
}
|
|
18
|
+
else if (isListType(type)) {
|
|
19
|
+
return resolveExternalList(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
23
|
+
var _a;
|
|
24
|
+
// if we have already resolved this object, for example, when the identical object appears twice
|
|
25
|
+
// in a list, see https://github.com/ardatan/graphql-tools/issues/2304
|
|
26
|
+
if (!isExternalObject(object)) {
|
|
27
|
+
annotateExternalObject(object, unpathedErrors, subschema, Object.create(null));
|
|
28
|
+
}
|
|
29
|
+
if (skipTypeMerging || info == null) {
|
|
30
|
+
return object;
|
|
31
|
+
}
|
|
32
|
+
const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
33
|
+
if (stitchingInfo == null) {
|
|
34
|
+
return object;
|
|
35
|
+
}
|
|
36
|
+
const typeName = isAbstractType(type) ? object.__typename : type.name;
|
|
37
|
+
const mergedTypeInfo = stitchingInfo.mergedTypes[typeName];
|
|
38
|
+
let targetSubschemas;
|
|
39
|
+
// Within the stitching context, delegation to a stitched GraphQLSchema or SubschemaConfig
|
|
40
|
+
// will be redirected to the appropriate Subschema object, from which merge targets can be queried.
|
|
41
|
+
if (mergedTypeInfo != null) {
|
|
42
|
+
targetSubschemas = mergedTypeInfo.targetSubschemas.get(subschema);
|
|
43
|
+
}
|
|
44
|
+
// If there are no merge targets from the subschema, return.
|
|
45
|
+
if (!targetSubschemas || !targetSubschemas.length) {
|
|
46
|
+
return object;
|
|
47
|
+
}
|
|
48
|
+
return mergeFields(mergedTypeInfo, object, subschema, context, info);
|
|
49
|
+
}
|
|
50
|
+
function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
51
|
+
return list.map(listMember => resolveExternalListMember(getNullableType(type.ofType), listMember, unpathedErrors, subschema, context, info, skipTypeMerging));
|
|
52
|
+
}
|
|
53
|
+
function resolveExternalListMember(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
54
|
+
if (listMember instanceof Error) {
|
|
55
|
+
return listMember;
|
|
56
|
+
}
|
|
57
|
+
if (listMember == null) {
|
|
58
|
+
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
59
|
+
}
|
|
60
|
+
if ('parseValue' in type) {
|
|
61
|
+
return type.parseValue(listMember);
|
|
62
|
+
}
|
|
63
|
+
else if (isCompositeType(type)) {
|
|
64
|
+
return resolveExternalObject(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
65
|
+
}
|
|
66
|
+
else if (isListType(type)) {
|
|
67
|
+
return resolveExternalList(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const reportedErrors = new WeakMap();
|
|
71
|
+
function reportUnpathedErrorsViaNull(unpathedErrors) {
|
|
72
|
+
if (unpathedErrors.length) {
|
|
73
|
+
const unreportedErrors = [];
|
|
74
|
+
for (const error of unpathedErrors) {
|
|
75
|
+
if (!reportedErrors.has(error)) {
|
|
76
|
+
unreportedErrors.push(error);
|
|
77
|
+
reportedErrors.set(error, true);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (unreportedErrors.length) {
|
|
81
|
+
if (unreportedErrors.length === 1) {
|
|
82
|
+
return unreportedErrors[0];
|
|
83
|
+
}
|
|
84
|
+
const combinedError = new AggregateError(unreportedErrors, unreportedErrors.map(error => error.message).join(', \n'));
|
|
85
|
+
// We cast path as any for GraphQL.js 14 compat
|
|
86
|
+
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
87
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
88
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
89
|
+
return locatedError(combinedError, undefined, unreportedErrors[0].path);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
function getReturnType(info) {
|
|
95
|
+
if (info == null) {
|
|
96
|
+
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
97
|
+
}
|
|
98
|
+
return info.returnType;
|
|
99
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function isSubschemaConfig(value) {
|
|
2
|
+
return Boolean(value === null || value === void 0 ? void 0 : value.schema);
|
|
3
|
+
}
|
|
4
|
+
export function cloneSubschemaConfig(subschemaConfig) {
|
|
5
|
+
var _a, _b;
|
|
6
|
+
const newSubschemaConfig = {
|
|
7
|
+
...subschemaConfig,
|
|
8
|
+
transforms: subschemaConfig.transforms != null ? [...subschemaConfig.transforms] : undefined,
|
|
9
|
+
};
|
|
10
|
+
if (newSubschemaConfig.merge != null) {
|
|
11
|
+
newSubschemaConfig.merge = { ...subschemaConfig.merge };
|
|
12
|
+
for (const typeName in newSubschemaConfig.merge) {
|
|
13
|
+
const mergedTypeConfig = (newSubschemaConfig.merge[typeName] = { ...((_b = (_a = subschemaConfig.merge) === null || _a === void 0 ? void 0 : _a[typeName]) !== null && _b !== void 0 ? _b : {}) });
|
|
14
|
+
if (mergedTypeConfig.entryPoints != null) {
|
|
15
|
+
mergedTypeConfig.entryPoints = mergedTypeConfig.entryPoints.map(entryPoint => ({ ...entryPoint }));
|
|
16
|
+
}
|
|
17
|
+
if (mergedTypeConfig.fields != null) {
|
|
18
|
+
const fields = (mergedTypeConfig.fields = { ...mergedTypeConfig.fields });
|
|
19
|
+
for (const fieldName in fields) {
|
|
20
|
+
fields[fieldName] = { ...fields[fieldName] };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return newSubschemaConfig;
|
|
26
|
+
}
|
package/esm/symbols.js
ADDED
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { OBJECT_SUBSCHEMA_SYMBOL, FIELD_SUBSCHEMA_MAP_SYMBOL, UNPATHED_ERRORS_SYMBOL } from './symbols.js';
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/delegate",
|
|
3
|
-
"version": "9.0.0-alpha-
|
|
3
|
+
"version": "9.0.0-alpha-25204a2f.0",
|
|
4
4
|
"description": "A set of utils for faster development of GraphQL tools",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
7
|
+
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@graphql-tools/batch-execute": "8.
|
|
11
|
-
"@graphql-tools/schema": "8.
|
|
12
|
-
"@graphql-tools/utils": "
|
|
13
|
-
"dataloader": "2.
|
|
14
|
-
"tslib": "~2.
|
|
15
|
-
"value-or-promise": "1.0.
|
|
10
|
+
"@graphql-tools/batch-execute": "8.5.0",
|
|
11
|
+
"@graphql-tools/schema": "8.5.0",
|
|
12
|
+
"@graphql-tools/utils": "8.8.0",
|
|
13
|
+
"dataloader": "2.1.0",
|
|
14
|
+
"tslib": "~2.4.0",
|
|
15
|
+
"value-or-promise": "1.0.11"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -20,20 +20,42 @@
|
|
|
20
20
|
"directory": "packages/delegate"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
|
-
"main": "index.js",
|
|
24
|
-
"module": "index.
|
|
25
|
-
"typings": "index.d.ts",
|
|
23
|
+
"main": "cjs/index.js",
|
|
24
|
+
"module": "esm/index.js",
|
|
25
|
+
"typings": "typings/index.d.ts",
|
|
26
26
|
"typescript": {
|
|
27
|
-
"definition": "index.d.ts"
|
|
27
|
+
"definition": "typings/index.d.ts"
|
|
28
28
|
},
|
|
29
|
+
"type": "module",
|
|
29
30
|
"exports": {
|
|
30
31
|
".": {
|
|
31
|
-
"require":
|
|
32
|
-
|
|
32
|
+
"require": {
|
|
33
|
+
"types": "./typings/index.d.ts",
|
|
34
|
+
"default": "./cjs/index.js"
|
|
35
|
+
},
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./typings/index.d.ts",
|
|
38
|
+
"default": "./esm/index.js"
|
|
39
|
+
},
|
|
40
|
+
"default": {
|
|
41
|
+
"types": "./typings/index.d.ts",
|
|
42
|
+
"default": "./esm/index.js"
|
|
43
|
+
}
|
|
33
44
|
},
|
|
34
45
|
"./*": {
|
|
35
|
-
"require":
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
"require": {
|
|
47
|
+
"types": "./typings/*.d.ts",
|
|
48
|
+
"default": "./cjs/*.js"
|
|
49
|
+
},
|
|
50
|
+
"import": {
|
|
51
|
+
"types": "./typings/*.d.ts",
|
|
52
|
+
"default": "./esm/*.js"
|
|
53
|
+
},
|
|
54
|
+
"default": {
|
|
55
|
+
"types": "./typings/*.d.ts",
|
|
56
|
+
"default": "./esm/*.js"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"./package.json": "./package.json"
|
|
38
60
|
}
|
|
39
|
-
}
|
|
61
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { GraphQLSchema } from 'graphql';
|
|
2
|
-
import { SubschemaConfig, Transform, MergedTypeConfig, CreateProxyingResolverFn, BatchingOptions } from './types';
|
|
2
|
+
import { SubschemaConfig, Transform, MergedTypeConfig, CreateProxyingResolverFn, BatchingOptions } from './types.js';
|
|
3
3
|
import { Executor } from '@graphql-tools/utils';
|
|
4
4
|
export declare function isSubschema(value: any): value is Subschema;
|
|
5
|
-
|
|
5
|
+
interface ISubschema<K = any, V = any, C = K, TContext = Record<string, any>> extends SubschemaConfig<K, V, C, TContext> {
|
|
6
|
+
transformedSchema: GraphQLSchema;
|
|
7
|
+
}
|
|
8
|
+
export declare class Subschema<K = any, V = any, C = K, TContext = Record<string, any>> implements ISubschema<K, V, C, TContext> {
|
|
6
9
|
schema: GraphQLSchema;
|
|
7
10
|
executor?: Executor<TContext>;
|
|
8
11
|
batch?: boolean;
|
|
@@ -10,6 +13,7 @@ export declare class Subschema<K = any, V = any, C = K, TContext = Record<string
|
|
|
10
13
|
createProxyingResolver?: CreateProxyingResolverFn<TContext>;
|
|
11
14
|
transforms: Array<Transform<any, TContext>>;
|
|
12
15
|
transformedSchema: GraphQLSchema;
|
|
13
|
-
merge?: Record<string, MergedTypeConfig<any, TContext>>;
|
|
16
|
+
merge?: Record<string, MergedTypeConfig<any, any, TContext>>;
|
|
14
17
|
constructor(config: SubschemaConfig<K, V, C, TContext>);
|
|
15
18
|
}
|
|
19
|
+
export {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils';
|
|
2
|
-
import { DelegationContext } from './types';
|
|
3
|
-
export declare class Transformer<TContext = Record<string, any>> {
|
|
2
|
+
import { DelegationContext } from './types.js';
|
|
3
|
+
export declare class Transformer<TContext extends Record<string, any> = Record<string, any>> {
|
|
4
4
|
private transformations;
|
|
5
5
|
private delegationContext;
|
|
6
6
|
constructor(context: DelegationContext<TContext>);
|
|
7
7
|
private addTransform;
|
|
8
8
|
transformRequest(originalRequest: ExecutionRequest): ExecutionRequest;
|
|
9
|
-
transformResult(originalResult: ExecutionResult):
|
|
9
|
+
transformResult(originalResult: ExecutionResult): any;
|
|
10
10
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { GraphQLSchema } from 'graphql';
|
|
2
|
-
import { SubschemaConfig } from './types';
|
|
3
|
-
export declare function applySchemaTransforms(originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig<any, any, any, any
|
|
2
|
+
import { SubschemaConfig } from './types.js';
|
|
3
|
+
export declare function applySchemaTransforms(originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig<any, any, any, any>): GraphQLSchema;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GraphQLError } from 'graphql';
|
|
2
|
+
import { ExecutionResult } from '@graphql-tools/utils';
|
|
3
|
+
import { DelegationContext } from './types.js';
|
|
4
|
+
export declare function checkResultAndHandleErrors<TContext extends Record<string, any>>(result: ExecutionResult, delegationContext: DelegationContext<TContext>): any;
|
|
5
|
+
export declare function mergeDataAndErrors(data: any, errors: ReadonlyArray<GraphQLError>, path: Array<string | number> | undefined, onLocatedError?: (originalError: GraphQLError) => GraphQLError, index?: number): {
|
|
6
|
+
data: any;
|
|
7
|
+
unpathedErrors: Array<GraphQLError>;
|
|
8
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { GraphQLSchema, GraphQLObjectType, OperationTypeNode } from 'graphql';
|
|
2
2
|
import { ExecutionRequest } from '@graphql-tools/utils';
|
|
3
|
-
import {
|
|
3
|
+
import { ICreateRequest } from './types.js';
|
|
4
4
|
export declare function getDelegatingOperation(parentType: GraphQLObjectType, schema: GraphQLSchema): OperationTypeNode;
|
|
5
|
-
export declare function createRequestFromInfo({ info, rootValue, operationName, operation, fieldName, selectionSet, fieldNodes, context, }: ICreateRequestFromInfo): ExecutionRequest;
|
|
6
5
|
export declare function createRequest({ sourceSchema, sourceParentType, sourceFieldName, fragments, variableDefinitions, variableValues, targetRootValue, targetOperationName, targetOperation, targetFieldName, selectionSet, fieldNodes, context, info, }: ICreateRequest): ExecutionRequest;
|