@apollo/federation-internals 2.7.2 → 2.7.3-testing.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/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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.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/dist/specs/connectSpec.d.ts +12 -0
- package/dist/specs/connectSpec.d.ts.map +1 -0
- package/dist/specs/connectSpec.js +82 -0
- package/dist/specs/connectSpec.js.map +1 -0
- package/package.json +1 -1
- package/src/definitions.ts +33 -17
- package/src/index.ts +1 -0
- package/src/operations.ts +33 -25
- package/src/specs/connectSpec.ts +146 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { GraphQLError } from 'graphql';
|
|
2
|
+
import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureVersion } from "./coreSpec";
|
|
3
|
+
import { Schema } from '../definitions';
|
|
4
|
+
export declare const connectIdentity = "https://specs.apollo.dev/connect";
|
|
5
|
+
export declare class ConnectSpecDefinition extends FeatureDefinition {
|
|
6
|
+
readonly minimumFederationVersion: FeatureVersion;
|
|
7
|
+
constructor(version: FeatureVersion, minimumFederationVersion: FeatureVersion);
|
|
8
|
+
addElementsToSchema(schema: Schema): GraphQLError[];
|
|
9
|
+
get defaultCorePurpose(): CorePurpose;
|
|
10
|
+
}
|
|
11
|
+
export declare const CONNECT_VERSIONS: FeatureDefinitions<ConnectSpecDefinition>;
|
|
12
|
+
//# sourceMappingURL=connectSpec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectSpec.d.ts","sourceRoot":"","sources":["../../src/specs/connectSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EACL,MAAM,EAKP,MAAM,gBAAgB,CAAC;AAIxB,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAUlE,qBAAa,qBAAsB,SAAQ,iBAAiB;IACrB,QAAQ,CAAC,wBAAwB,EAAE,cAAc;gBAA1E,OAAO,EAAE,cAAc,EAAW,wBAAwB,EAAE,cAAc;IA2BtF,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE;IAuFnD,IAAI,kBAAkB,IAAI,WAAW,CAEpC;CACF;AAED,eAAO,MAAM,gBAAgB,2CACwD,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONNECT_VERSIONS = exports.ConnectSpecDefinition = exports.connectIdentity = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const coreSpec_1 = require("./coreSpec");
|
|
6
|
+
const definitions_1 = require("../definitions");
|
|
7
|
+
const knownCoreFeatures_1 = require("../knownCoreFeatures");
|
|
8
|
+
const directiveAndTypeSpecification_1 = require("../directiveAndTypeSpecification");
|
|
9
|
+
exports.connectIdentity = 'https://specs.apollo.dev/connect';
|
|
10
|
+
const CONNECT = "connect";
|
|
11
|
+
const SOURCE = "source";
|
|
12
|
+
const URL_PATH_TEMPLATE = "URLPathTemplate";
|
|
13
|
+
const JSON_SELECTION = "JSONSelection";
|
|
14
|
+
const CONNECT_HTTP = "ConnectHTTP";
|
|
15
|
+
const SOURCE_HTTP = "SourceHTTP";
|
|
16
|
+
const HTTP_HEADER_MAPPING = "HTTPHeaderMapping";
|
|
17
|
+
class ConnectSpecDefinition extends coreSpec_1.FeatureDefinition {
|
|
18
|
+
constructor(version, minimumFederationVersion) {
|
|
19
|
+
super(new coreSpec_1.FeatureUrl(exports.connectIdentity, 'connect', version), minimumFederationVersion);
|
|
20
|
+
this.minimumFederationVersion = minimumFederationVersion;
|
|
21
|
+
this.registerDirective((0, directiveAndTypeSpecification_1.createDirectiveSpecification)({
|
|
22
|
+
name: CONNECT,
|
|
23
|
+
locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
|
|
24
|
+
repeatable: true,
|
|
25
|
+
composes: false,
|
|
26
|
+
}));
|
|
27
|
+
this.registerDirective((0, directiveAndTypeSpecification_1.createDirectiveSpecification)({
|
|
28
|
+
name: SOURCE,
|
|
29
|
+
locations: [graphql_1.DirectiveLocation.SCHEMA],
|
|
30
|
+
repeatable: true,
|
|
31
|
+
composes: false,
|
|
32
|
+
}));
|
|
33
|
+
this.registerType({ name: URL_PATH_TEMPLATE, checkOrAdd: () => [] });
|
|
34
|
+
this.registerType({ name: JSON_SELECTION, checkOrAdd: () => [] });
|
|
35
|
+
this.registerType({ name: CONNECT_HTTP, checkOrAdd: () => [] });
|
|
36
|
+
this.registerType({ name: SOURCE_HTTP, checkOrAdd: () => [] });
|
|
37
|
+
this.registerType({ name: HTTP_HEADER_MAPPING, checkOrAdd: () => [] });
|
|
38
|
+
}
|
|
39
|
+
addElementsToSchema(schema) {
|
|
40
|
+
const URLPathTemplate = this.addScalarType(schema, URL_PATH_TEMPLATE);
|
|
41
|
+
const JSONSelection = this.addScalarType(schema, JSON_SELECTION);
|
|
42
|
+
const connect = this.addDirective(schema, CONNECT).addLocations(graphql_1.DirectiveLocation.FIELD_DEFINITION);
|
|
43
|
+
connect.repeatable = true;
|
|
44
|
+
connect.addArgument(SOURCE, schema.stringType());
|
|
45
|
+
const HTTPHeaderMapping = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, HTTP_HEADER_MAPPING)));
|
|
46
|
+
HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('name')).type =
|
|
47
|
+
new definitions_1.NonNullType(schema.stringType());
|
|
48
|
+
HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('as')).type =
|
|
49
|
+
schema.stringType();
|
|
50
|
+
HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('value')).type =
|
|
51
|
+
schema.stringType();
|
|
52
|
+
const ConnectHTTP = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, CONNECT_HTTP)));
|
|
53
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('GET')).type = URLPathTemplate;
|
|
54
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('POST')).type = URLPathTemplate;
|
|
55
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('PUT')).type = URLPathTemplate;
|
|
56
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('PATCH')).type = URLPathTemplate;
|
|
57
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('DELETE')).type = URLPathTemplate;
|
|
58
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('body')).type = JSONSelection;
|
|
59
|
+
ConnectHTTP.addField(new definitions_1.InputFieldDefinition('headers')).type =
|
|
60
|
+
new definitions_1.ListType(new definitions_1.NonNullType(HTTPHeaderMapping));
|
|
61
|
+
connect.addArgument('http', ConnectHTTP);
|
|
62
|
+
connect.addArgument('selection', JSONSelection);
|
|
63
|
+
const source = this.addDirective(schema, SOURCE).addLocations(graphql_1.DirectiveLocation.SCHEMA);
|
|
64
|
+
source.repeatable = true;
|
|
65
|
+
source.addArgument('name', new definitions_1.NonNullType(schema.stringType()));
|
|
66
|
+
const SourceHTTP = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, SOURCE_HTTP)));
|
|
67
|
+
SourceHTTP.addField(new definitions_1.InputFieldDefinition('baseURL')).type =
|
|
68
|
+
new definitions_1.NonNullType(schema.stringType());
|
|
69
|
+
SourceHTTP.addField(new definitions_1.InputFieldDefinition('headers')).type =
|
|
70
|
+
new definitions_1.ListType(new definitions_1.NonNullType(HTTPHeaderMapping));
|
|
71
|
+
source.addArgument('http', SourceHTTP);
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
get defaultCorePurpose() {
|
|
75
|
+
return 'EXECUTION';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.ConnectSpecDefinition = ConnectSpecDefinition;
|
|
79
|
+
exports.CONNECT_VERSIONS = new coreSpec_1.FeatureDefinitions(exports.connectIdentity)
|
|
80
|
+
.add(new ConnectSpecDefinition(new coreSpec_1.FeatureVersion(0, 1), new coreSpec_1.FeatureVersion(2, 8)));
|
|
81
|
+
(0, knownCoreFeatures_1.registerKnownFeature)(exports.CONNECT_VERSIONS);
|
|
82
|
+
//# sourceMappingURL=connectSpec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectSpec.js","sourceRoot":"","sources":["../../src/specs/connectSpec.ts"],"names":[],"mappings":"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"}
|
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/index.ts
CHANGED
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()
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { DirectiveLocation, GraphQLError } from 'graphql';
|
|
2
|
+
import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion } from "./coreSpec";
|
|
3
|
+
import {
|
|
4
|
+
Schema,
|
|
5
|
+
NonNullType,
|
|
6
|
+
InputObjectType,
|
|
7
|
+
InputFieldDefinition,
|
|
8
|
+
ListType,
|
|
9
|
+
} from '../definitions';
|
|
10
|
+
import { registerKnownFeature } from '../knownCoreFeatures';
|
|
11
|
+
import { createDirectiveSpecification } from '../directiveAndTypeSpecification';
|
|
12
|
+
|
|
13
|
+
export const connectIdentity = 'https://specs.apollo.dev/connect';
|
|
14
|
+
|
|
15
|
+
const CONNECT = "connect";
|
|
16
|
+
const SOURCE = "source";
|
|
17
|
+
const URL_PATH_TEMPLATE = "URLPathTemplate";
|
|
18
|
+
const JSON_SELECTION = "JSONSelection";
|
|
19
|
+
const CONNECT_HTTP = "ConnectHTTP";
|
|
20
|
+
const SOURCE_HTTP = "SourceHTTP";
|
|
21
|
+
const HTTP_HEADER_MAPPING = "HTTPHeaderMapping";
|
|
22
|
+
|
|
23
|
+
export class ConnectSpecDefinition extends FeatureDefinition {
|
|
24
|
+
constructor(version: FeatureVersion, readonly minimumFederationVersion: FeatureVersion) {
|
|
25
|
+
super(new FeatureUrl(connectIdentity, 'connect', version), minimumFederationVersion);
|
|
26
|
+
|
|
27
|
+
this.registerDirective(createDirectiveSpecification({
|
|
28
|
+
name: CONNECT,
|
|
29
|
+
locations: [DirectiveLocation.FIELD_DEFINITION],
|
|
30
|
+
repeatable: true,
|
|
31
|
+
// We "compose" these directives using the `@join__directive` mechanism,
|
|
32
|
+
// so they do not need to be composed in the way passing `composes: true`
|
|
33
|
+
// here implies.
|
|
34
|
+
composes: false,
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
this.registerDirective(createDirectiveSpecification({
|
|
38
|
+
name: SOURCE,
|
|
39
|
+
locations: [DirectiveLocation.SCHEMA],
|
|
40
|
+
repeatable: true,
|
|
41
|
+
composes: false,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
this.registerType({ name: URL_PATH_TEMPLATE, checkOrAdd: () => [] });
|
|
45
|
+
this.registerType({ name: JSON_SELECTION, checkOrAdd: () => [] });
|
|
46
|
+
this.registerType({ name: CONNECT_HTTP, checkOrAdd: () => [] });
|
|
47
|
+
this.registerType({ name: SOURCE_HTTP, checkOrAdd: () => [] });
|
|
48
|
+
this.registerType({ name: HTTP_HEADER_MAPPING, checkOrAdd: () => [] });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
addElementsToSchema(schema: Schema): GraphQLError[] {
|
|
52
|
+
/* scalar URLPathTemplate */
|
|
53
|
+
const URLPathTemplate = this.addScalarType(schema, URL_PATH_TEMPLATE);
|
|
54
|
+
|
|
55
|
+
/* scalar JSONSelection */
|
|
56
|
+
const JSONSelection = this.addScalarType(schema, JSON_SELECTION);
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
directive @connect(
|
|
60
|
+
source: String
|
|
61
|
+
http: ConnectHTTP
|
|
62
|
+
selection: JSONSelection!
|
|
63
|
+
) repeatable on FIELD_DEFINITION
|
|
64
|
+
*/
|
|
65
|
+
const connect = this.addDirective(schema, CONNECT).addLocations(DirectiveLocation.FIELD_DEFINITION);
|
|
66
|
+
connect.repeatable = true;
|
|
67
|
+
|
|
68
|
+
connect.addArgument(SOURCE, schema.stringType());
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
input HTTPHeaderMapping {
|
|
72
|
+
name: String!
|
|
73
|
+
as: String
|
|
74
|
+
value: String
|
|
75
|
+
}
|
|
76
|
+
*/
|
|
77
|
+
const HTTPHeaderMapping = schema.addType(new InputObjectType(this.typeNameInSchema(schema, HTTP_HEADER_MAPPING)!));
|
|
78
|
+
HTTPHeaderMapping.addField(new InputFieldDefinition('name')).type =
|
|
79
|
+
new NonNullType(schema.stringType());
|
|
80
|
+
HTTPHeaderMapping.addField(new InputFieldDefinition('as')).type =
|
|
81
|
+
schema.stringType();
|
|
82
|
+
HTTPHeaderMapping.addField(new InputFieldDefinition('value')).type =
|
|
83
|
+
schema.stringType();
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
input ConnectHTTP {
|
|
87
|
+
GET: URLPathTemplate
|
|
88
|
+
POST: URLPathTemplate
|
|
89
|
+
PUT: URLPathTemplate
|
|
90
|
+
PATCH: URLPathTemplate
|
|
91
|
+
DELETE: URLPathTemplate
|
|
92
|
+
body: JSONSelection
|
|
93
|
+
headers: [HTTPHeaderMapping!]
|
|
94
|
+
}
|
|
95
|
+
*/
|
|
96
|
+
const ConnectHTTP = schema.addType(new InputObjectType(this.typeNameInSchema(schema, CONNECT_HTTP)!));
|
|
97
|
+
ConnectHTTP.addField(new InputFieldDefinition('GET')).type = URLPathTemplate;
|
|
98
|
+
ConnectHTTP.addField(new InputFieldDefinition('POST')).type = URLPathTemplate;
|
|
99
|
+
ConnectHTTP.addField(new InputFieldDefinition('PUT')).type = URLPathTemplate;
|
|
100
|
+
ConnectHTTP.addField(new InputFieldDefinition('PATCH')).type = URLPathTemplate;
|
|
101
|
+
ConnectHTTP.addField(new InputFieldDefinition('DELETE')).type = URLPathTemplate;
|
|
102
|
+
ConnectHTTP.addField(new InputFieldDefinition('body')).type = JSONSelection;
|
|
103
|
+
ConnectHTTP.addField(new InputFieldDefinition('headers')).type =
|
|
104
|
+
new ListType(new NonNullType(HTTPHeaderMapping));
|
|
105
|
+
connect.addArgument('http', ConnectHTTP);
|
|
106
|
+
|
|
107
|
+
connect.addArgument('selection', JSONSelection);
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
directive @source(
|
|
111
|
+
name: String!
|
|
112
|
+
http: ConnectHTTP
|
|
113
|
+
) repeatable on SCHEMA
|
|
114
|
+
*/
|
|
115
|
+
const source = this.addDirective(schema, SOURCE).addLocations(
|
|
116
|
+
DirectiveLocation.SCHEMA,
|
|
117
|
+
);
|
|
118
|
+
source.repeatable = true;
|
|
119
|
+
source.addArgument('name', new NonNullType(schema.stringType()));
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
input SourceHTTP {
|
|
123
|
+
baseURL: String!
|
|
124
|
+
headers: [HTTPHeaderMapping!]
|
|
125
|
+
}
|
|
126
|
+
*/
|
|
127
|
+
const SourceHTTP = schema.addType(new InputObjectType(this.typeNameInSchema(schema, SOURCE_HTTP)!));
|
|
128
|
+
SourceHTTP.addField(new InputFieldDefinition('baseURL')).type =
|
|
129
|
+
new NonNullType(schema.stringType());
|
|
130
|
+
SourceHTTP.addField(new InputFieldDefinition('headers')).type =
|
|
131
|
+
new ListType(new NonNullType(HTTPHeaderMapping));
|
|
132
|
+
|
|
133
|
+
source.addArgument('http', SourceHTTP);
|
|
134
|
+
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
get defaultCorePurpose(): CorePurpose {
|
|
139
|
+
return 'EXECUTION';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const CONNECT_VERSIONS = new FeatureDefinitions<ConnectSpecDefinition>(connectIdentity)
|
|
144
|
+
.add(new ConnectSpecDefinition(new FeatureVersion(0, 1), new FeatureVersion(2, 8)));
|
|
145
|
+
|
|
146
|
+
registerKnownFeature(CONNECT_VERSIONS);
|