@apollo/federation-internals 2.7.2 → 2.7.3
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/dist/definitions.d.ts +2 -0
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +24 -17
- package/dist/definitions.js.map +1 -1
- package/dist/operations.d.ts +7 -2
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +22 -26
- package/dist/operations.js.map +1 -1
- package/package.json +1 -1
- package/src/definitions.ts +33 -17
- package/src/operations.ts +33 -25
package/package.json
CHANGED
package/src/definitions.ts
CHANGED
|
@@ -392,26 +392,11 @@ export class DirectiveTargetElement<T extends DirectiveTargetElement<T>> {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
appliedDirectivesToDirectiveNodes() : ConstDirectiveNode[] | undefined {
|
|
395
|
-
|
|
396
|
-
return undefined;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return this.appliedDirectives.map(directive => {
|
|
400
|
-
return {
|
|
401
|
-
kind: Kind.DIRECTIVE,
|
|
402
|
-
name: {
|
|
403
|
-
kind: Kind.NAME,
|
|
404
|
-
value: directive.name,
|
|
405
|
-
},
|
|
406
|
-
arguments: directive.argumentsToAST()
|
|
407
|
-
};
|
|
408
|
-
});
|
|
395
|
+
return directivesToDirectiveNodes(this.appliedDirectives);
|
|
409
396
|
}
|
|
410
397
|
|
|
411
398
|
appliedDirectivesToString(): string {
|
|
412
|
-
return this.appliedDirectives
|
|
413
|
-
? ''
|
|
414
|
-
: ' ' + this.appliedDirectives.join(' ');
|
|
399
|
+
return directivesToString(this.appliedDirectives);
|
|
415
400
|
}
|
|
416
401
|
|
|
417
402
|
collectVariablesInAppliedDirectives(collector: VariableCollector) {
|
|
@@ -3257,6 +3242,37 @@ export class Directive<
|
|
|
3257
3242
|
}
|
|
3258
3243
|
}
|
|
3259
3244
|
|
|
3245
|
+
/**
|
|
3246
|
+
* Formats a Directive array as a string (with a leading space, if present).
|
|
3247
|
+
*/
|
|
3248
|
+
export function directivesToString(directives?: readonly Directive<any>[])
|
|
3249
|
+
: string
|
|
3250
|
+
{
|
|
3251
|
+
return (!directives || directives.length == 0)
|
|
3252
|
+
? ''
|
|
3253
|
+
: ' ' + directives.join(' ');
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3256
|
+
/**
|
|
3257
|
+
* Converts a Directive array into DirectiveNode array.
|
|
3258
|
+
*/
|
|
3259
|
+
export function directivesToDirectiveNodes(directives?: readonly Directive<any>[])
|
|
3260
|
+
: ConstDirectiveNode[] | undefined
|
|
3261
|
+
{
|
|
3262
|
+
return (!directives || directives.length === 0)
|
|
3263
|
+
? undefined
|
|
3264
|
+
: directives.map(directive => {
|
|
3265
|
+
return {
|
|
3266
|
+
kind: Kind.DIRECTIVE,
|
|
3267
|
+
name: {
|
|
3268
|
+
kind: Kind.NAME,
|
|
3269
|
+
value: directive.name,
|
|
3270
|
+
},
|
|
3271
|
+
arguments: directive.argumentsToAST()
|
|
3272
|
+
};
|
|
3273
|
+
});
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3260
3276
|
/**
|
|
3261
3277
|
* Checks if 2 directive applications should be considered equal.
|
|
3262
3278
|
*
|
package/src/operations.ts
CHANGED
|
@@ -48,6 +48,8 @@ import {
|
|
|
48
48
|
isObjectType,
|
|
49
49
|
NamedType,
|
|
50
50
|
isUnionType,
|
|
51
|
+
directivesToString,
|
|
52
|
+
directivesToDirectiveNodes,
|
|
51
53
|
} from "./definitions";
|
|
52
54
|
import { isInterfaceObjectType } from "./federation";
|
|
53
55
|
import { ERRORS } from "./error";
|
|
@@ -877,7 +879,6 @@ function computeFragmentsToKeep(
|
|
|
877
879
|
return toExpand.size === 0 ? fragments : fragments.filter((f) => !toExpand.has(f.name));
|
|
878
880
|
}
|
|
879
881
|
|
|
880
|
-
// TODO Operations can also have directives
|
|
881
882
|
export class Operation {
|
|
882
883
|
constructor(
|
|
883
884
|
readonly schema: Schema,
|
|
@@ -885,7 +886,8 @@ export class Operation {
|
|
|
885
886
|
readonly selectionSet: SelectionSet,
|
|
886
887
|
readonly variableDefinitions: VariableDefinitions,
|
|
887
888
|
readonly fragments?: NamedFragments,
|
|
888
|
-
readonly name?: string
|
|
889
|
+
readonly name?: string,
|
|
890
|
+
readonly directives?: readonly Directive<any>[]) {
|
|
889
891
|
}
|
|
890
892
|
|
|
891
893
|
// Returns a copy of this operation with the provided updated selection set.
|
|
@@ -901,7 +903,8 @@ export class Operation {
|
|
|
901
903
|
newSelectionSet,
|
|
902
904
|
this.variableDefinitions,
|
|
903
905
|
this.fragments,
|
|
904
|
-
this.name
|
|
906
|
+
this.name,
|
|
907
|
+
this.directives
|
|
905
908
|
);
|
|
906
909
|
}
|
|
907
910
|
|
|
@@ -917,7 +920,8 @@ export class Operation {
|
|
|
917
920
|
newSelectionSet,
|
|
918
921
|
this.variableDefinitions,
|
|
919
922
|
newFragments,
|
|
920
|
-
this.name
|
|
923
|
+
this.name,
|
|
924
|
+
this.directives
|
|
921
925
|
);
|
|
922
926
|
}
|
|
923
927
|
|
|
@@ -982,6 +986,7 @@ export class Operation {
|
|
|
982
986
|
this.variableDefinitions,
|
|
983
987
|
fragments,
|
|
984
988
|
this.name,
|
|
989
|
+
this.directives
|
|
985
990
|
);
|
|
986
991
|
}
|
|
987
992
|
|
|
@@ -1053,7 +1058,7 @@ export class Operation {
|
|
|
1053
1058
|
}
|
|
1054
1059
|
|
|
1055
1060
|
toString(expandFragments: boolean = false, prettyPrint: boolean = true): string {
|
|
1056
|
-
return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, expandFragments, prettyPrint);
|
|
1061
|
+
return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, this.directives, expandFragments, prettyPrint);
|
|
1057
1062
|
}
|
|
1058
1063
|
}
|
|
1059
1064
|
|
|
@@ -1219,6 +1224,14 @@ export class NamedFragmentDefinition extends DirectiveTargetElement<NamedFragmen
|
|
|
1219
1224
|
const expandedSelectionSet = this.expandedSelectionSet();
|
|
1220
1225
|
const selectionSet = expandedSelectionSet.normalize({ parentType: type });
|
|
1221
1226
|
|
|
1227
|
+
if (!isObjectType(this.typeCondition)) {
|
|
1228
|
+
// When the type condition of the fragment is not an object type, the `FieldsInSetCanMerge` rule is more
|
|
1229
|
+
// restrictive and any fields can create conflicts. Thus, we have to use the full validator in this case.
|
|
1230
|
+
// (see https://github.com/graphql/graphql-spec/issues/1085 for details.)
|
|
1231
|
+
const validator = FieldsConflictValidator.build(expandedSelectionSet);
|
|
1232
|
+
return { selectionSet, validator };
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1222
1235
|
// Note that `trimmed` is the difference of 2 selections that may not have been normalized on the same parent type,
|
|
1223
1236
|
// so in practice, it is possible that `trimmed` contains some of the selections that `selectionSet` contains, but
|
|
1224
1237
|
// that they have been simplified in `selectionSet` in such a way that the `minus` call does not see it. However,
|
|
@@ -2077,6 +2090,7 @@ export class SelectionSet {
|
|
|
2077
2090
|
variableDefinitions: VariableDefinitions,
|
|
2078
2091
|
fragments: NamedFragments | undefined,
|
|
2079
2092
|
operationName?: string,
|
|
2093
|
+
directives?: readonly Directive<any>[],
|
|
2080
2094
|
expandFragments: boolean = false,
|
|
2081
2095
|
prettyPrint: boolean = true
|
|
2082
2096
|
): string {
|
|
@@ -2090,7 +2104,8 @@ export class SelectionSet {
|
|
|
2090
2104
|
const nameAndVariables = operationName
|
|
2091
2105
|
? " " + (operationName + (variableDefinitions.isEmpty() ? "" : variableDefinitions.toString()))
|
|
2092
2106
|
: (variableDefinitions.isEmpty() ? "" : " " + variableDefinitions.toString());
|
|
2093
|
-
|
|
2107
|
+
const directives_str = directivesToString(directives);
|
|
2108
|
+
return fragmentsDefinitions + rootKind + nameAndVariables + directives_str + " " + this.toString(expandFragments, true, indent);
|
|
2094
2109
|
}
|
|
2095
2110
|
|
|
2096
2111
|
/**
|
|
@@ -2873,7 +2888,7 @@ class FieldsConflictValidator {
|
|
|
2873
2888
|
continue;
|
|
2874
2889
|
}
|
|
2875
2890
|
|
|
2876
|
-
// We're basically checking [
|
|
2891
|
+
// We're basically checking [FieldsInSetCanMerge](https://spec.graphql.org/draft/#FieldsInSetCanMerge()),
|
|
2877
2892
|
// but from 2 set of fields (`thisFields` and `thatFields`) of the same response that we know individually
|
|
2878
2893
|
// merge already.
|
|
2879
2894
|
for (const [thisField, thisValidator] of thisFields.entries()) {
|
|
@@ -3562,7 +3577,7 @@ class FragmentSpreadSelection extends FragmentSelection {
|
|
|
3562
3577
|
|
|
3563
3578
|
key(): string {
|
|
3564
3579
|
if (!this.computedKey) {
|
|
3565
|
-
this.computedKey = '...' + this.namedFragment.name + (this.spreadDirectives
|
|
3580
|
+
this.computedKey = '...' + this.namedFragment.name + directivesToString(this.spreadDirectives);
|
|
3566
3581
|
}
|
|
3567
3582
|
return this.computedKey;
|
|
3568
3583
|
}
|
|
@@ -3588,18 +3603,7 @@ class FragmentSpreadSelection extends FragmentSelection {
|
|
|
3588
3603
|
}
|
|
3589
3604
|
|
|
3590
3605
|
toSelectionNode(): FragmentSpreadNode {
|
|
3591
|
-
const directiveNodes = this.spreadDirectives
|
|
3592
|
-
? undefined
|
|
3593
|
-
: this.spreadDirectives.map(directive => {
|
|
3594
|
-
return {
|
|
3595
|
-
kind: Kind.DIRECTIVE,
|
|
3596
|
-
name: {
|
|
3597
|
-
kind: Kind.NAME,
|
|
3598
|
-
value: directive.name,
|
|
3599
|
-
},
|
|
3600
|
-
arguments: directive.argumentsToAST()
|
|
3601
|
-
} as DirectiveNode;
|
|
3602
|
-
});
|
|
3606
|
+
const directiveNodes = directivesToDirectiveNodes(this.spreadDirectives);
|
|
3603
3607
|
return {
|
|
3604
3608
|
kind: Kind.FRAGMENT_SPREAD,
|
|
3605
3609
|
name: { kind: Kind.NAME, value: this.namedFragment.name },
|
|
@@ -3744,9 +3748,7 @@ class FragmentSpreadSelection extends FragmentSelection {
|
|
|
3744
3748
|
if (expandFragments) {
|
|
3745
3749
|
return (indent ?? '') + this.element + ' ' + this.selectionSet.toString(true, true, indent);
|
|
3746
3750
|
} else {
|
|
3747
|
-
|
|
3748
|
-
const directiveString = directives.length == 0 ? '' : ' ' + directives.join(' ');
|
|
3749
|
-
return (indent ?? '') + '...' + this.namedFragment.name + directiveString;
|
|
3751
|
+
return (indent ?? '') + '...' + this.namedFragment.name + directivesToString(this.spreadDirectives);
|
|
3750
3752
|
}
|
|
3751
3753
|
}
|
|
3752
3754
|
}
|
|
@@ -3832,6 +3834,7 @@ export function operationFromDocument(
|
|
|
3832
3834
|
}
|
|
3833
3835
|
) : Operation {
|
|
3834
3836
|
let operation: OperationDefinitionNode | undefined;
|
|
3837
|
+
let operation_directives: Directive<any>[] | undefined; // the directives on `operation`
|
|
3835
3838
|
const operationName = options?.operationName;
|
|
3836
3839
|
const fragments = new NamedFragments();
|
|
3837
3840
|
// We do a first pass to collect the operation, and create all named fragment, but without their selection set yet.
|
|
@@ -3842,6 +3845,7 @@ export function operationFromDocument(
|
|
|
3842
3845
|
validate(!operation || operationName, () => 'Must provide operation name if query contains multiple operations.');
|
|
3843
3846
|
if (!operationName || (definition.name && definition.name.value === operationName)) {
|
|
3844
3847
|
operation = definition;
|
|
3848
|
+
operation_directives = directivesOfNodes(schema, definition.directives);
|
|
3845
3849
|
}
|
|
3846
3850
|
break;
|
|
3847
3851
|
case Kind.FRAGMENT_DEFINITION:
|
|
@@ -3875,18 +3879,20 @@ export function operationFromDocument(
|
|
|
3875
3879
|
}
|
|
3876
3880
|
});
|
|
3877
3881
|
fragments.validate(variableDefinitions);
|
|
3878
|
-
return operationFromAST({schema, operation, variableDefinitions, fragments, validateInput: options?.validate});
|
|
3882
|
+
return operationFromAST({schema, operation, operation_directives, variableDefinitions, fragments, validateInput: options?.validate});
|
|
3879
3883
|
}
|
|
3880
3884
|
|
|
3881
3885
|
function operationFromAST({
|
|
3882
3886
|
schema,
|
|
3883
3887
|
operation,
|
|
3888
|
+
operation_directives,
|
|
3884
3889
|
variableDefinitions,
|
|
3885
3890
|
fragments,
|
|
3886
3891
|
validateInput,
|
|
3887
3892
|
}:{
|
|
3888
3893
|
schema: Schema,
|
|
3889
3894
|
operation: OperationDefinitionNode,
|
|
3895
|
+
operation_directives?: Directive<any>[],
|
|
3890
3896
|
variableDefinitions: VariableDefinitions,
|
|
3891
3897
|
fragments: NamedFragments,
|
|
3892
3898
|
validateInput?: boolean,
|
|
@@ -3906,7 +3912,8 @@ function operationFromAST({
|
|
|
3906
3912
|
}),
|
|
3907
3913
|
variableDefinitions,
|
|
3908
3914
|
fragmentsIfAny,
|
|
3909
|
-
operation.name?.value
|
|
3915
|
+
operation.name?.value,
|
|
3916
|
+
operation_directives
|
|
3910
3917
|
);
|
|
3911
3918
|
}
|
|
3912
3919
|
|
|
@@ -3961,6 +3968,7 @@ export function operationToDocument(operation: Operation): DocumentNode {
|
|
|
3961
3968
|
name: operation.name ? { kind: Kind.NAME, value: operation.name } : undefined,
|
|
3962
3969
|
selectionSet: operation.selectionSet.toSelectionSetNode(),
|
|
3963
3970
|
variableDefinitions: operation.variableDefinitions.toVariableDefinitionNodes(),
|
|
3971
|
+
directives: directivesToDirectiveNodes(operation.directives),
|
|
3964
3972
|
};
|
|
3965
3973
|
const fragmentASTs: DefinitionNode[] = operation.fragments
|
|
3966
3974
|
? operation.fragments?.toFragmentDefinitionNodes()
|