@apollo/federation-internals 2.9.0-connectors.9 → 2.9.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/argumentCompositionStrategies.d.ts +17 -0
- package/dist/argumentCompositionStrategies.d.ts.map +1 -1
- package/dist/argumentCompositionStrategies.js +38 -0
- package/dist/argumentCompositionStrategies.js.map +1 -1
- package/dist/error.d.ts +19 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +38 -0
- package/dist/error.js.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.js +59 -8
- package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
- package/dist/federation.d.ts +9 -2
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +42 -5
- package/dist/federation.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/knownCoreFeatures.d.ts +3 -0
- package/dist/knownCoreFeatures.d.ts.map +1 -1
- package/dist/knownCoreFeatures.js +12 -1
- package/dist/knownCoreFeatures.js.map +1 -1
- package/dist/operations.d.ts +3 -1
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +26 -5
- package/dist/operations.js.map +1 -1
- package/dist/schemaUpgrader.d.ts.map +1 -1
- package/dist/schemaUpgrader.js +50 -31
- package/dist/schemaUpgrader.js.map +1 -1
- package/dist/specs/coreSpec.d.ts +2 -0
- package/dist/specs/coreSpec.d.ts.map +1 -1
- package/dist/specs/coreSpec.js +21 -0
- package/dist/specs/coreSpec.js.map +1 -1
- package/dist/specs/costSpec.d.ts +17 -0
- package/dist/specs/costSpec.d.ts.map +1 -0
- package/dist/specs/costSpec.js +49 -0
- package/dist/specs/costSpec.js.map +1 -0
- package/dist/specs/federationSpec.d.ts +6 -1
- package/dist/specs/federationSpec.d.ts.map +1 -1
- package/dist/specs/federationSpec.js +15 -1
- package/dist/specs/federationSpec.js.map +1 -1
- package/dist/specs/sourceSpec.d.ts +69 -0
- package/dist/specs/sourceSpec.d.ts.map +1 -0
- package/dist/specs/sourceSpec.js +345 -0
- package/dist/specs/sourceSpec.js.map +1 -0
- package/dist/supergraphs.d.ts +1 -1
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +1 -0
- package/dist/supergraphs.js.map +1 -1
- package/package.json +1 -1
- package/src/argumentCompositionStrategies.ts +37 -0
- package/src/error.ts +137 -4
- package/src/extractSubgraphsFromSupergraph.ts +94 -7
- package/src/federation.ts +89 -33
- package/src/index.ts +2 -1
- package/src/knownCoreFeatures.ts +15 -0
- package/src/operations.ts +41 -4
- package/src/schemaUpgrader.ts +55 -31
- package/src/specs/coreSpec.ts +26 -0
- package/src/specs/costSpec.ts +60 -0
- package/src/specs/federationSpec.ts +17 -1
- package/src/specs/sourceSpec.ts +607 -0
- package/src/supergraphs.ts +2 -1
- package/dist/specs/connectSpec.d.ts +0 -42
- package/dist/specs/connectSpec.d.ts.map +0 -1
- package/dist/specs/connectSpec.js +0 -83
- package/dist/specs/connectSpec.js.map +0 -1
- package/src/specs/connectSpec.ts +0 -183
package/src/error.ts
CHANGED
|
@@ -591,10 +591,123 @@ const INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE = makeCodeDefinition(
|
|
|
591
591
|
{ addedIn: '2.3.0' },
|
|
592
592
|
)
|
|
593
593
|
|
|
594
|
+
const SOURCE_FEDERATION_VERSION_REQUIRED = makeCodeDefinition(
|
|
595
|
+
'SOURCE_FEDERATION_VERSION_REQUIRED',
|
|
596
|
+
'Schemas using `@source{API,Type,Field}` directives must @link-import v2.7 or later of federation',
|
|
597
|
+
{ addedIn: '2.7.1' },
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
const SOURCE_API_NAME_INVALID = makeCodeDefinition(
|
|
601
|
+
'SOURCE_API_NAME_INVALID',
|
|
602
|
+
'Each `@sourceAPI` directive must take a unique and valid name as an argument',
|
|
603
|
+
{ addedIn: '2.7.0' },
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
const SOURCE_API_PROTOCOL_INVALID = makeCodeDefinition(
|
|
607
|
+
'SOURCE_API_PROTOCOL_INVALID',
|
|
608
|
+
'Each `@sourceAPI` directive must specify exactly one of the known protocols',
|
|
609
|
+
{ addedIn: '2.7.0' },
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
const SOURCE_API_HTTP_BASE_URL_INVALID = makeCodeDefinition(
|
|
613
|
+
'SOURCE_API_HTTP_BASE_URL_INVALID',
|
|
614
|
+
'The `@sourceAPI` directive must specify a valid http.baseURL',
|
|
615
|
+
{ addedIn: '2.7.0' },
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
const SOURCE_HTTP_HEADERS_INVALID = makeCodeDefinition(
|
|
619
|
+
'SOURCE_HTTP_HEADERS_INVALID',
|
|
620
|
+
'The `http.headers` argument of `@source*` directives must specify valid HTTP headers',
|
|
621
|
+
{ addedIn: '2.7.0' },
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
const SOURCE_TYPE_API_ERROR = makeCodeDefinition(
|
|
625
|
+
'SOURCE_TYPE_API_ERROR',
|
|
626
|
+
'The `api` argument of the `@sourceType` directive must match a valid `@sourceAPI` name',
|
|
627
|
+
{ addedIn: '2.7.0' },
|
|
628
|
+
);
|
|
629
|
+
|
|
630
|
+
const SOURCE_TYPE_PROTOCOL_INVALID = makeCodeDefinition(
|
|
631
|
+
'SOURCE_TYPE_PROTOCOL_INVALID',
|
|
632
|
+
'The `@sourceType` directive must specify the same protocol as its corresponding `@sourceAPI`',
|
|
633
|
+
{ addedIn: '2.7.0' },
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
const SOURCE_TYPE_HTTP_METHOD_INVALID = makeCodeDefinition(
|
|
637
|
+
'SOURCE_TYPE_HTTP_METHOD_INVALID',
|
|
638
|
+
'The `@sourceType` directive must specify exactly one of `http.GET` or `http.POST`',
|
|
639
|
+
{ addedIn: '2.7.0' },
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
const SOURCE_TYPE_HTTP_PATH_INVALID = makeCodeDefinition(
|
|
643
|
+
'SOURCE_TYPE_HTTP_PATH_INVALID',
|
|
644
|
+
'The `@sourceType` directive must specify a valid URL template for `http.GET` or `http.POST`',
|
|
645
|
+
{ addedIn: '2.7.0' },
|
|
646
|
+
);
|
|
647
|
+
|
|
648
|
+
const SOURCE_TYPE_HTTP_BODY_INVALID = makeCodeDefinition(
|
|
649
|
+
'SOURCE_TYPE_HTTP_BODY_INVALID',
|
|
650
|
+
'If the `@sourceType` specifies `http.body`, it must be a valid `JSONSelection`',
|
|
651
|
+
{ addedIn: '2.7.0' },
|
|
652
|
+
);
|
|
653
|
+
|
|
654
|
+
const SOURCE_TYPE_ON_NON_OBJECT_OR_NON_ENTITY = makeCodeDefinition(
|
|
655
|
+
'SOURCE_TYPE_ON_NON_OBJECT_OR_NON_ENTITY',
|
|
656
|
+
'The `@sourceType` directive must be applied to an object or interface type that also has `@key`',
|
|
657
|
+
{ addedIn: '2.7.0' },
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
const SOURCE_TYPE_SELECTION_INVALID = makeCodeDefinition(
|
|
661
|
+
'SOURCE_TYPE_SELECTION_INVALID',
|
|
662
|
+
'The `selection` argument of the `@sourceType` directive must be a valid `JSONSelection` that outputs fields of the GraphQL type',
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
const SOURCE_FIELD_API_ERROR = makeCodeDefinition(
|
|
666
|
+
'SOURCE_FIELD_API_ERROR',
|
|
667
|
+
'The `api` argument of the `@sourceField` directive must match a valid `@sourceAPI` name',
|
|
668
|
+
{ addedIn: '2.7.0' },
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
const SOURCE_FIELD_PROTOCOL_INVALID = makeCodeDefinition(
|
|
672
|
+
'SOURCE_FIELD_PROTOCOL_INVALID',
|
|
673
|
+
'If `@sourceField` specifies a protocol, it must match the corresponding `@sourceAPI` protocol',
|
|
674
|
+
{ addedIn: '2.7.0' },
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
const SOURCE_FIELD_HTTP_METHOD_INVALID = makeCodeDefinition(
|
|
678
|
+
'SOURCE_FIELD_HTTP_METHOD_INVALID',
|
|
679
|
+
'The `@sourceField` directive must specify at most one of `http.{GET,POST,PUT,PATCH,DELETE}`',
|
|
680
|
+
{ addedIn: '2.7.0' },
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
const SOURCE_FIELD_HTTP_PATH_INVALID = makeCodeDefinition(
|
|
684
|
+
'SOURCE_FIELD_HTTP_PATH_INVALID',
|
|
685
|
+
'The `@sourceField` directive must specify a valid URL template for `http.{GET,POST,PUT,PATCH,DELETE}`',
|
|
686
|
+
{ addedIn: '2.7.0' },
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
const SOURCE_FIELD_HTTP_BODY_INVALID = makeCodeDefinition(
|
|
690
|
+
'SOURCE_FIELD_HTTP_BODY_INVALID',
|
|
691
|
+
'If `@sourceField` specifies http.body, it must be a valid `JSONSelection` matching available arguments and fields',
|
|
692
|
+
{ addedIn: '2.7.0' },
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
const SOURCE_FIELD_SELECTION_INVALID = makeCodeDefinition(
|
|
696
|
+
'SOURCE_FIELD_SELECTION_INVALID',
|
|
697
|
+
'The `selection` argument of the `@sourceField` directive must be a valid `JSONSelection` that outputs fields of the GraphQL type',
|
|
698
|
+
{ addedIn: '2.7.0' },
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
const SOURCE_FIELD_NOT_ON_ROOT_OR_ENTITY_FIELD = makeCodeDefinition(
|
|
702
|
+
'SOURCE_FIELD_NOT_ON_ROOT_OR_ENTITY_FIELD',
|
|
703
|
+
'The `@sourceField` directive must be applied to a field of the `Query` or `Mutation` types, or of an entity type',
|
|
704
|
+
{ addedIn: '2.7.0' },
|
|
705
|
+
);
|
|
706
|
+
|
|
594
707
|
const CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS = makeCodeDefinition(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
708
|
+
'CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS',
|
|
709
|
+
'Argument on field is marked contextual in only some subgraphs',
|
|
710
|
+
{ addedIn: '2.7.0' },
|
|
598
711
|
);
|
|
599
712
|
|
|
600
713
|
export const ERROR_CATEGORIES = {
|
|
@@ -690,7 +803,27 @@ export const ERRORS = {
|
|
|
690
803
|
INTERFACE_OBJECT_USAGE_ERROR,
|
|
691
804
|
INTERFACE_KEY_NOT_ON_IMPLEMENTATION,
|
|
692
805
|
INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE,
|
|
693
|
-
|
|
806
|
+
// Errors related to @sourceAPI, @sourceType, and/or @sourceField
|
|
807
|
+
SOURCE_FEDERATION_VERSION_REQUIRED,
|
|
808
|
+
SOURCE_API_NAME_INVALID,
|
|
809
|
+
SOURCE_API_PROTOCOL_INVALID,
|
|
810
|
+
SOURCE_API_HTTP_BASE_URL_INVALID,
|
|
811
|
+
SOURCE_HTTP_HEADERS_INVALID,
|
|
812
|
+
SOURCE_TYPE_API_ERROR,
|
|
813
|
+
SOURCE_TYPE_PROTOCOL_INVALID,
|
|
814
|
+
SOURCE_TYPE_HTTP_METHOD_INVALID,
|
|
815
|
+
SOURCE_TYPE_HTTP_PATH_INVALID,
|
|
816
|
+
SOURCE_TYPE_HTTP_BODY_INVALID,
|
|
817
|
+
SOURCE_TYPE_ON_NON_OBJECT_OR_NON_ENTITY,
|
|
818
|
+
SOURCE_TYPE_SELECTION_INVALID,
|
|
819
|
+
SOURCE_FIELD_API_ERROR,
|
|
820
|
+
SOURCE_FIELD_PROTOCOL_INVALID,
|
|
821
|
+
SOURCE_FIELD_HTTP_METHOD_INVALID,
|
|
822
|
+
SOURCE_FIELD_HTTP_PATH_INVALID,
|
|
823
|
+
SOURCE_FIELD_HTTP_BODY_INVALID,
|
|
824
|
+
SOURCE_FIELD_SELECTION_INVALID,
|
|
825
|
+
SOURCE_FIELD_NOT_ON_ROOT_OR_ENTITY_FIELD,
|
|
826
|
+
CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS,
|
|
694
827
|
};
|
|
695
828
|
|
|
696
829
|
const codeDefByCode = Object.values(ERRORS).reduce((obj: {[code: string]: ErrorCodeDefinition}, codeDef: ErrorCodeDefinition) => { obj[codeDef.code] = codeDef; return obj; }, {});
|
|
@@ -40,7 +40,7 @@ import { parseSelectionSet } from "./operations";
|
|
|
40
40
|
import fs from 'fs';
|
|
41
41
|
import path from 'path';
|
|
42
42
|
import { validateStringContainsBoolean } from "./utils";
|
|
43
|
-
import { CONTEXT_VERSIONS, ContextSpecDefinition, DirectiveDefinition, errorCauses, isFederationDirectiveDefinedInSchema, printErrors } from ".";
|
|
43
|
+
import { CONTEXT_VERSIONS, ContextSpecDefinition, DirectiveDefinition, FeatureUrl, FederationDirectiveName, SchemaElement, errorCauses, isFederationDirectiveDefinedInSchema, printErrors } from ".";
|
|
44
44
|
|
|
45
45
|
function filteredTypes(
|
|
46
46
|
supergraph: Schema,
|
|
@@ -224,11 +224,13 @@ export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtra
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
const types = filteredTypes(supergraph, joinSpec, coreFeatures.coreDefinition);
|
|
227
|
+
const originalDirectiveNames = getApolloDirectiveNames(supergraph);
|
|
227
228
|
const args: ExtractArguments = {
|
|
228
229
|
supergraph,
|
|
229
230
|
subgraphs,
|
|
230
231
|
joinSpec,
|
|
231
232
|
filteredTypes: types,
|
|
233
|
+
originalDirectiveNames,
|
|
232
234
|
getSubgraph,
|
|
233
235
|
getSubgraphEnumValue,
|
|
234
236
|
};
|
|
@@ -292,6 +294,7 @@ type ExtractArguments = {
|
|
|
292
294
|
subgraphs: Subgraphs,
|
|
293
295
|
joinSpec: JoinSpecDefinition,
|
|
294
296
|
filteredTypes: NamedType[],
|
|
297
|
+
originalDirectiveNames: Record<string, string>,
|
|
295
298
|
getSubgraph: (application: Directive<any, { graph?: string }>) => Subgraph | undefined,
|
|
296
299
|
getSubgraphEnumValue: (subgraphName: string) => string
|
|
297
300
|
}
|
|
@@ -348,7 +351,8 @@ function addAllEmptySubgraphTypes(args: ExtractArguments): TypesInfo {
|
|
|
348
351
|
for (const application of typeApplications) {
|
|
349
352
|
const subgraph = getSubgraph(application);
|
|
350
353
|
assert(subgraph, () => `Should have found the subgraph for ${application}`);
|
|
351
|
-
subgraph.schema.addType(newNamedType(type.kind, type.name));
|
|
354
|
+
const subgraphType = subgraph.schema.addType(newNamedType(type.kind, type.name));
|
|
355
|
+
propagateDemandControlDirectives(type, subgraphType, subgraph, args.originalDirectiveNames);
|
|
352
356
|
}
|
|
353
357
|
break;
|
|
354
358
|
}
|
|
@@ -434,6 +438,8 @@ function extractObjOrItfContent(args: ExtractArguments, info: TypeInfo<ObjectTyp
|
|
|
434
438
|
const implementsDirective = args.joinSpec.implementsDirective(args.supergraph);
|
|
435
439
|
assert(implementsDirective, '@join__implements should existing for a fed2 supergraph');
|
|
436
440
|
|
|
441
|
+
const originalDirectiveNames = args.originalDirectiveNames;
|
|
442
|
+
|
|
437
443
|
for (const { type, subgraphsInfo } of info) {
|
|
438
444
|
const implementsApplications = type.appliedDirectivesOf(implementsDirective);
|
|
439
445
|
for (const application of implementsApplications) {
|
|
@@ -444,13 +450,17 @@ function extractObjOrItfContent(args: ExtractArguments, info: TypeInfo<ObjectTyp
|
|
|
444
450
|
subgraphInfo.type.addImplementedInterface(args.interface);
|
|
445
451
|
}
|
|
446
452
|
|
|
453
|
+
for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
|
|
454
|
+
propagateDemandControlDirectives(type, subgraphType, subgraph, args.originalDirectiveNames);
|
|
455
|
+
}
|
|
456
|
+
|
|
447
457
|
for (const field of type.fields()) {
|
|
448
458
|
const fieldApplications = field.appliedDirectivesOf(fieldDirective);
|
|
449
459
|
if (fieldApplications.length === 0) {
|
|
450
460
|
// In fed2 subgraph, no @join__field means that the field is in all the subgraphs in which the type is.
|
|
451
461
|
const isShareable = isObjectType(type) && subgraphsInfo.size > 1;
|
|
452
462
|
for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
|
|
453
|
-
addSubgraphField({ field, type: subgraphType, subgraph, isShareable });
|
|
463
|
+
addSubgraphField({ field, type: subgraphType, subgraph, isShareable, originalDirectiveNames });
|
|
454
464
|
}
|
|
455
465
|
} else {
|
|
456
466
|
const isShareable = isObjectType(type)
|
|
@@ -468,15 +478,58 @@ function extractObjOrItfContent(args: ExtractArguments, info: TypeInfo<ObjectTyp
|
|
|
468
478
|
}
|
|
469
479
|
|
|
470
480
|
const { type: subgraphType, subgraph } = subgraphsInfo.get(joinFieldArgs.graph)!;
|
|
471
|
-
addSubgraphField({ field, type: subgraphType, subgraph, isShareable, joinFieldArgs });
|
|
481
|
+
addSubgraphField({ field, type: subgraphType, subgraph, isShareable, joinFieldArgs, originalDirectiveNames });
|
|
472
482
|
}
|
|
473
483
|
}
|
|
474
484
|
}
|
|
475
485
|
}
|
|
476
486
|
}
|
|
477
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Builds a map of original name to new name for Apollo feature directives. This is
|
|
490
|
+
* used to handle cases where a directive is renamed via an import statement. For
|
|
491
|
+
* example, importing a directive with a custom name like
|
|
492
|
+
* ```graphql
|
|
493
|
+
* @link(url: "https://specs.apollo.dev/cost/v0.1", import: [{ name: "@cost", as: "@renamedCost" }])
|
|
494
|
+
* ```
|
|
495
|
+
* results in a map entry of `cost -> renamedCost` with the `@` prefix removed.
|
|
496
|
+
*
|
|
497
|
+
* If the directive is imported under its default name, that also results in an entry. So,
|
|
498
|
+
* ```graphql
|
|
499
|
+
* @link(url: "https://specs.apollo.dev/cost/v0.1", import: ["@cost"])
|
|
500
|
+
* ```
|
|
501
|
+
* results in a map entry of `cost -> cost`. This duals as a way to check if a directive
|
|
502
|
+
* is included in the supergraph schema.
|
|
503
|
+
*
|
|
504
|
+
* **Important:** This map does _not_ include directives imported from identities other
|
|
505
|
+
* than `specs.apollo.dev`. This helps us avoid extracting directives to subgraphs
|
|
506
|
+
* when a custom directive's name conflicts with that of a default one.
|
|
507
|
+
*/
|
|
508
|
+
function getApolloDirectiveNames(supergraph: Schema): Record<string, string> {
|
|
509
|
+
const originalDirectiveNames: Record<string, string> = {};
|
|
510
|
+
for (const linkDirective of supergraph.schemaDefinition.appliedDirectivesOf("link")) {
|
|
511
|
+
if (linkDirective.arguments().url && linkDirective.arguments().import) {
|
|
512
|
+
const url = FeatureUrl.maybeParse(linkDirective.arguments().url);
|
|
513
|
+
if (!url?.identity.includes("specs.apollo.dev")) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
for (const importedDirective of linkDirective.arguments().import) {
|
|
518
|
+
if (importedDirective.name && importedDirective.as) {
|
|
519
|
+
originalDirectiveNames[importedDirective.name.replace('@', '')] = importedDirective.as.replace('@', '');
|
|
520
|
+
} else if (typeof importedDirective === 'string') {
|
|
521
|
+
originalDirectiveNames[importedDirective.replace('@', '')] = importedDirective.replace('@', '');
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return originalDirectiveNames;
|
|
528
|
+
}
|
|
529
|
+
|
|
478
530
|
function extractInputObjContent(args: ExtractArguments, info: TypeInfo<InputObjectType>[]) {
|
|
479
531
|
const fieldDirective = args.joinSpec.fieldDirective(args.supergraph);
|
|
532
|
+
const originalDirectiveNames = args.originalDirectiveNames;
|
|
480
533
|
|
|
481
534
|
for (const { type, subgraphsInfo } of info) {
|
|
482
535
|
for (const field of type.fields()) {
|
|
@@ -484,7 +537,7 @@ function extractInputObjContent(args: ExtractArguments, info: TypeInfo<InputObje
|
|
|
484
537
|
if (fieldApplications.length === 0) {
|
|
485
538
|
// In fed2 subgraph, no @join__field means that the field is in all the subgraphs in which the type is.
|
|
486
539
|
for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
|
|
487
|
-
addSubgraphInputField({ field, type: subgraphType, subgraph });
|
|
540
|
+
addSubgraphInputField({ field, type: subgraphType, subgraph, originalDirectiveNames });
|
|
488
541
|
}
|
|
489
542
|
} else {
|
|
490
543
|
for (const application of fieldApplications) {
|
|
@@ -496,7 +549,7 @@ function extractInputObjContent(args: ExtractArguments, info: TypeInfo<InputObje
|
|
|
496
549
|
}
|
|
497
550
|
|
|
498
551
|
const { type: subgraphType, subgraph } = subgraphsInfo.get(args.graph)!;
|
|
499
|
-
addSubgraphInputField({ field, type: subgraphType, subgraph, joinFieldArgs: args});
|
|
552
|
+
addSubgraphInputField({ field, type: subgraphType, subgraph, joinFieldArgs: args, originalDirectiveNames });
|
|
500
553
|
}
|
|
501
554
|
}
|
|
502
555
|
}
|
|
@@ -506,8 +559,13 @@ function extractInputObjContent(args: ExtractArguments, info: TypeInfo<InputObje
|
|
|
506
559
|
function extractEnumTypeContent(args: ExtractArguments, info: TypeInfo<EnumType>[]) {
|
|
507
560
|
// This was added in join 0.3, so it can genuinely be undefined.
|
|
508
561
|
const enumValueDirective = args.joinSpec.enumValueDirective(args.supergraph);
|
|
562
|
+
const originalDirectiveNames = args.originalDirectiveNames;
|
|
509
563
|
|
|
510
564
|
for (const { type, subgraphsInfo } of info) {
|
|
565
|
+
for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
|
|
566
|
+
propagateDemandControlDirectives(type, subgraphType, subgraph, originalDirectiveNames);
|
|
567
|
+
}
|
|
568
|
+
|
|
511
569
|
for (const value of type.values) {
|
|
512
570
|
const enumValueApplications = enumValueDirective ? value.appliedDirectivesOf(enumValueDirective) : [];
|
|
513
571
|
if (enumValueApplications.length === 0) {
|
|
@@ -620,6 +678,24 @@ function maybeDumpSubgraphSchema(subgraph: Subgraph): string {
|
|
|
620
678
|
}
|
|
621
679
|
}
|
|
622
680
|
|
|
681
|
+
function propagateDemandControlDirectives(source: SchemaElement<any, any>, dest: SchemaElement<any, any>, subgraph: Subgraph, originalDirectiveNames?: Record<string, string>) {
|
|
682
|
+
const costDirectiveName = originalDirectiveNames?.[FederationDirectiveName.COST];
|
|
683
|
+
if (costDirectiveName) {
|
|
684
|
+
const costDirective = source.appliedDirectivesOf(costDirectiveName).pop();
|
|
685
|
+
if (costDirective) {
|
|
686
|
+
dest.applyDirective(subgraph.metadata().costDirective().name, costDirective.arguments());
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const listSizeDirectiveName = originalDirectiveNames?.[FederationDirectiveName.LIST_SIZE];
|
|
691
|
+
if (listSizeDirectiveName) {
|
|
692
|
+
const listSizeDirective = source.appliedDirectivesOf(listSizeDirectiveName).pop();
|
|
693
|
+
if (listSizeDirective) {
|
|
694
|
+
dest.applyDirective(subgraph.metadata().listSizeDirective().name, listSizeDirective.arguments());
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
623
699
|
function errorToString(e: any,): string {
|
|
624
700
|
const causes = errorCauses(e);
|
|
625
701
|
return causes ? printErrors(causes) : String(e);
|
|
@@ -631,12 +707,14 @@ function addSubgraphField({
|
|
|
631
707
|
subgraph,
|
|
632
708
|
isShareable,
|
|
633
709
|
joinFieldArgs,
|
|
710
|
+
originalDirectiveNames,
|
|
634
711
|
}: {
|
|
635
712
|
field: FieldDefinition<ObjectType | InterfaceType>,
|
|
636
713
|
type: ObjectType | InterfaceType,
|
|
637
714
|
subgraph: Subgraph,
|
|
638
715
|
isShareable: boolean,
|
|
639
716
|
joinFieldArgs?: JoinFieldDirectiveArguments,
|
|
717
|
+
originalDirectiveNames?: Record<string, string>,
|
|
640
718
|
}): FieldDefinition<ObjectType | InterfaceType> {
|
|
641
719
|
const copiedFieldType = joinFieldArgs?.type
|
|
642
720
|
? decodeType(joinFieldArgs.type, subgraph.schema, subgraph.name)
|
|
@@ -644,7 +722,8 @@ function addSubgraphField({
|
|
|
644
722
|
|
|
645
723
|
const subgraphField = type.addField(field.name, copiedFieldType);
|
|
646
724
|
for (const arg of field.arguments()) {
|
|
647
|
-
subgraphField.addArgument(arg.name, copyType(arg.type!, subgraph.schema, subgraph.name), arg.defaultValue);
|
|
725
|
+
const argDef = subgraphField.addArgument(arg.name, copyType(arg.type!, subgraph.schema, subgraph.name), arg.defaultValue);
|
|
726
|
+
propagateDemandControlDirectives(arg, argDef, subgraph, originalDirectiveNames)
|
|
648
727
|
}
|
|
649
728
|
if (joinFieldArgs?.requires) {
|
|
650
729
|
subgraphField.applyDirective(subgraph.metadata().requiresDirective(), {'fields': joinFieldArgs.requires});
|
|
@@ -689,6 +768,9 @@ function addSubgraphField({
|
|
|
689
768
|
if (isShareable && !external && !usedOverridden) {
|
|
690
769
|
subgraphField.applyDirective(subgraph.metadata().shareableDirective());
|
|
691
770
|
}
|
|
771
|
+
|
|
772
|
+
propagateDemandControlDirectives(field, subgraphField, subgraph, originalDirectiveNames);
|
|
773
|
+
|
|
692
774
|
return subgraphField;
|
|
693
775
|
}
|
|
694
776
|
|
|
@@ -697,11 +779,13 @@ function addSubgraphInputField({
|
|
|
697
779
|
type,
|
|
698
780
|
subgraph,
|
|
699
781
|
joinFieldArgs,
|
|
782
|
+
originalDirectiveNames,
|
|
700
783
|
}: {
|
|
701
784
|
field: InputFieldDefinition,
|
|
702
785
|
type: InputObjectType,
|
|
703
786
|
subgraph: Subgraph,
|
|
704
787
|
joinFieldArgs?: JoinFieldDirectiveArguments,
|
|
788
|
+
originalDirectiveNames?: Record<string, string>
|
|
705
789
|
}): InputFieldDefinition {
|
|
706
790
|
const copiedType = joinFieldArgs?.type
|
|
707
791
|
? decodeType(joinFieldArgs?.type, subgraph.schema, subgraph.name)
|
|
@@ -709,6 +793,9 @@ function addSubgraphInputField({
|
|
|
709
793
|
|
|
710
794
|
const inputField = type.addField(field.name, copiedType);
|
|
711
795
|
inputField.defaultValue = field.defaultValue
|
|
796
|
+
|
|
797
|
+
propagateDemandControlDirectives(field, inputField, subgraph, originalDirectiveNames);
|
|
798
|
+
|
|
712
799
|
return inputField;
|
|
713
800
|
}
|
|
714
801
|
|