@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.
Files changed (69) hide show
  1. package/dist/argumentCompositionStrategies.d.ts +17 -0
  2. package/dist/argumentCompositionStrategies.d.ts.map +1 -1
  3. package/dist/argumentCompositionStrategies.js +38 -0
  4. package/dist/argumentCompositionStrategies.js.map +1 -1
  5. package/dist/error.d.ts +19 -0
  6. package/dist/error.d.ts.map +1 -1
  7. package/dist/error.js +38 -0
  8. package/dist/error.js.map +1 -1
  9. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
  10. package/dist/extractSubgraphsFromSupergraph.js +59 -8
  11. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  12. package/dist/federation.d.ts +9 -2
  13. package/dist/federation.d.ts.map +1 -1
  14. package/dist/federation.js +42 -5
  15. package/dist/federation.js.map +1 -1
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/knownCoreFeatures.d.ts +3 -0
  21. package/dist/knownCoreFeatures.d.ts.map +1 -1
  22. package/dist/knownCoreFeatures.js +12 -1
  23. package/dist/knownCoreFeatures.js.map +1 -1
  24. package/dist/operations.d.ts +3 -1
  25. package/dist/operations.d.ts.map +1 -1
  26. package/dist/operations.js +26 -5
  27. package/dist/operations.js.map +1 -1
  28. package/dist/schemaUpgrader.d.ts.map +1 -1
  29. package/dist/schemaUpgrader.js +50 -31
  30. package/dist/schemaUpgrader.js.map +1 -1
  31. package/dist/specs/coreSpec.d.ts +2 -0
  32. package/dist/specs/coreSpec.d.ts.map +1 -1
  33. package/dist/specs/coreSpec.js +21 -0
  34. package/dist/specs/coreSpec.js.map +1 -1
  35. package/dist/specs/costSpec.d.ts +17 -0
  36. package/dist/specs/costSpec.d.ts.map +1 -0
  37. package/dist/specs/costSpec.js +49 -0
  38. package/dist/specs/costSpec.js.map +1 -0
  39. package/dist/specs/federationSpec.d.ts +6 -1
  40. package/dist/specs/federationSpec.d.ts.map +1 -1
  41. package/dist/specs/federationSpec.js +15 -1
  42. package/dist/specs/federationSpec.js.map +1 -1
  43. package/dist/specs/sourceSpec.d.ts +69 -0
  44. package/dist/specs/sourceSpec.d.ts.map +1 -0
  45. package/dist/specs/sourceSpec.js +345 -0
  46. package/dist/specs/sourceSpec.js.map +1 -0
  47. package/dist/supergraphs.d.ts +1 -1
  48. package/dist/supergraphs.d.ts.map +1 -1
  49. package/dist/supergraphs.js +1 -0
  50. package/dist/supergraphs.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/argumentCompositionStrategies.ts +37 -0
  53. package/src/error.ts +137 -4
  54. package/src/extractSubgraphsFromSupergraph.ts +94 -7
  55. package/src/federation.ts +89 -33
  56. package/src/index.ts +2 -1
  57. package/src/knownCoreFeatures.ts +15 -0
  58. package/src/operations.ts +41 -4
  59. package/src/schemaUpgrader.ts +55 -31
  60. package/src/specs/coreSpec.ts +26 -0
  61. package/src/specs/costSpec.ts +60 -0
  62. package/src/specs/federationSpec.ts +17 -1
  63. package/src/specs/sourceSpec.ts +607 -0
  64. package/src/supergraphs.ts +2 -1
  65. package/dist/specs/connectSpec.d.ts +0 -42
  66. package/dist/specs/connectSpec.d.ts.map +0 -1
  67. package/dist/specs/connectSpec.js +0 -83
  68. package/dist/specs/connectSpec.js.map +0 -1
  69. 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
- 'CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS',
596
- 'Argument on field is marked contextual in only some subgraphs',
597
- { addedIn: '2.7.0' },
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
- CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS,
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