@theguild/federation-composition 0.9.0 → 0.10.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 (126) hide show
  1. package/README.md +2 -1
  2. package/cjs/specifications/link.js +40 -5
  3. package/cjs/subgraph/helpers.js +2 -2
  4. package/cjs/subgraph/state.js +8 -0
  5. package/cjs/subgraph/validation/rules/elements/provides.js +8 -6
  6. package/cjs/subgraph/validation/rules/elements/requires.js +9 -7
  7. package/cjs/subgraph/validation/validate-state.js +9 -3
  8. package/cjs/subgraph/validation/validate-subgraph.js +4 -2
  9. package/cjs/subgraph/validation/validation-context.js +10 -0
  10. package/cjs/supergraph/composition/directive.js +3 -0
  11. package/cjs/supergraph/composition/enum-type.js +3 -0
  12. package/cjs/supergraph/composition/input-object-type.js +3 -0
  13. package/cjs/supergraph/composition/interface-type.js +4 -0
  14. package/cjs/supergraph/composition/object-type.js +18 -20
  15. package/cjs/supergraph/composition/scalar-type.js +2 -0
  16. package/cjs/supergraph/composition/union-type.js +2 -0
  17. package/cjs/supergraph/state.js +24 -26
  18. package/cjs/supergraph/validation/rules/fields-of-the-same-type-rule.js +35 -0
  19. package/cjs/supergraph/validation/rules/invalid-field-sharing-rule.js +4 -1
  20. package/cjs/supergraph/validation/rules/satisfiablity/constants.js +4 -0
  21. package/cjs/supergraph/validation/rules/satisfiablity/edge.js +64 -0
  22. package/cjs/supergraph/validation/rules/satisfiablity/errors.js +44 -0
  23. package/cjs/supergraph/validation/rules/satisfiablity/fields.js +147 -0
  24. package/cjs/supergraph/validation/rules/satisfiablity/finder.js +267 -0
  25. package/cjs/supergraph/validation/rules/satisfiablity/graph.js +675 -0
  26. package/cjs/supergraph/validation/rules/satisfiablity/helpers.js +41 -0
  27. package/cjs/supergraph/validation/rules/satisfiablity/move-validator.js +337 -0
  28. package/cjs/supergraph/validation/rules/satisfiablity/moves.js +52 -0
  29. package/cjs/supergraph/validation/rules/satisfiablity/node.js +89 -0
  30. package/cjs/supergraph/validation/rules/satisfiablity/operation-path.js +70 -0
  31. package/cjs/supergraph/validation/rules/satisfiablity/supergraph.js +37 -0
  32. package/cjs/supergraph/validation/rules/satisfiablity/walker.js +306 -0
  33. package/cjs/supergraph/validation/rules/satisfiablity-rule.js +45 -1081
  34. package/cjs/supergraph/validation/validate-supergraph.js +1 -1
  35. package/cjs/utils/logger.js +127 -0
  36. package/esm/specifications/link.js +40 -5
  37. package/esm/subgraph/helpers.js +2 -2
  38. package/esm/subgraph/state.js +8 -0
  39. package/esm/subgraph/validation/rules/elements/provides.js +8 -6
  40. package/esm/subgraph/validation/rules/elements/requires.js +9 -7
  41. package/esm/subgraph/validation/validate-state.js +9 -3
  42. package/esm/subgraph/validation/validate-subgraph.js +4 -2
  43. package/esm/subgraph/validation/validation-context.js +11 -1
  44. package/esm/supergraph/composition/directive.js +3 -0
  45. package/esm/supergraph/composition/enum-type.js +3 -0
  46. package/esm/supergraph/composition/input-object-type.js +3 -0
  47. package/esm/supergraph/composition/interface-type.js +4 -0
  48. package/esm/supergraph/composition/object-type.js +18 -20
  49. package/esm/supergraph/composition/scalar-type.js +2 -0
  50. package/esm/supergraph/composition/union-type.js +2 -0
  51. package/esm/supergraph/state.js +24 -26
  52. package/esm/supergraph/validation/rules/fields-of-the-same-type-rule.js +35 -0
  53. package/esm/supergraph/validation/rules/invalid-field-sharing-rule.js +4 -1
  54. package/esm/supergraph/validation/rules/satisfiablity/constants.js +1 -0
  55. package/esm/supergraph/validation/rules/satisfiablity/edge.js +54 -0
  56. package/esm/supergraph/validation/rules/satisfiablity/errors.js +40 -0
  57. package/esm/supergraph/validation/rules/satisfiablity/fields.js +142 -0
  58. package/esm/supergraph/validation/rules/satisfiablity/finder.js +261 -0
  59. package/esm/supergraph/validation/rules/satisfiablity/graph.js +671 -0
  60. package/esm/supergraph/validation/rules/satisfiablity/helpers.js +35 -0
  61. package/esm/supergraph/validation/rules/satisfiablity/move-validator.js +333 -0
  62. package/esm/supergraph/validation/rules/satisfiablity/moves.js +46 -0
  63. package/esm/supergraph/validation/rules/satisfiablity/node.js +85 -0
  64. package/esm/supergraph/validation/rules/satisfiablity/operation-path.js +66 -0
  65. package/esm/supergraph/validation/rules/satisfiablity/supergraph.js +33 -0
  66. package/esm/supergraph/validation/rules/satisfiablity/walker.js +301 -0
  67. package/esm/supergraph/validation/rules/satisfiablity-rule.js +40 -1076
  68. package/esm/supergraph/validation/validate-supergraph.js +1 -1
  69. package/esm/utils/logger.js +119 -0
  70. package/package.json +2 -1
  71. package/typings/subgraph/state.d.cts +2 -0
  72. package/typings/subgraph/state.d.ts +2 -0
  73. package/typings/subgraph/validation/validate-state.d.cts +2 -1
  74. package/typings/subgraph/validation/validate-state.d.ts +2 -1
  75. package/typings/subgraph/validation/validation-context.d.cts +3 -0
  76. package/typings/subgraph/validation/validation-context.d.ts +3 -0
  77. package/typings/supergraph/composition/common.d.cts +2 -1
  78. package/typings/supergraph/composition/common.d.ts +2 -1
  79. package/typings/supergraph/composition/directive.d.cts +4 -0
  80. package/typings/supergraph/composition/directive.d.ts +4 -0
  81. package/typings/supergraph/composition/enum-type.d.cts +4 -0
  82. package/typings/supergraph/composition/enum-type.d.ts +4 -0
  83. package/typings/supergraph/composition/input-object-type.d.cts +4 -0
  84. package/typings/supergraph/composition/input-object-type.d.ts +4 -0
  85. package/typings/supergraph/composition/interface-type.d.cts +5 -0
  86. package/typings/supergraph/composition/interface-type.d.ts +5 -0
  87. package/typings/supergraph/composition/object-type.d.cts +5 -0
  88. package/typings/supergraph/composition/object-type.d.ts +5 -0
  89. package/typings/supergraph/composition/scalar-type.d.cts +3 -0
  90. package/typings/supergraph/composition/scalar-type.d.ts +3 -0
  91. package/typings/supergraph/composition/union-type.d.cts +3 -0
  92. package/typings/supergraph/composition/union-type.d.ts +3 -0
  93. package/typings/supergraph/state.d.cts +4 -4
  94. package/typings/supergraph/state.d.ts +4 -4
  95. package/typings/supergraph/validation/rules/satisfiablity/constants.d.cts +2 -0
  96. package/typings/supergraph/validation/rules/satisfiablity/constants.d.ts +2 -0
  97. package/typings/supergraph/validation/rules/satisfiablity/edge.d.cts +31 -0
  98. package/typings/supergraph/validation/rules/satisfiablity/edge.d.ts +31 -0
  99. package/typings/supergraph/validation/rules/satisfiablity/errors.d.cts +17 -0
  100. package/typings/supergraph/validation/rules/satisfiablity/errors.d.ts +17 -0
  101. package/typings/supergraph/validation/rules/satisfiablity/fields.d.cts +33 -0
  102. package/typings/supergraph/validation/rules/satisfiablity/fields.d.ts +33 -0
  103. package/typings/supergraph/validation/rules/satisfiablity/finder.d.cts +28 -0
  104. package/typings/supergraph/validation/rules/satisfiablity/finder.d.ts +28 -0
  105. package/typings/supergraph/validation/rules/satisfiablity/graph.d.cts +63 -0
  106. package/typings/supergraph/validation/rules/satisfiablity/graph.d.ts +63 -0
  107. package/typings/supergraph/validation/rules/satisfiablity/helpers.d.cts +7 -0
  108. package/typings/supergraph/validation/rules/satisfiablity/helpers.d.ts +7 -0
  109. package/typings/supergraph/validation/rules/satisfiablity/move-validator.d.cts +25 -0
  110. package/typings/supergraph/validation/rules/satisfiablity/move-validator.d.ts +25 -0
  111. package/typings/supergraph/validation/rules/satisfiablity/moves.d.cts +24 -0
  112. package/typings/supergraph/validation/rules/satisfiablity/moves.d.ts +24 -0
  113. package/typings/supergraph/validation/rules/satisfiablity/node.d.cts +31 -0
  114. package/typings/supergraph/validation/rules/satisfiablity/node.d.ts +31 -0
  115. package/typings/supergraph/validation/rules/satisfiablity/operation-path.d.cts +29 -0
  116. package/typings/supergraph/validation/rules/satisfiablity/operation-path.d.ts +29 -0
  117. package/typings/supergraph/validation/rules/satisfiablity/supergraph.d.cts +14 -0
  118. package/typings/supergraph/validation/rules/satisfiablity/supergraph.d.ts +14 -0
  119. package/typings/supergraph/validation/rules/satisfiablity/walker.d.cts +35 -0
  120. package/typings/supergraph/validation/rules/satisfiablity/walker.d.ts +35 -0
  121. package/typings/utils/logger.d.cts +33 -0
  122. package/typings/utils/logger.d.ts +33 -0
  123. package/cjs/utils/dependency-graph.js +0 -227
  124. package/esm/utils/dependency-graph.js +0 -222
  125. package/typings/utils/dependency-graph.d.cts +0 -31
  126. package/typings/utils/dependency-graph.d.ts +0 -31
