@graphql-tools/delegate 8.2.2-alpha-5d885fa3.0 → 9.0.0-alpha-881b29e4.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/Subschema.d.ts +2 -6
- package/Transformer.d.ts +1 -1
- package/defaultMergedResolver.d.ts +3 -1
- package/delegateToSchema.d.ts +5 -2
- package/externalObjects.d.ts +11 -0
- package/externalValues.d.ts +4 -0
- package/getMergedParent.d.ts +9 -0
- package/index.d.ts +3 -2
- package/index.js +631 -305
- package/index.mjs +620 -306
- package/mergeDataAndErrors.d.ts +5 -0
- package/package.json +4 -4
- package/symbols.d.ts +5 -1
- package/types.d.ts +21 -13
- package/checkResultAndHandleErrors.d.ts +0 -8
- package/es5/README.md +0 -7
- package/es5/Subschema.d.ts +0 -19
- package/es5/Transformer.d.ts +0 -10
- package/es5/applySchemaTransforms.d.ts +0 -3
- package/es5/checkResultAndHandleErrors.d.ts +0 -8
- package/es5/createRequest.d.ts +0 -6
- package/es5/defaultMergedResolver.d.ts +0 -9
- package/es5/delegateToSchema.d.ts +0 -6
- package/es5/finalizeGatewayRequest.d.ts +0 -3
- package/es5/getDocumentMetadata.d.ts +0 -6
- package/es5/index.d.ts +0 -10
- package/es5/index.js +0 -1694
- package/es5/index.mjs +0 -1672
- package/es5/mergeFields.d.ts +0 -8
- package/es5/package.json +0 -39
- package/es5/prepareGatewayDocument.d.ts +0 -2
- package/es5/resolveExternalValue.d.ts +0 -3
- package/es5/subschemaConfig.d.ts +0 -3
- package/es5/symbols.d.ts +0 -3
- package/es5/types.d.ts +0 -149
- package/mergeFields.d.ts +0 -8
- package/resolveExternalValue.d.ts +0 -3
package/index.js
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
6
|
+
|
|
5
7
|
const graphql = require('graphql');
|
|
6
8
|
const utils = require('@graphql-tools/utils');
|
|
9
|
+
const DataLoader = _interopDefault(require('dataloader'));
|
|
7
10
|
const valueOrPromise = require('value-or-promise');
|
|
8
11
|
const batchExecute = require('@graphql-tools/batch-execute');
|
|
9
12
|
|
|
@@ -669,262 +672,6 @@ function union(...arrays) {
|
|
|
669
672
|
return result;
|
|
670
673
|
}
|
|
671
674
|
|
|
672
|
-
const UNPATHED_ERRORS_SYMBOL = Symbol('subschemaErrors');
|
|
673
|
-
const OBJECT_SUBSCHEMA_SYMBOL = Symbol('initialSubschema');
|
|
674
|
-
const FIELD_SUBSCHEMA_MAP_SYMBOL = Symbol('subschemaMap');
|
|
675
|
-
|
|
676
|
-
function isExternalObject(data) {
|
|
677
|
-
return data[UNPATHED_ERRORS_SYMBOL] !== undefined;
|
|
678
|
-
}
|
|
679
|
-
function annotateExternalObject(object, errors, subschema, subschemaMap) {
|
|
680
|
-
Object.defineProperties(object, {
|
|
681
|
-
[OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema },
|
|
682
|
-
[FIELD_SUBSCHEMA_MAP_SYMBOL]: { value: subschemaMap },
|
|
683
|
-
[UNPATHED_ERRORS_SYMBOL]: { value: errors },
|
|
684
|
-
});
|
|
685
|
-
return object;
|
|
686
|
-
}
|
|
687
|
-
function getSubschema(object, responseKey) {
|
|
688
|
-
var _a;
|
|
689
|
-
return (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL][responseKey]) !== null && _a !== void 0 ? _a : object[OBJECT_SUBSCHEMA_SYMBOL];
|
|
690
|
-
}
|
|
691
|
-
function getUnpathedErrors(object) {
|
|
692
|
-
return object[UNPATHED_ERRORS_SYMBOL];
|
|
693
|
-
}
|
|
694
|
-
const EMPTY_ARRAY = [];
|
|
695
|
-
const EMPTY_OBJECT = Object.create(null);
|
|
696
|
-
async function mergeFields(mergedTypeInfo, object, sourceSubschema, context, info) {
|
|
697
|
-
var _a;
|
|
698
|
-
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);
|
|
699
|
-
for (const delegationMap of delegationMaps) {
|
|
700
|
-
await executeDelegationStage(mergedTypeInfo, delegationMap, object, context, info);
|
|
701
|
-
}
|
|
702
|
-
return object;
|
|
703
|
-
}
|
|
704
|
-
async function executeDelegationStage(mergedTypeInfo, delegationMap, object, context, info) {
|
|
705
|
-
const combinedErrors = object[UNPATHED_ERRORS_SYMBOL];
|
|
706
|
-
const path = graphql.responsePathAsArray(info.path);
|
|
707
|
-
const combinedFieldSubschemaMap = object[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
708
|
-
const type = info.schema.getType(object.__typename);
|
|
709
|
-
await Promise.all([...delegationMap.entries()].map(async ([s, selectionSet]) => {
|
|
710
|
-
var _a;
|
|
711
|
-
const resolver = mergedTypeInfo.resolvers.get(s);
|
|
712
|
-
if (resolver) {
|
|
713
|
-
let source;
|
|
714
|
-
try {
|
|
715
|
-
source = await resolver(object, context, info, s, selectionSet);
|
|
716
|
-
}
|
|
717
|
-
catch (error) {
|
|
718
|
-
source = error;
|
|
719
|
-
}
|
|
720
|
-
if (source instanceof Error || source == null) {
|
|
721
|
-
const fieldNodeResponseKeyMap = utils.collectFields(info.schema, {}, {}, type, selectionSet, new Map(), new Set());
|
|
722
|
-
const nullResult = {};
|
|
723
|
-
for (const [responseKey, fieldNodes] of fieldNodeResponseKeyMap) {
|
|
724
|
-
const combinedPath = [...path, responseKey];
|
|
725
|
-
if (source instanceof graphql.GraphQLError) {
|
|
726
|
-
nullResult[responseKey] = utils.relocatedError(source, combinedPath);
|
|
727
|
-
}
|
|
728
|
-
else if (source instanceof Error) {
|
|
729
|
-
nullResult[responseKey] = graphql.locatedError(source, fieldNodes, combinedPath);
|
|
730
|
-
}
|
|
731
|
-
else {
|
|
732
|
-
nullResult[responseKey] = null;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
source = nullResult;
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
if (source[UNPATHED_ERRORS_SYMBOL]) {
|
|
739
|
-
combinedErrors.push(...source[UNPATHED_ERRORS_SYMBOL]);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
const objectSubschema = source[OBJECT_SUBSCHEMA_SYMBOL];
|
|
743
|
-
const fieldSubschemaMap = source[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
744
|
-
for (const responseKey in source) {
|
|
745
|
-
object[responseKey] = source[responseKey];
|
|
746
|
-
combinedFieldSubschemaMap[responseKey] = (_a = fieldSubschemaMap === null || fieldSubschemaMap === void 0 ? void 0 : fieldSubschemaMap[responseKey]) !== null && _a !== void 0 ? _a : objectSubschema;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}));
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType(info), skipTypeMerging) {
|
|
753
|
-
const type = graphql.getNullableType(returnType);
|
|
754
|
-
if (result instanceof Error) {
|
|
755
|
-
return result;
|
|
756
|
-
}
|
|
757
|
-
if (result == null) {
|
|
758
|
-
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
759
|
-
}
|
|
760
|
-
if ('parseValue' in type) {
|
|
761
|
-
return type.parseValue(result);
|
|
762
|
-
}
|
|
763
|
-
else if (graphql.isCompositeType(type)) {
|
|
764
|
-
return resolveExternalObject(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
765
|
-
}
|
|
766
|
-
else if (graphql.isListType(type)) {
|
|
767
|
-
return resolveExternalList(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
771
|
-
var _a;
|
|
772
|
-
// if we have already resolved this object, for example, when the identical object appears twice
|
|
773
|
-
// in a list, see https://github.com/ardatan/graphql-tools/issues/2304
|
|
774
|
-
if (!isExternalObject(object)) {
|
|
775
|
-
annotateExternalObject(object, unpathedErrors, subschema, Object.create(null));
|
|
776
|
-
}
|
|
777
|
-
if (skipTypeMerging || info == null) {
|
|
778
|
-
return object;
|
|
779
|
-
}
|
|
780
|
-
const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
781
|
-
if (stitchingInfo == null) {
|
|
782
|
-
return object;
|
|
783
|
-
}
|
|
784
|
-
let typeName;
|
|
785
|
-
if (graphql.isAbstractType(type)) {
|
|
786
|
-
const resolvedType = info.schema.getType(object.__typename);
|
|
787
|
-
if (resolvedType == null) {
|
|
788
|
-
throw new Error(`Unable to resolve type '${object.__typename}'. Did you forget to include a transform that renames types? Did you delegate to the original subschema rather that the subschema config object containing the transform?`);
|
|
789
|
-
}
|
|
790
|
-
typeName = resolvedType.name;
|
|
791
|
-
}
|
|
792
|
-
else {
|
|
793
|
-
typeName = type.name;
|
|
794
|
-
}
|
|
795
|
-
const mergedTypeInfo = stitchingInfo.mergedTypes[typeName];
|
|
796
|
-
let targetSubschemas;
|
|
797
|
-
// Within the stitching context, delegation to a stitched GraphQLSchema or SubschemaConfig
|
|
798
|
-
// will be redirected to the appropriate Subschema object, from which merge targets can be queried.
|
|
799
|
-
if (mergedTypeInfo != null) {
|
|
800
|
-
targetSubschemas = mergedTypeInfo.targetSubschemas.get(subschema);
|
|
801
|
-
}
|
|
802
|
-
// If there are no merge targets from the subschema, return.
|
|
803
|
-
if (!targetSubschemas || !targetSubschemas.length) {
|
|
804
|
-
return object;
|
|
805
|
-
}
|
|
806
|
-
return mergeFields(mergedTypeInfo, object, subschema, context, info);
|
|
807
|
-
}
|
|
808
|
-
function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
809
|
-
return list.map(listMember => resolveExternalListMember(graphql.getNullableType(type.ofType), listMember, unpathedErrors, subschema, context, info, skipTypeMerging));
|
|
810
|
-
}
|
|
811
|
-
function resolveExternalListMember(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
812
|
-
if (listMember instanceof Error) {
|
|
813
|
-
return listMember;
|
|
814
|
-
}
|
|
815
|
-
if (listMember == null) {
|
|
816
|
-
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
817
|
-
}
|
|
818
|
-
if ('parseValue' in type) {
|
|
819
|
-
return type.parseValue(listMember);
|
|
820
|
-
}
|
|
821
|
-
else if (graphql.isCompositeType(type)) {
|
|
822
|
-
return resolveExternalObject(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
823
|
-
}
|
|
824
|
-
else if (graphql.isListType(type)) {
|
|
825
|
-
return resolveExternalList(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
const reportedErrors = new WeakMap();
|
|
829
|
-
function reportUnpathedErrorsViaNull(unpathedErrors) {
|
|
830
|
-
if (unpathedErrors.length) {
|
|
831
|
-
const unreportedErrors = [];
|
|
832
|
-
for (const error of unpathedErrors) {
|
|
833
|
-
if (!reportedErrors.has(error)) {
|
|
834
|
-
unreportedErrors.push(error);
|
|
835
|
-
reportedErrors.set(error, true);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
if (unreportedErrors.length) {
|
|
839
|
-
if (unreportedErrors.length === 1) {
|
|
840
|
-
return unreportedErrors[0];
|
|
841
|
-
}
|
|
842
|
-
const combinedError = new utils.AggregateError(unreportedErrors);
|
|
843
|
-
// We cast path as any for GraphQL.js 14 compat
|
|
844
|
-
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
845
|
-
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
846
|
-
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
847
|
-
return graphql.locatedError(combinedError, undefined, unreportedErrors[0].path);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
return null;
|
|
851
|
-
}
|
|
852
|
-
function getReturnType(info) {
|
|
853
|
-
if (info == null) {
|
|
854
|
-
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
855
|
-
}
|
|
856
|
-
return info.returnType;
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
function checkResultAndHandleErrors(result, delegationContext) {
|
|
860
|
-
const { context, info, fieldName: responseKey = getResponseKey(info), subschema, returnType = getReturnType$1(info), skipTypeMerging, onLocatedError, } = delegationContext;
|
|
861
|
-
const { data, unpathedErrors } = mergeDataAndErrors(result.data == null ? undefined : result.data[responseKey], result.errors == null ? [] : result.errors, info != null && info.path ? graphql.responsePathAsArray(info.path) : undefined, onLocatedError);
|
|
862
|
-
return resolveExternalValue(data, unpathedErrors, subschema, context, info, returnType, skipTypeMerging);
|
|
863
|
-
}
|
|
864
|
-
function mergeDataAndErrors(data, errors, path, onLocatedError, index = 1) {
|
|
865
|
-
var _a;
|
|
866
|
-
if (data == null) {
|
|
867
|
-
if (!errors.length) {
|
|
868
|
-
return { data: null, unpathedErrors: [] };
|
|
869
|
-
}
|
|
870
|
-
if (errors.length === 1) {
|
|
871
|
-
const error = onLocatedError ? onLocatedError(errors[0]) : errors[0];
|
|
872
|
-
const newPath = path === undefined ? error.path : error.path === undefined ? path : path.concat(error.path.slice(1));
|
|
873
|
-
return { data: utils.relocatedError(errors[0], newPath), unpathedErrors: [] };
|
|
874
|
-
}
|
|
875
|
-
// We cast path as any for GraphQL.js 14 compat
|
|
876
|
-
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
877
|
-
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
878
|
-
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
879
|
-
const newError = graphql.locatedError(new utils.AggregateError(errors), undefined, path);
|
|
880
|
-
return { data: newError, unpathedErrors: [] };
|
|
881
|
-
}
|
|
882
|
-
if (!errors.length) {
|
|
883
|
-
return { data, unpathedErrors: [] };
|
|
884
|
-
}
|
|
885
|
-
const unpathedErrors = [];
|
|
886
|
-
const errorMap = new Map();
|
|
887
|
-
for (const error of errors) {
|
|
888
|
-
const pathSegment = (_a = error.path) === null || _a === void 0 ? void 0 : _a[index];
|
|
889
|
-
if (pathSegment != null) {
|
|
890
|
-
let pathSegmentErrors = errorMap.get(pathSegment);
|
|
891
|
-
if (pathSegmentErrors === undefined) {
|
|
892
|
-
pathSegmentErrors = [error];
|
|
893
|
-
errorMap.set(pathSegment, pathSegmentErrors);
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
pathSegmentErrors.push(error);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
else {
|
|
900
|
-
unpathedErrors.push(error);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
for (const [pathSegment, pathSegmentErrors] of errorMap) {
|
|
904
|
-
if (data[pathSegment] !== undefined) {
|
|
905
|
-
const { data: newData, unpathedErrors: newErrors } = mergeDataAndErrors(data[pathSegment], pathSegmentErrors, path, onLocatedError, index + 1);
|
|
906
|
-
data[pathSegment] = newData;
|
|
907
|
-
unpathedErrors.push(...newErrors);
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
unpathedErrors.push(...pathSegmentErrors);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
return { data, unpathedErrors };
|
|
914
|
-
}
|
|
915
|
-
function getResponseKey(info) {
|
|
916
|
-
if (info == null) {
|
|
917
|
-
throw new Error(`Data cannot be extracted from result without an explicit key or source schema.`);
|
|
918
|
-
}
|
|
919
|
-
return utils.getResponseKeyFromInfo(info);
|
|
920
|
-
}
|
|
921
|
-
function getReturnType$1(info) {
|
|
922
|
-
if (info == null) {
|
|
923
|
-
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
924
|
-
}
|
|
925
|
-
return info.returnType;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
675
|
class Transformer {
|
|
929
676
|
constructor(context) {
|
|
930
677
|
this.transformations = [];
|
|
@@ -960,7 +707,7 @@ class Transformer {
|
|
|
960
707
|
result = transformation.transform.transformResult(result, this.delegationContext, transformation.context);
|
|
961
708
|
}
|
|
962
709
|
}
|
|
963
|
-
return
|
|
710
|
+
return result;
|
|
964
711
|
}
|
|
965
712
|
}
|
|
966
713
|
|
|
@@ -1101,70 +848,578 @@ function updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argument
|
|
|
1101
848
|
}
|
|
1102
849
|
}
|
|
1103
850
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
return graphql.defaultFieldResolver(parent, args, context, info);
|
|
851
|
+
const INITIAL_PATH_SYMBOL = Symbol('initialPath');
|
|
852
|
+
const UNPATHED_ERRORS_SYMBOL = Symbol('unpathedErrors');
|
|
853
|
+
const OBJECT_SUBSCHEMA_SYMBOL = Symbol('initialSubschema');
|
|
854
|
+
const INITIAL_POSSIBLE_FIELDS = Symbol('initialPossibleFields');
|
|
855
|
+
const INFO_SYMBOL = Symbol('info');
|
|
856
|
+
const RESPONSE_KEY_SUBSCHEMA_MAP_SYMBOL = Symbol('subschemaMap');
|
|
857
|
+
|
|
858
|
+
function isExternalObject(data) {
|
|
859
|
+
return (data === null || data === void 0 ? void 0 : data[UNPATHED_ERRORS_SYMBOL]) !== undefined;
|
|
860
|
+
}
|
|
861
|
+
function annotateExternalObject(object, errors, initialPath, subschema, info) {
|
|
862
|
+
var _a, _b, _c;
|
|
863
|
+
if (isExternalObject(object)) {
|
|
864
|
+
return object;
|
|
1119
865
|
}
|
|
1120
|
-
const
|
|
1121
|
-
const
|
|
1122
|
-
|
|
1123
|
-
|
|
866
|
+
const schema = subschema instanceof Subschema ? subschema.transformedSchema : (_b = (_a = subschema) === null || _a === void 0 ? void 0 : _a.schema) !== null && _b !== void 0 ? _b : subschema;
|
|
867
|
+
const initialPossibleFields = (_c = schema.getType(object.__typename)) === null || _c === void 0 ? void 0 : _c.getFields();
|
|
868
|
+
Object.defineProperties(object, {
|
|
869
|
+
[INITIAL_PATH_SYMBOL]: { value: initialPath },
|
|
870
|
+
[OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema },
|
|
871
|
+
[INITIAL_POSSIBLE_FIELDS]: { value: initialPossibleFields },
|
|
872
|
+
[INFO_SYMBOL]: { value: info },
|
|
873
|
+
[RESPONSE_KEY_SUBSCHEMA_MAP_SYMBOL]: { value: Object.create(null) },
|
|
874
|
+
[UNPATHED_ERRORS_SYMBOL]: { value: errors },
|
|
875
|
+
});
|
|
876
|
+
return object;
|
|
877
|
+
}
|
|
878
|
+
function getInitialPath(object) {
|
|
879
|
+
return object[INITIAL_PATH_SYMBOL];
|
|
880
|
+
}
|
|
881
|
+
function getInitialPossibleFields(object) {
|
|
882
|
+
return object[INITIAL_POSSIBLE_FIELDS];
|
|
883
|
+
}
|
|
884
|
+
function getInfo(object) {
|
|
885
|
+
return object[INFO_SYMBOL];
|
|
886
|
+
}
|
|
887
|
+
function getUnpathedErrors(object) {
|
|
888
|
+
return object[UNPATHED_ERRORS_SYMBOL];
|
|
889
|
+
}
|
|
890
|
+
function getObjectSubchema(object) {
|
|
891
|
+
return object[OBJECT_SUBSCHEMA_SYMBOL];
|
|
892
|
+
}
|
|
893
|
+
function getSubschemaMap(object) {
|
|
894
|
+
return object[RESPONSE_KEY_SUBSCHEMA_MAP_SYMBOL];
|
|
895
|
+
}
|
|
896
|
+
function getSubschema(object, responseKey) {
|
|
897
|
+
var _a;
|
|
898
|
+
return (_a = object[RESPONSE_KEY_SUBSCHEMA_MAP_SYMBOL][responseKey]) !== null && _a !== void 0 ? _a : object[OBJECT_SUBSCHEMA_SYMBOL];
|
|
1124
899
|
}
|
|
1125
900
|
|
|
1126
|
-
function
|
|
1127
|
-
|
|
901
|
+
function mergeDataAndErrors(data, errors = [], onLocatedError = (originalError) => originalError, index = 1) {
|
|
902
|
+
var _a;
|
|
903
|
+
if (data == null) {
|
|
904
|
+
if (!errors.length) {
|
|
905
|
+
return { data: null, unpathedErrors: [] };
|
|
906
|
+
}
|
|
907
|
+
if (errors.length === 1) {
|
|
908
|
+
const error = onLocatedError(errors[0]);
|
|
909
|
+
const newPath = error.path === undefined ? [] : error.path.slice(1);
|
|
910
|
+
const newError = utils.relocatedError(error, newPath);
|
|
911
|
+
return { data: newError, unpathedErrors: [] };
|
|
912
|
+
}
|
|
913
|
+
const newErrors = errors.map(error => onLocatedError(error));
|
|
914
|
+
const firstError = newErrors[0];
|
|
915
|
+
const newPath = firstError.path === undefined ? [] : firstError.path.slice(1);
|
|
916
|
+
// We cast path as any for GraphQL.js 14 compat
|
|
917
|
+
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
918
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
919
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
920
|
+
const newError = graphql.locatedError(new utils.AggregateError(newErrors), undefined, newPath);
|
|
921
|
+
return { data: newError, unpathedErrors: [] };
|
|
922
|
+
}
|
|
923
|
+
if (!errors.length) {
|
|
924
|
+
return { data, unpathedErrors: [] };
|
|
925
|
+
}
|
|
926
|
+
const unpathedErrors = [];
|
|
927
|
+
const errorMap = new Map();
|
|
928
|
+
for (const error of errors) {
|
|
929
|
+
const pathSegment = (_a = error.path) === null || _a === void 0 ? void 0 : _a[index];
|
|
930
|
+
if (pathSegment != null) {
|
|
931
|
+
let pathSegmentErrors = errorMap.get(pathSegment);
|
|
932
|
+
if (pathSegmentErrors === undefined) {
|
|
933
|
+
pathSegmentErrors = [error];
|
|
934
|
+
errorMap.set(pathSegment, pathSegmentErrors);
|
|
935
|
+
}
|
|
936
|
+
else {
|
|
937
|
+
pathSegmentErrors.push(error);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
unpathedErrors.push(error);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
for (const [pathSegment, pathSegmentErrors] of errorMap) {
|
|
945
|
+
if (data[pathSegment] !== undefined) {
|
|
946
|
+
const { data: newData, unpathedErrors: newErrors } = mergeDataAndErrors(data[pathSegment], pathSegmentErrors, onLocatedError, index + 1);
|
|
947
|
+
data[pathSegment] = newData;
|
|
948
|
+
unpathedErrors.push(...newErrors);
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
unpathedErrors.push(...pathSegmentErrors);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return { data, unpathedErrors };
|
|
1128
955
|
}
|
|
1129
|
-
|
|
956
|
+
|
|
957
|
+
function externalValueFromResult({ result, schema, info, context, fieldName = getFieldName(info), returnType = getReturnType(info), onLocatedError = (error) => error, }) {
|
|
1130
958
|
var _a, _b;
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
|
|
959
|
+
const data = (_a = result.data) === null || _a === void 0 ? void 0 : _a[fieldName];
|
|
960
|
+
const errors = (_b = result.errors) !== null && _b !== void 0 ? _b : [];
|
|
961
|
+
const initialPath = info ? graphql.responsePathAsArray(info.path) : [];
|
|
962
|
+
const { data: newData, unpathedErrors } = mergeDataAndErrors(data, errors, onLocatedError);
|
|
963
|
+
return createExternalValue(newData, unpathedErrors, initialPath, schema, context, info, returnType);
|
|
964
|
+
}
|
|
965
|
+
function createExternalValue(data, unpathedErrors, initialPath, subschema, context, info, returnType = getReturnType(info)) {
|
|
966
|
+
const type = graphql.getNullableType(returnType);
|
|
967
|
+
if (data instanceof graphql.GraphQLError) {
|
|
968
|
+
return utils.relocatedError(data, data.path ? initialPath.concat(data.path) : initialPath);
|
|
969
|
+
}
|
|
970
|
+
if (data instanceof Error) {
|
|
971
|
+
return data;
|
|
972
|
+
}
|
|
973
|
+
if (data == null) {
|
|
974
|
+
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
975
|
+
}
|
|
976
|
+
if ('parseValue' in type) {
|
|
977
|
+
return type.parseValue(data);
|
|
978
|
+
}
|
|
979
|
+
else if (graphql.isCompositeType(type)) {
|
|
980
|
+
return annotateExternalObject(data, unpathedErrors, initialPath, subschema, info);
|
|
981
|
+
}
|
|
982
|
+
else if (graphql.isListType(type)) {
|
|
983
|
+
return createExternalList(type, data, unpathedErrors, initialPath, subschema, context, info);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
function createExternalList(type, list, unpathedErrors, initialPath, subschema, context, info) {
|
|
987
|
+
return list.map(listMember => createExternalListMember(graphql.getNullableType(type.ofType), listMember, unpathedErrors, initialPath, subschema, context, info));
|
|
988
|
+
}
|
|
989
|
+
function createExternalListMember(type, listMember, unpathedErrors, initialPath, subschema, context, info) {
|
|
990
|
+
if (listMember instanceof graphql.GraphQLError) {
|
|
991
|
+
return utils.relocatedError(listMember, listMember.path ? initialPath.concat(listMember.path) : initialPath);
|
|
992
|
+
}
|
|
993
|
+
if (listMember instanceof Error) {
|
|
994
|
+
return listMember;
|
|
995
|
+
}
|
|
996
|
+
if (listMember == null) {
|
|
997
|
+
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
998
|
+
}
|
|
999
|
+
if ('parseValue' in type) {
|
|
1000
|
+
return type.parseValue(listMember);
|
|
1001
|
+
}
|
|
1002
|
+
else if (graphql.isCompositeType(type)) {
|
|
1003
|
+
return annotateExternalObject(listMember, unpathedErrors, initialPath, subschema, info);
|
|
1004
|
+
}
|
|
1005
|
+
else if (graphql.isListType(type)) {
|
|
1006
|
+
return createExternalList(type, listMember, unpathedErrors, initialPath, subschema, context, info);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
const reportedErrors = new WeakMap();
|
|
1010
|
+
function reportUnpathedErrorsViaNull(unpathedErrors) {
|
|
1011
|
+
if (unpathedErrors.length) {
|
|
1012
|
+
const unreportedErrors = [];
|
|
1013
|
+
for (const error of unpathedErrors) {
|
|
1014
|
+
if (!reportedErrors.has(error)) {
|
|
1015
|
+
unreportedErrors.push(error);
|
|
1016
|
+
reportedErrors.set(error, true);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (unreportedErrors.length) {
|
|
1020
|
+
if (unreportedErrors.length === 1) {
|
|
1021
|
+
return unreportedErrors[0];
|
|
1022
|
+
}
|
|
1023
|
+
const combinedError = new utils.AggregateError(unreportedErrors);
|
|
1024
|
+
// We cast path as any for GraphQL.js 14 compat
|
|
1025
|
+
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
1026
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
1027
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
1028
|
+
return graphql.locatedError(combinedError, undefined, unreportedErrors[0].path);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
1033
|
+
function getFieldName(info) {
|
|
1034
|
+
if (info == null) {
|
|
1035
|
+
throw new Error(`Data cannot be extracted from result without an explicit key or source schema.`);
|
|
1036
|
+
}
|
|
1037
|
+
return info.fieldName;
|
|
1038
|
+
}
|
|
1039
|
+
function getReturnType(info) {
|
|
1040
|
+
if (info == null) {
|
|
1041
|
+
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
1042
|
+
}
|
|
1043
|
+
return info.returnType;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
const getMergedTypeInfo = utils.memoize1(function getMergedTypeInfo(info) {
|
|
1047
|
+
var _a;
|
|
1048
|
+
const schema = info.schema;
|
|
1049
|
+
const stitchingInfo = (_a = schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
1050
|
+
if (stitchingInfo == null) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const parentTypeName = info.parentType.name;
|
|
1054
|
+
const mergedTypeInfo = stitchingInfo.mergedTypes[parentTypeName];
|
|
1055
|
+
if (mergedTypeInfo === undefined) {
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
return mergedTypeInfo;
|
|
1059
|
+
});
|
|
1060
|
+
const loaders = new WeakMap();
|
|
1061
|
+
async function getMergedParent(parent, context, info) {
|
|
1062
|
+
const mergedTypeInfo = getMergedTypeInfo(info);
|
|
1063
|
+
if (!mergedTypeInfo) {
|
|
1064
|
+
return parent;
|
|
1065
|
+
}
|
|
1066
|
+
// In the stitching context, all subschemas are compiled Subschema objects rather than SubschemaConfig objects
|
|
1067
|
+
const sourceSubschema = getObjectSubchema(parent);
|
|
1068
|
+
let loader = loaders.get(parent);
|
|
1069
|
+
if (loader === undefined) {
|
|
1070
|
+
loader = new DataLoader(fieldNodeArrays => getMergedParentsFromFieldNodes(parent, context, info.schema, fieldNodeArrays, mergedTypeInfo, sourceSubschema));
|
|
1071
|
+
loaders.set(parent, loader);
|
|
1072
|
+
}
|
|
1073
|
+
return loader.load(info.fieldNodes);
|
|
1074
|
+
}
|
|
1075
|
+
async function getMergedParentsFromFieldNodes(parent, context, gatewaySchema, fieldNodeArrays, mergedTypeInfo, sourceSubschema) {
|
|
1076
|
+
const { requiredKeys, delegationMaps, stageMap } = buildDelegationPlan(mergedTypeInfo, gatewaySchema, sourceSubschema, ...fieldNodeArrays);
|
|
1077
|
+
if (!delegationMaps.length) {
|
|
1078
|
+
return Array(fieldNodeArrays.length).fill(parent);
|
|
1079
|
+
}
|
|
1080
|
+
const promises = [];
|
|
1081
|
+
const parentInfo = getInfo(parent);
|
|
1082
|
+
const schema = parentInfo.schema;
|
|
1083
|
+
const type = schema.getType(parent.__typename);
|
|
1084
|
+
const parentPath = graphql.responsePathAsArray(parentInfo.path);
|
|
1085
|
+
let promise = executeDelegationStage(delegationMaps[0], schema, type, mergedTypeInfo, context, parent, parentInfo, parentPath);
|
|
1086
|
+
promises.push(promise);
|
|
1087
|
+
for (let i = 1, delegationStage = delegationMaps[i]; i < delegationMaps.length; i++) {
|
|
1088
|
+
promise = promise.then(parent => executeDelegationStage(delegationStage, schema, type, mergedTypeInfo, context, parent, parentInfo, parentPath));
|
|
1089
|
+
promises.push(promise);
|
|
1090
|
+
}
|
|
1091
|
+
return fieldNodeArrays.map(fieldNodeArray => {
|
|
1092
|
+
const fieldName = fieldNodeArray[0].name.value;
|
|
1093
|
+
const keys = requiredKeys[fieldName];
|
|
1094
|
+
if (keys === undefined) {
|
|
1095
|
+
const delegationStage = stageMap[fieldName];
|
|
1096
|
+
if (delegationStage !== undefined) {
|
|
1097
|
+
return promises[delegationStage];
|
|
1098
|
+
}
|
|
1099
|
+
return Promise.resolve(parent);
|
|
1100
|
+
}
|
|
1101
|
+
return Promise.all(Array.from(keys.values()).map(fieldName => {
|
|
1102
|
+
const delegationStage = stageMap[fieldName];
|
|
1103
|
+
if (delegationStage !== undefined) {
|
|
1104
|
+
return promises[delegationStage];
|
|
1105
|
+
}
|
|
1106
|
+
return Promise.resolve(parent);
|
|
1107
|
+
})).then(() => parent);
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
function sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemas, targetSubschemas, fieldNodes) {
|
|
1111
|
+
// 1. calculate if possible to delegate to given subschema
|
|
1112
|
+
const proxiableSubschemas = [];
|
|
1113
|
+
const nonProxiableSubschemas = [];
|
|
1114
|
+
for (const t of targetSubschemas) {
|
|
1115
|
+
const selectionSet = mergedTypeInfo.selectionSets.get(t);
|
|
1116
|
+
const fieldSelectionSets = mergedTypeInfo.fieldSelectionSets.get(t);
|
|
1117
|
+
if (selectionSet != null && !subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemas, selectionSet)) {
|
|
1118
|
+
nonProxiableSubschemas.push(t);
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
if (fieldSelectionSets == null ||
|
|
1122
|
+
fieldNodes.every(fieldNode => {
|
|
1123
|
+
const fieldName = fieldNode.name.value;
|
|
1124
|
+
const fieldSelectionSet = fieldSelectionSets[fieldName];
|
|
1125
|
+
return (fieldSelectionSet == null ||
|
|
1126
|
+
subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemas, fieldSelectionSet));
|
|
1127
|
+
})) {
|
|
1128
|
+
proxiableSubschemas.push(t);
|
|
1129
|
+
}
|
|
1130
|
+
else {
|
|
1131
|
+
nonProxiableSubschemas.push(t);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return {
|
|
1136
|
+
proxiableSubschemas,
|
|
1137
|
+
nonProxiableSubschemas,
|
|
1134
1138
|
};
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1139
|
+
}
|
|
1140
|
+
function calculateDelegationStage(mergedTypeInfo, sourceSubschemas, targetSubschemas, fieldNodes) {
|
|
1141
|
+
const { proxiableSubschemas, nonProxiableSubschemas } = sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemas, targetSubschemas, fieldNodes);
|
|
1142
|
+
const { delegationMap, proxiableFieldNodes, unproxiableFieldNodes } = buildDelegationStage(mergedTypeInfo, fieldNodes, proxiableSubschemas);
|
|
1143
|
+
return {
|
|
1144
|
+
proxiableSubschemas,
|
|
1145
|
+
nonProxiableSubschemas,
|
|
1146
|
+
delegationMap,
|
|
1147
|
+
proxiableFieldNodes,
|
|
1148
|
+
unproxiableFieldNodes,
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
const buildDelegationPlan = utils.memoize4ofMany(function buildDelegationPlan(mergedTypeInfo, gatewaySchema, sourceSubschema, ...fieldNodeArrays) {
|
|
1152
|
+
var _a, _b, _c;
|
|
1153
|
+
const requiredKeys = Object.create(null);
|
|
1154
|
+
const delegationMaps = [];
|
|
1155
|
+
const stageMap = Object.create(null);
|
|
1156
|
+
const stitchingInfo = (_a = gatewaySchema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
1157
|
+
if (stitchingInfo == null) {
|
|
1158
|
+
return { requiredKeys, delegationMaps, stageMap };
|
|
1159
|
+
}
|
|
1160
|
+
const targetSubschemas = mergedTypeInfo.targetSubschemas.get(sourceSubschema);
|
|
1161
|
+
if (targetSubschemas === undefined || targetSubschemas.length === 0) {
|
|
1162
|
+
return { requiredKeys, delegationMaps, stageMap };
|
|
1163
|
+
}
|
|
1164
|
+
const parentTypeName = mergedTypeInfo.typeName;
|
|
1165
|
+
const sourceSubschemaParentType = sourceSubschema.transformedSchema.getType(parentTypeName);
|
|
1166
|
+
const sourceSubschemaFields = sourceSubschemaParentType.getFields();
|
|
1167
|
+
const subschemaFields = mergedTypeInfo.subschemaFields;
|
|
1168
|
+
const typeFieldNodes = (_b = stitchingInfo.fieldNodesByField) === null || _b === void 0 ? void 0 : _b[parentTypeName];
|
|
1169
|
+
const fieldNodeSet = new Set();
|
|
1170
|
+
const fieldNodesByType = (_c = stitchingInfo.fieldNodesByType) === null || _c === void 0 ? void 0 : _c[parentTypeName];
|
|
1171
|
+
if (fieldNodesByType !== undefined) {
|
|
1172
|
+
for (const fieldNode of fieldNodesByType) {
|
|
1173
|
+
const fieldName = fieldNode.name.value;
|
|
1174
|
+
if (!sourceSubschemaFields[fieldName]) {
|
|
1175
|
+
const fieldName = fieldNode.name.value;
|
|
1176
|
+
if (!sourceSubschemaFields[fieldName]) {
|
|
1177
|
+
fieldNodeSet.add(fieldNode);
|
|
1178
|
+
}
|
|
1141
1179
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
for (const fieldNodeArray of fieldNodeArrays) {
|
|
1183
|
+
const fieldName = fieldNodeArray[0].name.value;
|
|
1184
|
+
if (subschemaFields[fieldName] !== undefined) {
|
|
1185
|
+
// merged subschema field
|
|
1186
|
+
for (const fieldNode of fieldNodeArray) {
|
|
1187
|
+
const fieldName = fieldNode.name.value;
|
|
1188
|
+
if (!sourceSubschemaFields[fieldName]) {
|
|
1189
|
+
fieldNodeSet.add(fieldNode);
|
|
1146
1190
|
}
|
|
1147
1191
|
}
|
|
1148
1192
|
}
|
|
1193
|
+
else {
|
|
1194
|
+
// gateway field
|
|
1195
|
+
if (requiredKeys[fieldName] === undefined) {
|
|
1196
|
+
requiredKeys[fieldName] = new Set();
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
const keyFieldNodes = new Set();
|
|
1200
|
+
const fieldNodesByField = typeFieldNodes === null || typeFieldNodes === void 0 ? void 0 : typeFieldNodes[fieldName];
|
|
1201
|
+
if (fieldNodesByField !== undefined) {
|
|
1202
|
+
for (const fieldNode of fieldNodesByField) {
|
|
1203
|
+
keyFieldNodes.add(fieldNode);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
if (requiredKeys[fieldName] !== undefined) {
|
|
1207
|
+
for (const fieldNode of keyFieldNodes.values()) {
|
|
1208
|
+
requiredKeys[fieldName].add(fieldNode.name.value);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
for (const fieldNode of keyFieldNodes) {
|
|
1212
|
+
fieldNodeSet.add(fieldNode);
|
|
1213
|
+
}
|
|
1149
1214
|
}
|
|
1150
|
-
|
|
1215
|
+
const fieldNodes = Array.from(fieldNodeSet);
|
|
1216
|
+
let sourceSubschemas = [sourceSubschema];
|
|
1217
|
+
let delegationStage = calculateDelegationStage(mergedTypeInfo, sourceSubschemas, targetSubschemas, fieldNodes);
|
|
1218
|
+
let stageIndex = 0;
|
|
1219
|
+
let delegationMap = delegationStage.delegationMap;
|
|
1220
|
+
while (delegationMap.size) {
|
|
1221
|
+
delegationMaps.push(delegationMap);
|
|
1222
|
+
const { proxiableSubschemas, nonProxiableSubschemas, proxiableFieldNodes, unproxiableFieldNodes } = delegationStage;
|
|
1223
|
+
sourceSubschemas = sourceSubschemas.concat(proxiableSubschemas);
|
|
1224
|
+
for (const fieldNode of proxiableFieldNodes) {
|
|
1225
|
+
stageMap[fieldNode.name.value] = stageIndex;
|
|
1226
|
+
}
|
|
1227
|
+
stageIndex++;
|
|
1228
|
+
delegationStage = calculateDelegationStage(mergedTypeInfo, sourceSubschemas, nonProxiableSubschemas, unproxiableFieldNodes);
|
|
1229
|
+
delegationMap = delegationStage.delegationMap;
|
|
1230
|
+
}
|
|
1231
|
+
return {
|
|
1232
|
+
requiredKeys,
|
|
1233
|
+
delegationMaps,
|
|
1234
|
+
stageMap,
|
|
1235
|
+
};
|
|
1236
|
+
});
|
|
1237
|
+
function buildDelegationStage(mergedTypeInfo, fieldNodes, proxiableSubschemas) {
|
|
1238
|
+
const { uniqueFields, nonUniqueFields } = mergedTypeInfo;
|
|
1239
|
+
const proxiableFieldNodes = [];
|
|
1240
|
+
const unproxiableFieldNodes = [];
|
|
1241
|
+
// 2. for each selection:
|
|
1242
|
+
const delegationMap = new Map();
|
|
1243
|
+
for (const fieldNode of fieldNodes) {
|
|
1244
|
+
if (fieldNode.name.value === '__typename') {
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
// 2a. use uniqueFields map to assign fields to subschema if one of possible subschemas
|
|
1248
|
+
const uniqueSubschema = uniqueFields[fieldNode.name.value];
|
|
1249
|
+
if (uniqueSubschema != null) {
|
|
1250
|
+
if (!proxiableSubschemas.includes(uniqueSubschema)) {
|
|
1251
|
+
unproxiableFieldNodes.push(fieldNode);
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
const existingSubschema = delegationMap.get(uniqueSubschema);
|
|
1255
|
+
if (existingSubschema != null) {
|
|
1256
|
+
existingSubschema.push(fieldNode);
|
|
1257
|
+
}
|
|
1258
|
+
else {
|
|
1259
|
+
delegationMap.set(uniqueSubschema, [fieldNode]);
|
|
1260
|
+
}
|
|
1261
|
+
proxiableFieldNodes.push(fieldNode);
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
// 2b. use nonUniqueFields to assign to a possible subschema,
|
|
1265
|
+
// preferring one of the subschemas already targets of delegation
|
|
1266
|
+
let nonUniqueSubschemas = nonUniqueFields[fieldNode.name.value];
|
|
1267
|
+
if (nonUniqueSubschemas == null) {
|
|
1268
|
+
unproxiableFieldNodes.push(fieldNode);
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
nonUniqueSubschemas = nonUniqueSubschemas.filter(s => proxiableSubschemas.includes(s));
|
|
1272
|
+
if (!nonUniqueSubschemas.length) {
|
|
1273
|
+
unproxiableFieldNodes.push(fieldNode);
|
|
1274
|
+
continue;
|
|
1275
|
+
}
|
|
1276
|
+
const existingSubschema = nonUniqueSubschemas.find(s => delegationMap.has(s));
|
|
1277
|
+
if (existingSubschema != null) {
|
|
1278
|
+
// It is okay we previously explicitly check whether the map has the element.
|
|
1279
|
+
delegationMap.get(existingSubschema).push(fieldNode);
|
|
1280
|
+
}
|
|
1281
|
+
else {
|
|
1282
|
+
delegationMap.set(nonUniqueSubschemas[0], [fieldNode]);
|
|
1283
|
+
}
|
|
1284
|
+
proxiableFieldNodes.push(fieldNode);
|
|
1285
|
+
}
|
|
1286
|
+
return {
|
|
1287
|
+
delegationMap,
|
|
1288
|
+
proxiableFieldNodes,
|
|
1289
|
+
unproxiableFieldNodes,
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
async function executeDelegationStage(delegationMap, schema, type, mergedTypeInfo, context, object, parentInfo, parentPath) {
|
|
1293
|
+
const initialPath = getInitialPath(object);
|
|
1294
|
+
const newSubschemaMap = getSubschemaMap(object);
|
|
1295
|
+
const unpathedErrors = getUnpathedErrors(object);
|
|
1296
|
+
await Promise.all([...delegationMap.entries()].map(async ([s, fieldNodes]) => {
|
|
1297
|
+
var _a;
|
|
1298
|
+
const resolver = mergedTypeInfo.resolvers.get(s);
|
|
1299
|
+
if (resolver) {
|
|
1300
|
+
const selectionSet = { kind: graphql.Kind.SELECTION_SET, selections: fieldNodes };
|
|
1301
|
+
let source;
|
|
1302
|
+
try {
|
|
1303
|
+
source = await resolver(object, context, parentInfo, s, selectionSet);
|
|
1304
|
+
}
|
|
1305
|
+
catch (error) {
|
|
1306
|
+
source = error;
|
|
1307
|
+
}
|
|
1308
|
+
if (source instanceof Error || source === null) {
|
|
1309
|
+
const fieldNodes = utils.collectFields(schema, {}, {}, type, selectionSet, new Map(), new Set());
|
|
1310
|
+
const nullResult = Object.create(null);
|
|
1311
|
+
if (source instanceof graphql.GraphQLError && source.path) {
|
|
1312
|
+
const basePath = parentPath.slice(initialPath.length);
|
|
1313
|
+
for (const [responseKey] of fieldNodes) {
|
|
1314
|
+
const tailPath = source.path.length === parentPath.length ? [responseKey] : source.path.slice(initialPath.length);
|
|
1315
|
+
const newPath = basePath.concat(tailPath);
|
|
1316
|
+
nullResult[responseKey] = utils.relocatedError(source, newPath);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
else if (source instanceof Error) {
|
|
1320
|
+
const basePath = parentPath.slice(initialPath.length);
|
|
1321
|
+
for (const [responseKey] of fieldNodes) {
|
|
1322
|
+
const newPath = basePath.concat([responseKey]);
|
|
1323
|
+
nullResult[responseKey] = graphql.locatedError(source, fieldNodes[responseKey], newPath);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
else {
|
|
1327
|
+
for (const [responseKey] of fieldNodes) {
|
|
1328
|
+
nullResult[responseKey] = null;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
source = nullResult;
|
|
1332
|
+
}
|
|
1333
|
+
// TODO: is this check necessary or just to make TS happy?
|
|
1334
|
+
if (!isExternalObject(source)) {
|
|
1335
|
+
Object.assign(object, source);
|
|
1336
|
+
return object;
|
|
1337
|
+
}
|
|
1338
|
+
const objectSubschema = getObjectSubchema(source);
|
|
1339
|
+
const subschemaMap = getSubschemaMap(source);
|
|
1340
|
+
for (const responseKey in source) {
|
|
1341
|
+
object[responseKey] = source[responseKey];
|
|
1342
|
+
newSubschemaMap[responseKey] = (_a = subschemaMap === null || subschemaMap === void 0 ? void 0 : subschemaMap[responseKey]) !== null && _a !== void 0 ? _a : objectSubschema;
|
|
1343
|
+
}
|
|
1344
|
+
unpathedErrors.push(...getUnpathedErrors(source));
|
|
1345
|
+
}
|
|
1346
|
+
}));
|
|
1347
|
+
return object;
|
|
1348
|
+
}
|
|
1349
|
+
const subschemaTypesContainSelectionSet = utils.memoize3(function subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemas, selectionSet) {
|
|
1350
|
+
return typesContainSelectionSet(sourceSubschemas.map(sourceSubschema => sourceSubschema.transformedSchema.getType(mergedTypeInfo.typeName)), selectionSet);
|
|
1351
|
+
});
|
|
1352
|
+
function typesContainSelectionSet(types, selectionSet) {
|
|
1353
|
+
var _a;
|
|
1354
|
+
const fieldMaps = types.map(type => type.getFields());
|
|
1355
|
+
for (const selection of selectionSet.selections) {
|
|
1356
|
+
if (selection.kind === graphql.Kind.FIELD) {
|
|
1357
|
+
const fields = fieldMaps.map(fieldMap => fieldMap[selection.name.value]).filter(field => field != null);
|
|
1358
|
+
if (!fields.length) {
|
|
1359
|
+
return false;
|
|
1360
|
+
}
|
|
1361
|
+
if (selection.selectionSet != null) {
|
|
1362
|
+
return typesContainSelectionSet(fields.map(field => graphql.getNamedType(field.type)), selection.selectionSet);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
else if (selection.kind === graphql.Kind.INLINE_FRAGMENT && ((_a = selection.typeCondition) === null || _a === void 0 ? void 0 : _a.name.value) === types[0].name) {
|
|
1366
|
+
return typesContainSelectionSet(types, selection.selectionSet);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* Resolver that knows how to:
|
|
1374
|
+
* a) handle aliases for proxied schemas
|
|
1375
|
+
* b) handle errors from proxied schemas
|
|
1376
|
+
* c) handle external to internal enum/scalar conversion
|
|
1377
|
+
* d) handle type merging
|
|
1378
|
+
* e) handle deferred values
|
|
1379
|
+
*/
|
|
1380
|
+
function defaultMergedResolver(parent, args, context, info) {
|
|
1381
|
+
if (!isExternalObject(parent)) {
|
|
1382
|
+
return graphql.defaultFieldResolver(parent, args, context, info);
|
|
1383
|
+
}
|
|
1384
|
+
const responseKey = utils.getResponseKeyFromInfo(info);
|
|
1385
|
+
const initialPossibleFields = getInitialPossibleFields(parent);
|
|
1386
|
+
if (initialPossibleFields === undefined) {
|
|
1387
|
+
// TODO: can this be removed in the next major release?
|
|
1388
|
+
// legacy use of delegation without setting transformedSchema
|
|
1389
|
+
const data = parent[responseKey];
|
|
1390
|
+
if (data !== undefined) {
|
|
1391
|
+
return resolveField(parent, responseKey, context, info);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
else if (info.fieldName in initialPossibleFields) {
|
|
1395
|
+
return resolveField(parent, responseKey, context, info);
|
|
1396
|
+
}
|
|
1397
|
+
return getMergedParent(parent, context, info).then(mergedParent => resolveField(mergedParent, responseKey, context, info));
|
|
1398
|
+
}
|
|
1399
|
+
function resolveField(parent, responseKey, context, info) {
|
|
1400
|
+
const initialPath = getInitialPath(parent);
|
|
1401
|
+
const subschema = getSubschema(parent, responseKey);
|
|
1402
|
+
const unpathedErrors = getUnpathedErrors(parent);
|
|
1403
|
+
return createExternalValue(parent[responseKey], unpathedErrors, initialPath, subschema, context, info);
|
|
1151
1404
|
}
|
|
1152
1405
|
|
|
1153
1406
|
function delegateToSchema(options) {
|
|
1154
|
-
const { info, schema, rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes, context, } = options;
|
|
1407
|
+
const { info, schema, rootValue = schema.rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes, context, } = options;
|
|
1155
1408
|
const request = createRequestFromInfo({
|
|
1156
1409
|
info,
|
|
1157
1410
|
operation,
|
|
1158
1411
|
fieldName,
|
|
1159
1412
|
selectionSet,
|
|
1160
1413
|
fieldNodes,
|
|
1161
|
-
rootValue
|
|
1414
|
+
rootValue,
|
|
1162
1415
|
operationName,
|
|
1163
1416
|
context,
|
|
1164
1417
|
});
|
|
1165
1418
|
return delegateRequest({
|
|
1166
1419
|
...options,
|
|
1167
1420
|
request,
|
|
1421
|
+
operation,
|
|
1422
|
+
fieldName,
|
|
1168
1423
|
});
|
|
1169
1424
|
}
|
|
1170
1425
|
function getDelegationReturnType(targetSchema, operation, fieldName) {
|
|
@@ -1172,10 +1427,30 @@ function getDelegationReturnType(targetSchema, operation, fieldName) {
|
|
|
1172
1427
|
return rootType.getFields()[fieldName].type;
|
|
1173
1428
|
}
|
|
1174
1429
|
function delegateRequest(options) {
|
|
1175
|
-
|
|
1430
|
+
var _a;
|
|
1431
|
+
let operationDefinition;
|
|
1432
|
+
let targetFieldName;
|
|
1433
|
+
const { document, operationName } = options.request;
|
|
1434
|
+
if (options.fieldName == null) {
|
|
1435
|
+
operationDefinition = graphql.getOperationAST(document, operationName);
|
|
1436
|
+
if (operationDefinition == null) {
|
|
1437
|
+
throw new Error('Cannot infer main operation from the provided document.');
|
|
1438
|
+
}
|
|
1439
|
+
targetFieldName = (operationDefinition === null || operationDefinition === void 0 ? void 0 : operationDefinition.selectionSet.selections[0]).name.value;
|
|
1440
|
+
}
|
|
1441
|
+
else {
|
|
1442
|
+
targetFieldName = options.fieldName;
|
|
1443
|
+
}
|
|
1444
|
+
const { schema, info, operation = getDelegatingOperation(info.parentType, info.schema), returnType = (_a = info === null || info === void 0 ? void 0 : info.returnType) !== null && _a !== void 0 ? _a : getDelegationReturnType(schema instanceof graphql.GraphQLSchema ? schema : schema.schema, operation, targetFieldName), context, onLocatedError = (error) => error, validateRequest: shouldValidateRequest, } = options;
|
|
1445
|
+
const delegationContext = getDelegationContext({
|
|
1446
|
+
...options,
|
|
1447
|
+
operation,
|
|
1448
|
+
fieldName: targetFieldName,
|
|
1449
|
+
returnType,
|
|
1450
|
+
});
|
|
1176
1451
|
const transformer = new Transformer(delegationContext);
|
|
1177
1452
|
const processedRequest = transformer.transformRequest(options.request);
|
|
1178
|
-
if (
|
|
1453
|
+
if (shouldValidateRequest) {
|
|
1179
1454
|
validateRequest(delegationContext, processedRequest.document);
|
|
1180
1455
|
}
|
|
1181
1456
|
const executor = getExecutor(delegationContext);
|
|
@@ -1183,13 +1458,29 @@ function delegateRequest(options) {
|
|
|
1183
1458
|
.then(originalResult => {
|
|
1184
1459
|
if (utils.isAsyncIterable(originalResult)) {
|
|
1185
1460
|
// "subscribe" to the subscription result and map the result through the transforms
|
|
1186
|
-
return utils.mapAsyncIterator(originalResult, result =>
|
|
1461
|
+
return utils.mapAsyncIterator(originalResult, result => externalValueFromResult({
|
|
1462
|
+
result: transformer.transformResult(result),
|
|
1463
|
+
schema,
|
|
1464
|
+
info,
|
|
1465
|
+
context,
|
|
1466
|
+
fieldName: targetFieldName,
|
|
1467
|
+
returnType,
|
|
1468
|
+
onLocatedError,
|
|
1469
|
+
}));
|
|
1187
1470
|
}
|
|
1188
|
-
return
|
|
1471
|
+
return externalValueFromResult({
|
|
1472
|
+
result: transformer.transformResult(originalResult),
|
|
1473
|
+
schema,
|
|
1474
|
+
info,
|
|
1475
|
+
context,
|
|
1476
|
+
fieldName: targetFieldName,
|
|
1477
|
+
returnType,
|
|
1478
|
+
onLocatedError,
|
|
1479
|
+
});
|
|
1189
1480
|
})
|
|
1190
1481
|
.resolve();
|
|
1191
1482
|
}
|
|
1192
|
-
function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema,
|
|
1483
|
+
function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema, }) {
|
|
1193
1484
|
var _a, _b, _c, _d;
|
|
1194
1485
|
const { operationType: operation, context, operationName, document } = request;
|
|
1195
1486
|
let operationDefinition;
|
|
@@ -1206,7 +1497,7 @@ function getDelegationContext({ request, schema, fieldName, returnType, args, in
|
|
|
1206
1497
|
}
|
|
1207
1498
|
const stitchingInfo = (_a = info === null || info === void 0 ? void 0 : info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
|
|
1208
1499
|
const subschemaOrSubschemaConfig = (_b = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.subschemaMap.get(schema)) !== null && _b !== void 0 ? _b : schema;
|
|
1209
|
-
if (
|
|
1500
|
+
if (!graphql.isSchema(subschemaOrSubschemaConfig)) {
|
|
1210
1501
|
const targetSchema = subschemaOrSubschemaConfig.schema;
|
|
1211
1502
|
return {
|
|
1212
1503
|
subschema: schema,
|
|
@@ -1222,7 +1513,6 @@ function getDelegationContext({ request, schema, fieldName, returnType, args, in
|
|
|
1222
1513
|
? subschemaOrSubschemaConfig.transforms.concat(transforms)
|
|
1223
1514
|
: transforms,
|
|
1224
1515
|
transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : (subschemaOrSubschemaConfig instanceof Subschema ? subschemaOrSubschemaConfig.transformedSchema : targetSchema),
|
|
1225
|
-
skipTypeMerging,
|
|
1226
1516
|
};
|
|
1227
1517
|
}
|
|
1228
1518
|
return {
|
|
@@ -1237,7 +1527,6 @@ function getDelegationContext({ request, schema, fieldName, returnType, args, in
|
|
|
1237
1527
|
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),
|
|
1238
1528
|
transforms,
|
|
1239
1529
|
transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : subschemaOrSubschemaConfig,
|
|
1240
|
-
skipTypeMerging,
|
|
1241
1530
|
};
|
|
1242
1531
|
}
|
|
1243
1532
|
function validateRequest(delegationContext, document) {
|
|
@@ -1278,22 +1567,59 @@ const createDefaultExecutor = utils.memoize1(function createDefaultExecutor(sche
|
|
|
1278
1567
|
};
|
|
1279
1568
|
});
|
|
1280
1569
|
|
|
1570
|
+
function isSubschemaConfig(value) {
|
|
1571
|
+
return Boolean(value === null || value === void 0 ? void 0 : value.schema);
|
|
1572
|
+
}
|
|
1573
|
+
function cloneSubschemaConfig(subschemaConfig) {
|
|
1574
|
+
var _a, _b;
|
|
1575
|
+
const newSubschemaConfig = {
|
|
1576
|
+
...subschemaConfig,
|
|
1577
|
+
transforms: subschemaConfig.transforms != null ? [...subschemaConfig.transforms] : undefined,
|
|
1578
|
+
};
|
|
1579
|
+
if (newSubschemaConfig.merge != null) {
|
|
1580
|
+
newSubschemaConfig.merge = { ...subschemaConfig.merge };
|
|
1581
|
+
for (const typeName in newSubschemaConfig.merge) {
|
|
1582
|
+
const mergedTypeConfig = (newSubschemaConfig.merge[typeName] = { ...((_b = (_a = subschemaConfig.merge) === null || _a === void 0 ? void 0 : _a[typeName]) !== null && _b !== void 0 ? _b : {}) });
|
|
1583
|
+
if (mergedTypeConfig.entryPoints != null) {
|
|
1584
|
+
mergedTypeConfig.entryPoints = mergedTypeConfig.entryPoints.map(entryPoint => ({ ...entryPoint }));
|
|
1585
|
+
}
|
|
1586
|
+
if (mergedTypeConfig.fields != null) {
|
|
1587
|
+
const fields = (mergedTypeConfig.fields = { ...mergedTypeConfig.fields });
|
|
1588
|
+
for (const fieldName in fields) {
|
|
1589
|
+
fields[fieldName] = { ...fields[fieldName] };
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
return newSubschemaConfig;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1281
1597
|
exports.Subschema = Subschema;
|
|
1282
1598
|
exports.Transformer = Transformer;
|
|
1283
1599
|
exports.annotateExternalObject = annotateExternalObject;
|
|
1284
1600
|
exports.applySchemaTransforms = applySchemaTransforms;
|
|
1601
|
+
exports.buildDelegationPlan = buildDelegationPlan;
|
|
1285
1602
|
exports.cloneSubschemaConfig = cloneSubschemaConfig;
|
|
1286
1603
|
exports.createDefaultExecutor = createDefaultExecutor;
|
|
1604
|
+
exports.createExternalValue = createExternalValue;
|
|
1287
1605
|
exports.createRequest = createRequest;
|
|
1288
1606
|
exports.createRequestFromInfo = createRequestFromInfo;
|
|
1289
1607
|
exports.defaultMergedResolver = defaultMergedResolver;
|
|
1290
1608
|
exports.delegateRequest = delegateRequest;
|
|
1291
1609
|
exports.delegateToSchema = delegateToSchema;
|
|
1610
|
+
exports.externalValueFromResult = externalValueFromResult;
|
|
1292
1611
|
exports.getDelegatingOperation = getDelegatingOperation;
|
|
1612
|
+
exports.getDelegationContext = getDelegationContext;
|
|
1613
|
+
exports.getExecutor = getExecutor;
|
|
1614
|
+
exports.getInfo = getInfo;
|
|
1615
|
+
exports.getInitialPath = getInitialPath;
|
|
1616
|
+
exports.getInitialPossibleFields = getInitialPossibleFields;
|
|
1617
|
+
exports.getMergedParent = getMergedParent;
|
|
1618
|
+
exports.getObjectSubchema = getObjectSubchema;
|
|
1293
1619
|
exports.getSubschema = getSubschema;
|
|
1620
|
+
exports.getSubschemaMap = getSubschemaMap;
|
|
1294
1621
|
exports.getUnpathedErrors = getUnpathedErrors;
|
|
1295
1622
|
exports.isExternalObject = isExternalObject;
|
|
1296
1623
|
exports.isSubschema = isSubschema;
|
|
1297
1624
|
exports.isSubschemaConfig = isSubschemaConfig;
|
|
1298
|
-
exports.
|
|
1299
|
-
exports.resolveExternalValue = resolveExternalValue;
|
|
1625
|
+
exports.validateRequest = validateRequest;
|