package/README.md CHANGED
@@ -12,7 +12,8 @@ Supports all Federation versions. Drop-in replacement for `@apollo/composition`.
12
12
  - produces Supergraph SDL (can be used with Apollo Router and every tool that supports Supergraph
13
13
  SDL)
14
14
  - does not support Hints
15
- - a lot faster! 5x faster when composing and validating simple schemas, but 28x faster at big scale.
15
+ - 5x faster when composing and validating small to medium schemas (a bit slower for huge schemas)
16
+ - 2x less memory usage
16
17
 
17
18
  ## Installation
18
19
 
@@ -34,10 +34,41 @@ function printLink(link) {
34
34
  },
35
35
  value: {
36
36
  kind: graphql_1.Kind.LIST,
37
- values: link.imports.map(im => ({
38
- kind: graphql_1.Kind.STRING,
39
- value: im.name,
40
- })),
37
+ values: link.imports.map(im => {
38
+ if (!im.alias) {
39
+ return {
40
+ kind: graphql_1.Kind.STRING,
41
+ value: im.name,
42
+ };
43
+ }
44
+ return {
45
+ kind: graphql_1.Kind.OBJECT,
46
+ fields: [
47
+ {
48
+ kind: graphql_1.Kind.OBJECT_FIELD,
49
+ name: {
50
+ kind: graphql_1.Kind.NAME,
51
+ value: 'name',
52
+ },
53
+ value: {
54
+ kind: graphql_1.Kind.STRING,
55
+ value: im.name,
56
+ },
57
+ },
58
+ {
59
+ kind: graphql_1.Kind.OBJECT_FIELD,
60
+ name: {
61
+ kind: graphql_1.Kind.NAME,
62
+ value: 'as',
63
+ },
64
+ value: {
65
+ kind: graphql_1.Kind.STRING,
66
+ value: im.alias,
67
+ },
68
+ },
69
+ ],
70
+ };
71
+ }),
41
72
  },
42
73
  },
43
74
  ],
@@ -162,7 +193,11 @@ function mergeLinks(links) {
162
193
  return Array.from(groupByIdentity.entries()).map(([identity, link]) => ({
163
194
  identity,
164
195
  version: link.highestVersion,
165
- imports: Array.from(link.imports).map(link => ({ kind: link.kind, name: link.name })),
196
+ imports: Array.from(link.imports).map(link => ({
197
+ kind: link.kind,
198
+ name: link.name,
199
+ alias: link.alias,
200
+ })),
166
201
  name: link.name,
167
202
  }));
168
203
  }
@@ -37,10 +37,10 @@ function validateDirectiveAgainstOriginal(providedDirectiveNode, directiveName,
37
37
  if (expectedType !== providedType) {
38
38
  const isNonNullableString = providedType === 'String!';
39
39
  const allowedFieldSetTypes = isFederationV2
40
- ? ['FieldSet!', 'federation__FieldSet!', '_FieldSet!']
40
+ ? ['FieldSet!', 'federation__FieldSet!', '_FieldSet!', '[String!]!']
41
41
  : ['_FieldSet!', 'String', 'String!'];
42
42
  const fieldSetTypesInSpec = isFederationV2
43
- ? ['FieldSet!', 'federation__FieldSet!', '_FieldSet!']
43
+ ? ['FieldSet!', 'federation__FieldSet!', '_FieldSet!', '[String!]!']
44
44
  : ['_FieldSet!', 'FieldSet!', 'String'];
45
45
  const expectsFieldSet = fieldSetTypesInSpec.includes(expectedType);
46
46
  if (!isNonNullableString && expectsFieldSet) {
@@ -104,6 +104,9 @@ function createSubgraphStateBuilder(graph, typeDefs, version, links) {
104
104
  throw new Error(`Expected to find an object type`);
105
105
  }
106
106
  objectTypeBuilder.field.setType(typeDef.name.value, node.name.value, (0, helpers_js_1.printOutputType)(node.type));
107
+ if (typeDef.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
108
+ objectTypeBuilder.field.setExtension(typeDef.name.value, node.name.value);
109
+ }
107
110
  if (version === 'v1.0' &&
108
111
  (typeDef.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION ||
109
112
  typeDef.name.value === expectedQueryTypeName ||
@@ -596,6 +599,9 @@ function objectTypeFactory(state, renameObject) {
596
599
  setType(typeName, fieldName, fieldType) {
597
600
  getOrCreateObjectField(state, renameObject, typeName, fieldName).type = fieldType;
598
601
  },
602
+ setExtension(typeName, fieldName) {
603
+ getOrCreateObjectField(state, renameObject, typeName, fieldName).extension = true;
604
+ },
599
605
  setDirective(typeName, fieldName, directive) {
600
606
  getOrCreateObjectField(state, renameObject, typeName, fieldName).ast.directives.push(directive);
601
607
  },
@@ -1108,6 +1114,7 @@ function getOrCreateObjectField(state, renameObject, typeName, fieldName) {
1108
1114
  external: false,
1109
1115
  inaccessible: false,
1110
1116
  authenticated: false,
1117
+ extension: false,
1111
1118
  policies: [],
1112
1119
  scopes: [],
1113
1120
  used: false,
@@ -1147,6 +1154,7 @@ function getOrCreateInterfaceField(state, typeName, fieldName) {
1147
1154
  required: false,
1148
1155
  provided: false,
1149
1156
  shareable: false,
1157
+ extension: false,
1150
1158
  tags: new Set(),
1151
1159
  args: new Map(),
1152
1160
  ast: {
@@ -106,12 +106,14 @@ function ProvidesRules(context) {
106
106
  context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @provides(fields: ${printedFieldsValue}): field ${info.typeDefinition.name.value}.${info.fieldName} cannot be included because it has arguments (fields with argument are not allowed in @provides)`, { nodes: directiveNode, extensions: { code: 'PROVIDES_FIELDS_HAS_ARGS' } }));
107
107
  },
108
108
  interceptNonExternalField(info) {
109
- isValid = false;
110
- context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @provides(fields: ${printedFieldsValue}): field "${info.typeDefinition.name.value}.${info.fieldName}" should not be part of a @provides since it is already provided by this subgraph (it is not marked @external)`, {
111
- extensions: {
112
- code: 'PROVIDES_FIELDS_MISSING_EXTERNAL',
113
- },
114
- }));
109
+ if (context.satisfiesVersionRange('> v1.0')) {
110
+ isValid = false;
111
+ context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @provides(fields: ${printedFieldsValue}): field "${info.typeDefinition.name.value}.${info.fieldName}" should not be part of a @provides since it is already provided by this subgraph (it is not marked @external)`, {
112
+ extensions: {
113
+ code: 'PROVIDES_FIELDS_MISSING_EXTERNAL',
114
+ },
115
+ }));
116
+ }
115
117
  },
116
118
  interceptExternalField(info) {
117
119
  const keyDirectives = info.typeDefinition.directives?.filter(directive => context.isAvailableFederationDirective('key', directive));
@@ -33,7 +33,7 @@ function RequiresRules(context) {
33
33
  return;
34
34
  }
35
35
  const printedFieldsValue = (0, printer_js_1.print)(fieldsArg.value);
36
- if (fieldsArg.value.kind !== graphql_1.Kind.STRING) {
36
+ if (fieldsArg.value.kind !== graphql_1.Kind.STRING && fieldsArg.value.kind !== graphql_1.Kind.ENUM) {
37
37
  context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @requires(fields: ${printedFieldsValue}): Invalid value for argument "fields": must be a string.`, {
38
38
  nodes: directiveNode,
39
39
  extensions: {
@@ -106,12 +106,14 @@ function RequiresRules(context) {
106
106
  }
107
107
  },
108
108
  interceptNonExternalField(info) {
109
- isValid = false;
110
- context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @requires(fields: ${printedFieldsValue}): field "${info.typeDefinition.name.value}.${info.fieldName}" should not be part of a @requires since it is already provided by this subgraph (it is not marked @external)`, {
111
- extensions: {
112
- code: 'REQUIRES_FIELDS_MISSING_EXTERNAL',
113
- },
114
- }));
109
+ if (context.satisfiesVersionRange('> v1.0')) {
110
+ isValid = false;
111
+ context.reportError(new graphql_1.GraphQLError(`On field "${fieldCoordinate}", for @requires(fields: ${printedFieldsValue}): field "${info.typeDefinition.name.value}.${info.fieldName}" should not be part of a @requires since it is already provided by this subgraph (it is not marked @external)`, {
112
+ extensions: {
113
+ code: 'REQUIRES_FIELDS_MISSING_EXTERNAL',
114
+ },
115
+ }));
116
+ }
115
117
  },
116
118
  });
117
119
  if (isValid) {
@@ -6,7 +6,7 @@ const format_js_1 = require("../../utils/format.js");
6
6
  const state_js_1 = require("../../utils/state.js");
7
7
  const state_js_2 = require("../state.js");
8
8
  const specifiedScalars = new Set(graphql_1.specifiedScalarTypes.map(t => t.name));
9
- function validateSubgraphState(state) {
9
+ function validateSubgraphState(state, context) {
10
10
  const errors = [];
11
11
  function reportError(message) {
12
12
  errors.push(new graphql_1.GraphQLError(message, {
@@ -16,7 +16,7 @@ function validateSubgraphState(state) {
16
16
  }));
17
17
  }
18
18
  validateRootTypes(state, reportError);
19
- validateDirectives(state, reportError);
19
+ validateDirectives(state, reportError, context);
20
20
  validateTypes(state, reportError);
21
21
  return errors;
22
22
  }
@@ -58,13 +58,19 @@ function validateRootTypes(state, reportError) {
58
58
  function capitalize(str) {
59
59
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
60
60
  }
61
- function validateDirectives(state, reportError) {
61
+ function validateDirectives(state, reportError, context) {
62
62
  for (const directive of state.types.values()) {
63
63
  if (isDirective(directive)) {
64
+ if (context.isLinkSpecDirective(directive.name)) {
65
+ continue;
66
+ }
64
67
  validateName(reportError, directive.name);
65
68
  for (const [argName, arg] of directive.args) {
66
69
  validateName(reportError, argName);
67
70
  const argInputTypeName = (0, state_js_1.stripTypeModifiers)(arg.type);
71
+ if (context.isLinkSpecType(argInputTypeName)) {
72
+ continue;
73
+ }
68
74
  if (!isInputType(state, argInputTypeName)) {
69
75
  reportError(`The type of @${directive.name}(${arg.name}:) must be Input Type ` +
70
76
  `but got: ${arg.type}.`);
@@ -162,7 +162,7 @@ function validateSubgraph(subgraph, stateBuilder, federation, __internal) {
162
162
  : null,
163
163
  subgraph.typeDefs,
164
164
  ].filter(onlyDocumentNode));
165
- const subgraphStateErrors = (0, validate_state_js_1.validateSubgraphState)(stateBuilder.state);
165
+ const subgraphStateErrors = (0, validate_state_js_1.validateSubgraphState)(stateBuilder.state, validationContext);
166
166
  const simpleValidationContext = (0, validation_context_js_1.createSimpleValidationContext)(fullTypeDefs, typeNodeInfo);
167
167
  (0, graphql_1.visit)(fullTypeDefs, (0, graphql_1.visitInParallel)(graphqlRules.map(rule => {
168
168
  if (rulesToSkip.includes(rule.name)) {
@@ -322,7 +322,9 @@ function cleanSubgraphTypeDefsFromSubgraphSpec(typeDefs) {
322
322
  const queryTypeName = schemaDef?.operationTypes?.find(op => op.operation === graphql_1.OperationTypeNode.QUERY)?.type.name
323
323
  .value ?? 'Query';
324
324
  typeDefs.definitions = typeDefs.definitions.filter(def => {
325
- if (def.kind === graphql_1.Kind.SCALAR_TYPE_DEFINITION && def.name.value === '_Any') {
325
+ if ((def.kind === graphql_1.Kind.SCALAR_TYPE_DEFINITION ||
326
+ def.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION) &&
327
+ def.name.value === '_Any') {
326
328
  return false;
327
329
  }
328
330
  if (def.kind === graphql_1.Kind.UNION_TYPE_DEFINITION && def.name.value === '_Entity') {
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSubgraphValidationContext = exports.createSimpleValidationContext = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const federation_js_1 = require("../../specifications/federation.js");
6
+ const link_js_1 = require("../../specifications/link.js");
6
7
  const state_js_1 = require("../../utils/state.js");
7
8
  const state_js_2 = require("../state.js");
9
+ const linkSpec = (0, graphql_1.parse)(link_js_1.sdl);
10
+ const linkSpecDirectives = linkSpec.definitions.filter((def) => def.kind === graphql_1.Kind.DIRECTIVE_DEFINITION);
11
+ const linkSpecTypes = linkSpec.definitions.filter(graphql_1.isTypeDefinitionNode);
8
12
  function createSimpleValidationContext(typeDefs, typeNodeInfo) {
9
13
  let reportedErrors = [];
10
14
  const directiveDefinitionMap = new Map();
@@ -155,6 +159,12 @@ function createSubgraphValidationContext(subgraph, federation, typeNodeInfo, sta
155
159
  }
156
160
  return {
157
161
  stateBuilder,
162
+ isLinkSpecDirective(name) {
163
+ return linkSpecDirectives.some(d => d.name.value === name);
164
+ },
165
+ isLinkSpecType(name) {
166
+ return linkSpecTypes.some(t => t.name.value === name);
167
+ },
158
168
  isAvailableFederationType(name) {
159
169
  const alternativeNames = typeAlternativeNamesMap.get(name);
160
170
  if (alternativeNames) {
@@ -31,11 +31,13 @@ function directiveBuilder() {
31
31
  argState.byGraph.set(graph.id, {
32
32
  type: arg.type,
33
33
  defaultValue: arg.defaultValue,
34
+ version: graph.version,
34
35
  });
35
36
  }
36
37
  directiveState.byGraph.set(graph.id, {
37
38
  locations: directive.locations,
38
39
  repeatable: directive.repeatable,
40
+ version: graph.version,
39
41
  });
40
42
  },
41
43
  composeSupergraphNode(directive) {
@@ -64,6 +66,7 @@ function getOrCreateDirective(state, directiveName) {
64
66
  return existing;
65
67
  }
66
68
  const def = {
69
+ kind: 'directive',
67
70
  name: directiveName,
68
71
  locations: new Set(),
69
72
  byGraph: new Map(),
@@ -39,6 +39,7 @@ function enumTypeBuilder() {
39
39
  }
40
40
  enumTypeState.byGraph.set(graph.id, {
41
41
  inaccessible: type.inaccessible,
42
+ version: graph.version,
42
43
  });
43
44
  for (const value of type.values.values()) {
44
45
  const valueState = getOrCreateEnumValue(enumTypeState, value.name);
@@ -54,6 +55,7 @@ function enumTypeBuilder() {
54
55
  }
55
56
  valueState.byGraph.set(graph.id, {
56
57
  inaccessible: value.inaccessible,
58
+ version: graph.version,
57
59
  });
58
60
  }
59
61
  },
@@ -114,6 +116,7 @@ function getOrCreateEnumType(state, typeName) {
114
116
  return existing;
115
117
  }
116
118
  const def = {
119
+ kind: 'enum',
117
120
  name: typeName,
118
121
  values: new Map(),
119
122
  tags: new Set(),
@@ -19,6 +19,7 @@ function inputObjectTypeBuilder() {
19
19
  }
20
20
  inputObjectTypeState.byGraph.set(graph.id, {
21
21
  inaccessible: type.inaccessible,
22
+ version: graph.version,
22
23
  });
23
24
  for (const field of type.fields.values()) {
24
25
  const fieldState = getOrCreateField(inputObjectTypeState, field.name, field.type);
@@ -42,6 +43,7 @@ function inputObjectTypeBuilder() {
42
43
  type: field.type,
43
44
  inaccessible: field.inaccessible,
44
45
  defaultValue: field.defaultValue,
46
+ version: graph.version,
45
47
  });
46
48
  }
47
49
  },
@@ -95,6 +97,7 @@ function getOrCreateInputObjectType(state, typeName) {
95
97
  return existing;
96
98
  }
97
99
  const def = {
100
+ kind: 'input',
98
101
  name: typeName,
99
102
  tags: new Set(),
100
103
  hasDefinition: false,
@@ -36,6 +36,7 @@ function interfaceTypeBuilder() {
36
36
  keys: type.keys,
37
37
  interfaces: type.interfaces,
38
38
  implementedBy: type.implementedBy,
39
+ version: graph.version,
39
40
  });
40
41
  for (const field of type.fields.values()) {
41
42
  const fieldState = getOrCreateInterfaceField(interfaceTypeState, field.name, field.type);
@@ -69,6 +70,7 @@ function interfaceTypeBuilder() {
69
70
  override: field.override,
70
71
  provides: field.provides,
71
72
  requires: field.requires,
73
+ version: graph.version,
72
74
  });
73
75
  for (const arg of field.args.values()) {
74
76
  const argState = getOrCreateArg(fieldState, arg.name, arg.type);
@@ -91,6 +93,7 @@ function interfaceTypeBuilder() {
91
93
  argState.byGraph.set(graph.id, {
92
94
  type: arg.type,
93
95
  defaultValue: arg.defaultValue,
96
+ version: graph.version,
94
97
  });
95
98
  }
96
99
  }
@@ -197,6 +200,7 @@ function getOrCreateInterfaceType(state, typeName) {
197
200
  return existing;
198
201
  }
199
202
  const def = {
203
+ kind: 'interface',
200
204
  name: typeName,
201
205
  tags: new Set(),
202
206
  inaccessible: false,
@@ -63,6 +63,7 @@ function objectTypeBuilder() {
63
63
  inaccessible: type.inaccessible,
64
64
  shareable: type.shareable,
65
65
  interfaces: type.interfaces,
66
+ version: graph.version,
66
67
  });
67
68
  const typeInGraph = objectTypeState.byGraph.get(graph.id);
68
69
  for (const field of type.fields.values()) {
@@ -120,8 +121,10 @@ function objectTypeBuilder() {
120
121
  provided: field.provided,
121
122
  required: field.required,
122
123
  shareable: field.shareable,
124
+ extension: field.extension,
123
125
  used: field.used,
124
126
  usedAsKey,
127
+ version: graph.version,
125
128
  });
126
129
  for (const arg of field.args.values()) {
127
130
  const argState = getOrCreateArg(fieldState, arg.name, arg.type);
@@ -148,6 +151,7 @@ function objectTypeBuilder() {
148
151
  type: arg.type,
149
152
  inaccessible: arg.inaccessible,
150
153
  defaultValue: arg.defaultValue,
154
+ version: graph.version,
151
155
  });
152
156
  }
153
157
  }
@@ -157,7 +161,7 @@ function objectTypeBuilder() {
157
161
  const joinTypes = isQuery
158
162
  ?
159
163
  Array.from(graphs.values()).map(graph => ({
160
- graph: graph.id,
164
+ graph: graph.graph.id,
161
165
  }))
162
166
  :
163
167
  Array.from(objectType.byGraph.entries())
@@ -220,12 +224,12 @@ function objectTypeBuilder() {
220
224
  }
221
225
  return true;
222
226
  }
223
- function createJoinFields(fieldInGraphs, field, { hasDifferentOutputType, overridesMap, }) {
227
+ function createJoinFields(fieldInGraphs, field, { hasDifferentOutputType, }) {
224
228
  return fieldInGraphs
225
229
  .map(([graphId, meta]) => {
226
230
  const type = hasDifferentOutputType ? meta.type : undefined;
227
231
  const override = meta.override ?? undefined;
228
- const usedOverridden = provideUsedOverriddenValue(field.name, meta, overridesMap, fieldNamesOfImplementedInterfaces, graphId);
232
+ const usedOverridden = provideUsedOverriddenValue(field, meta, fieldNamesOfImplementedInterfaces, graphId, graphNameToId);
229
233
  const external = shouldSetExternalOnJoinField(meta, graphId, field);
230
234
  const provides = meta.provides ?? undefined;
231
235
  const requires = meta.requires ?? undefined;
@@ -261,7 +265,6 @@ function objectTypeBuilder() {
261
265
  const hasDifferentOutputType = fieldInGraphs.some(([_, meta]) => meta.type !== field.type);
262
266
  const isDefinedEverywhere = field.byGraph.size === (isQuery ? graphs.size : objectType.byGraph.size);
263
267
  let joinFields = [];
264
- const overridesMap = {};
265
268
  const differencesBetweenGraphs = {
266
269
  override: false,
267
270
  type: false,
@@ -277,10 +280,6 @@ function objectTypeBuilder() {
277
280
  }
278
281
  if (meta.override !== null) {
279
282
  differencesBetweenGraphs.override = true;
280
- const originalGraphId = graphNameToId(meta.override);
281
- if (originalGraphId) {
282
- overridesMap[originalGraphId] = graphId;
283
- }
284
283
  }
285
284
  if (meta.provides !== null) {
286
285
  differencesBetweenGraphs.provides = true;
@@ -299,7 +298,7 @@ function objectTypeBuilder() {
299
298
  !fieldInGraph.usedAsKey &&
300
299
  !fieldInGraph.required &&
301
300
  !fieldInGraph.provided &&
302
- !provideUsedOverriddenValue(field.name, fieldInGraph, overridesMap, fieldNamesOfImplementedInterfaces, graphId) &&
301
+ !provideUsedOverriddenValue(field, fieldInGraph, fieldNamesOfImplementedInterfaces, graphId, graphNameToId) &&
303
302
  graphs.get(graphId).version === 'v1.0') {
304
303
  return null;
305
304
  }
@@ -315,7 +314,7 @@ function objectTypeBuilder() {
315
314
  joinFields = graphsWithOverride.map(([graphId, meta]) => ({
316
315
  graph: graphId,
317
316
  override: meta.override ?? undefined,
318
- usedOverridden: provideUsedOverriddenValue(field.name, meta, overridesMap, fieldNamesOfImplementedInterfaces, graphId),
317
+ usedOverridden: provideUsedOverriddenValue(field, meta, fieldNamesOfImplementedInterfaces, graphId, graphNameToId),
319
318
  type: differencesBetweenGraphs.type ? meta.type : undefined,
320
319
  external: meta.external ?? undefined,
321
320
  provides: meta.provides ?? undefined,
@@ -343,7 +342,7 @@ function objectTypeBuilder() {
343
342
  const graphsToEmit = fieldInGraphs.filter(([graphId, f]) => {
344
343
  const isExternal = f.external === true;
345
344
  const isOverridden = overriddenGraphs.includes(graphId);
346
- const needsToPrintUsedOverridden = provideUsedOverriddenValue(field.name, f, overridesMap, fieldNamesOfImplementedInterfaces, graphId);
345
+ const needsToPrintUsedOverridden = provideUsedOverriddenValue(field, f, fieldNamesOfImplementedInterfaces, graphId, graphNameToId);
347
346
  const isRequired = f.required === true;
348
347
  return (isExternal && isRequired) || needsToPrintUsedOverridden || !isOverridden;
349
348
  });
@@ -353,7 +352,7 @@ function objectTypeBuilder() {
353
352
  joinFields = graphsToEmit.map(([graphId, meta]) => ({
354
353
  graph: graphId,
355
354
  override: meta.override ?? undefined,
356
- usedOverridden: provideUsedOverriddenValue(field.name, meta, overridesMap, fieldNamesOfImplementedInterfaces, graphId),
355
+ usedOverridden: provideUsedOverriddenValue(field, meta, fieldNamesOfImplementedInterfaces, graphId, graphNameToId),
357
356
  type: differencesBetweenGraphs.type ? meta.type : undefined,
358
357
  external: meta.external ?? undefined,
359
358
  provides: meta.provides ?? undefined,
@@ -364,7 +363,6 @@ function objectTypeBuilder() {
364
363
  else if (hasDifferencesBetweenGraphs) {
365
364
  joinFields = createJoinFields(fieldInGraphs, field, {
366
365
  hasDifferentOutputType,
367
- overridesMap,
368
366
  });
369
367
  }
370
368
  }
@@ -376,11 +374,11 @@ function objectTypeBuilder() {
376
374
  const graphsToPrintJoinField = fieldInGraphs.filter(([graphId, meta]) => meta.override !== null ||
377
375
  meta.external === true ||
378
376
  (meta.shareable && !overriddenGraphs.includes(graphId)) ||
379
- provideUsedOverriddenValue(field.name, meta, overridesMap, fieldNamesOfImplementedInterfaces, graphId));
377
+ provideUsedOverriddenValue(field, meta, fieldNamesOfImplementedInterfaces, graphId, graphNameToId));
380
378
  joinFields = graphsToPrintJoinField.map(([graphId, meta]) => ({
381
379
  graph: graphId,
382
380
  override: meta.override ?? undefined,
383
- usedOverridden: provideUsedOverriddenValue(field.name, meta, overridesMap, fieldNamesOfImplementedInterfaces, graphId),
381
+ usedOverridden: provideUsedOverriddenValue(field, meta, fieldNamesOfImplementedInterfaces, graphId, graphNameToId),
384
382
  type: differencesBetweenGraphs.type ? meta.type : undefined,
385
383
  external: meta.external ?? undefined,
386
384
  provides: meta.provides ?? undefined,
@@ -390,7 +388,6 @@ function objectTypeBuilder() {
390
388
  else {
391
389
  joinFields = createJoinFields(fieldInGraphs, field, {
392
390
  hasDifferentOutputType,
393
- overridesMap,
394
391
  });
395
392
  }
396
393
  }
@@ -470,12 +467,12 @@ function objectTypeBuilder() {
470
467
  };
471
468
  }
472
469
  exports.objectTypeBuilder = objectTypeBuilder;
473
- function provideUsedOverriddenValue(fieldName, fieldStateInGraph, overridesMap, fieldNamesOfImplementedInterfaces, graphId) {
474
- const inGraphs = fieldNamesOfImplementedInterfaces[fieldName];
470
+ function provideUsedOverriddenValue(field, fieldStateInGraph, fieldNamesOfImplementedInterfaces, graphId, graphNameToId) {
471
+ const inGraphs = fieldNamesOfImplementedInterfaces[field.name];
475
472
  const hasMatchingInterfaceFieldInGraph = inGraphs && inGraphs.has(graphId);
476
473
  const isUsedAsNonExternalKey = fieldStateInGraph.usedAsKey && !fieldStateInGraph.external;
477
- const hasOverride = typeof overridesMap[graphId] === 'string';
478
- if (hasOverride && (isUsedAsNonExternalKey || hasMatchingInterfaceFieldInGraph)) {
474
+ const isOverridden = field.override && graphNameToId(field.override) === graphId;
475
+ if (isOverridden && (isUsedAsNonExternalKey || hasMatchingInterfaceFieldInGraph)) {
479
476
  return true;
480
477
  }
481
478
  return false;
@@ -486,6 +483,7 @@ function getOrCreateObjectType(state, typeName) {
486
483
  return existing;
487
484
  }
488
485
  const def = {
486
+ kind: 'object',
489
487
  name: typeName,
490
488
  tags: new Set(),
491
489
  hasDefinition: false,
@@ -31,6 +31,7 @@ function scalarTypeBuilder() {
31
31
  });
32
32
  scalarTypeState.byGraph.set(graph.id, {
33
33
  inaccessible: type.inaccessible,
34
+ version: graph.version,
34
35
  });
35
36
  },
36
37
  composeSupergraphNode(scalarType) {
@@ -62,6 +63,7 @@ function getOrCreateScalarType(state, typeName) {
62
63
  return existing;
63
64
  }
64
65
  const def = {
66
+ kind: 'scalar',
65
67
  name: typeName,
66
68
  tags: new Set(),
67
69
  inaccessible: false,
@@ -18,6 +18,7 @@ function unionTypeBuilder() {
18
18
  }
19
19
  unionTypeState.byGraph.set(graph.id, {
20
20
  members: type.members,
21
+ version: graph.version,
21
22
  });
22
23
  for (const member of type.members) {
23
24
  unionTypeState.members.add(member);
@@ -52,6 +53,7 @@ function getOrCreateUnionType(state, typeName) {
52
53
  return existing;
53
54
  }
54
55
  const def = {
56
+ kind: 'union',
55
57
  name: typeName,
56
58
  members: new Set(),
57
59
  tags: new Set(),