@apollo/federation-internals 2.7.1 → 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.
@@ -536,25 +536,26 @@ function computeFragmentsToKeep(selectionSet, fragments, minUsagesToOptimize) {
536
536
  return toExpand.size === 0 ? fragments : fragments.filter((f) => !toExpand.has(f.name));
537
537
  }
538
538
  class Operation {
539
- constructor(schema, rootKind, selectionSet, variableDefinitions, fragments, name) {
539
+ constructor(schema, rootKind, selectionSet, variableDefinitions, fragments, name, directives) {
540
540
  this.schema = schema;
541
541
  this.rootKind = rootKind;
542
542
  this.selectionSet = selectionSet;
543
543
  this.variableDefinitions = variableDefinitions;
544
544
  this.fragments = fragments;
545
545
  this.name = name;
546
+ this.directives = directives;
546
547
  }
547
548
  withUpdatedSelectionSet(newSelectionSet) {
548
549
  if (this.selectionSet === newSelectionSet) {
549
550
  return this;
550
551
  }
551
- return new Operation(this.schema, this.rootKind, newSelectionSet, this.variableDefinitions, this.fragments, this.name);
552
+ return new Operation(this.schema, this.rootKind, newSelectionSet, this.variableDefinitions, this.fragments, this.name, this.directives);
552
553
  }
553
554
  withUpdatedSelectionSetAndFragments(newSelectionSet, newFragments) {
554
555
  if (this.selectionSet === newSelectionSet && newFragments === this.fragments) {
555
556
  return this;
556
557
  }
557
- return new Operation(this.schema, this.rootKind, newSelectionSet, this.variableDefinitions, newFragments, this.name);
558
+ return new Operation(this.schema, this.rootKind, newSelectionSet, this.variableDefinitions, newFragments, this.name, this.directives);
558
559
  }
559
560
  optimize(fragments, minUsagesToOptimize = 2) {
560
561
  (0, utils_1.assert)(minUsagesToOptimize >= 1, `Expected 'minUsagesToOptimize' to be at least 1, but got ${minUsagesToOptimize}`);
@@ -582,6 +583,10 @@ class Operation {
582
583
  }
583
584
  return this.withUpdatedSelectionSetAndFragments(optimizedSelection, finalFragments !== null && finalFragments !== void 0 ? finalFragments : undefined);
584
585
  }
586
+ generateQueryFragments() {
587
+ const [minimizedSelectionSet, fragments] = this.selectionSet.minimizeSelectionSet();
588
+ return new Operation(this.schema, this.rootKind, minimizedSelectionSet, this.variableDefinitions, fragments, this.name, this.directives);
589
+ }
585
590
  expandAllFragments() {
586
591
  const expanded = this.selectionSet.expandFragments();
587
592
  return this.withUpdatedSelectionSetAndFragments(expanded.normalize({ parentType: expanded.parentType }), undefined);
@@ -616,7 +621,7 @@ class Operation {
616
621
  return defaultedVariableValues;
617
622
  }
618
623
  toString(expandFragments = false, prettyPrint = true) {
619
- return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, expandFragments, prettyPrint);
624
+ return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, this.directives, expandFragments, prettyPrint);
620
625
  }
621
626
  }
622
627
  exports.Operation = Operation;
@@ -703,6 +708,10 @@ class NamedFragmentDefinition extends definitions_1.DirectiveTargetElement {
703
708
  computeExpandedSelectionSetAtType(type) {
704
709
  const expandedSelectionSet = this.expandedSelectionSet();
705
710
  const selectionSet = expandedSelectionSet.normalize({ parentType: type });
711
+ if (!(0, definitions_1.isObjectType)(this.typeCondition)) {
712
+ const validator = FieldsConflictValidator.build(expandedSelectionSet);
713
+ return { selectionSet, validator };
714
+ }
706
715
  const trimmed = expandedSelectionSet.minus(selectionSet);
707
716
  const validator = trimmed.isEmpty() ? undefined : FieldsConflictValidator.build(trimmed);
708
717
  return { selectionSet, validator };
@@ -815,17 +824,6 @@ class NamedFragments {
815
824
  return fragment.withUpdatedSelectionSet(reoptimizedSelectionSet);
816
825
  });
817
826
  }
818
- selectionSetIsWorthUsing(selectionSet) {
819
- const selections = selectionSet.selections();
820
- if (selections.length === 0) {
821
- return false;
822
- }
823
- if (selections.length === 1) {
824
- const s = selections[0];
825
- return !(s.kind === 'FieldSelection' && s.element.isLeafField());
826
- }
827
- return true;
828
- }
829
827
  rebaseOn(schema) {
830
828
  return this.mapInDependencyOrder((fragment, newFragments) => {
831
829
  const rebasedType = schema.type(fragment.selectionSet.parentType.name);
@@ -834,7 +832,7 @@ class NamedFragments {
834
832
  }
835
833
  let rebasedSelection = fragment.selectionSet.rebaseOn({ parentType: rebasedType, fragments: newFragments, errorIfCannotRebase: false });
836
834
  rebasedSelection = rebasedSelection.normalize({ parentType: rebasedType });
837
- return this.selectionSetIsWorthUsing(rebasedSelection)
835
+ return rebasedSelection.isWorthUsing()
838
836
  ? new NamedFragmentDefinition(schema, fragment.name, rebasedType).setSelectionSet(rebasedSelection)
839
837
  : undefined;
840
838
  });
@@ -923,6 +921,39 @@ class SelectionSet {
923
921
  this._keyedSelections = keyedSelections;
924
922
  this._selections = (0, utils_1.mapValues)(keyedSelections);
925
923
  }
924
+ minimizeSelectionSet(namedFragments = new NamedFragments(), seenSelections = new Map()) {
925
+ const minimizedSelectionSet = this.lazyMap((selection) => {
926
+ var _a;
927
+ if (selection.kind === 'FragmentSelection' && selection.element.typeCondition && selection.element.appliedDirectives.length === 0
928
+ && selection.selectionSet && selection.selectionSet.isWorthUsing()) {
929
+ const mockHashCode = `on${selection.element.typeCondition}` + selection.selectionSet.selections().length;
930
+ const equivalentSelectionSetCandidates = seenSelections.get(mockHashCode);
931
+ if (equivalentSelectionSetCandidates) {
932
+ const match = equivalentSelectionSetCandidates.find(([candidateSet]) => candidateSet.equals(selection.selectionSet));
933
+ if (match) {
934
+ return new FragmentSpreadSelection(this.parentType, namedFragments, match[1], []);
935
+ }
936
+ }
937
+ const [minimizedSelectionSet] = selection.selectionSet.minimizeSelectionSet(namedFragments, seenSelections);
938
+ const fragmentDefinition = new NamedFragmentDefinition(this.parentType.schema(), `_generated_${mockHashCode}_${(_a = equivalentSelectionSetCandidates === null || equivalentSelectionSetCandidates === void 0 ? void 0 : equivalentSelectionSetCandidates.length) !== null && _a !== void 0 ? _a : 0}`, selection.element.typeCondition).setSelectionSet(minimizedSelectionSet);
939
+ if (!equivalentSelectionSetCandidates) {
940
+ seenSelections.set(mockHashCode, [[selection.selectionSet, fragmentDefinition]]);
941
+ namedFragments.add(fragmentDefinition);
942
+ }
943
+ else {
944
+ equivalentSelectionSetCandidates.push([selection.selectionSet, fragmentDefinition]);
945
+ }
946
+ return new FragmentSpreadSelection(this.parentType, namedFragments, fragmentDefinition, []);
947
+ }
948
+ else if (selection.kind === 'FieldSelection') {
949
+ if (selection.selectionSet) {
950
+ selection = selection.withUpdatedSelectionSet(selection.selectionSet.minimizeSelectionSet(namedFragments, seenSelections)[0]);
951
+ }
952
+ }
953
+ return selection;
954
+ });
955
+ return [minimizedSelectionSet, namedFragments];
956
+ }
926
957
  selectionsInReverseOrder() {
927
958
  const length = this._selections.length;
928
959
  const reversed = new Array(length);
@@ -1219,7 +1250,7 @@ class SelectionSet {
1219
1250
  }
1220
1251
  return false;
1221
1252
  }
1222
- toOperationString(rootKind, variableDefinitions, fragments, operationName, expandFragments = false, prettyPrint = true) {
1253
+ toOperationString(rootKind, variableDefinitions, fragments, operationName, directives, expandFragments = false, prettyPrint = true) {
1223
1254
  const indent = prettyPrint ? '' : undefined;
1224
1255
  const fragmentsDefinitions = !expandFragments && fragments && !fragments.isEmpty()
1225
1256
  ? fragments.toString(indent) + "\n\n"
@@ -1230,7 +1261,8 @@ class SelectionSet {
1230
1261
  const nameAndVariables = operationName
1231
1262
  ? " " + (operationName + (variableDefinitions.isEmpty() ? "" : variableDefinitions.toString()))
1232
1263
  : (variableDefinitions.isEmpty() ? "" : " " + variableDefinitions.toString());
1233
- return fragmentsDefinitions + rootKind + nameAndVariables + " " + this.toString(expandFragments, true, indent);
1264
+ const directives_str = (0, definitions_1.directivesToString)(directives);
1265
+ return fragmentsDefinitions + rootKind + nameAndVariables + directives_str + " " + this.toString(expandFragments, true, indent);
1234
1266
  }
1235
1267
  toString(expandFragments = true, includeExternalBrackets = true, indent) {
1236
1268
  if (this.isEmpty()) {
@@ -1248,6 +1280,17 @@ class SelectionSet {
1248
1280
  : selectionsToString;
1249
1281
  }
1250
1282
  }
1283
+ isWorthUsing() {
1284
+ const selections = this.selections();
1285
+ if (selections.length === 0) {
1286
+ return false;
1287
+ }
1288
+ if (selections.length === 1) {
1289
+ const s = selections[0];
1290
+ return !(s.kind === 'FieldSelection' && s.element.isLeafField());
1291
+ }
1292
+ return true;
1293
+ }
1251
1294
  }
1252
1295
  exports.SelectionSet = SelectionSet;
1253
1296
  class SelectionSetUpdates {
@@ -2163,7 +2206,7 @@ class FragmentSpreadSelection extends FragmentSelection {
2163
2206
  }
2164
2207
  key() {
2165
2208
  if (!this.computedKey) {
2166
- this.computedKey = '...' + this.namedFragment.name + (this.spreadDirectives.length === 0 ? '' : ' ' + this.spreadDirectives.join(' '));
2209
+ this.computedKey = '...' + this.namedFragment.name + (0, definitions_1.directivesToString)(this.spreadDirectives);
2167
2210
  }
2168
2211
  return this.computedKey;
2169
2212
  }
@@ -2179,18 +2222,7 @@ class FragmentSpreadSelection extends FragmentSelection {
2179
2222
  validate((0, definitions_1.runtimeTypesIntersects)(this.parentType, this.namedFragment.typeCondition), () => `Fragment "${this.namedFragment.name}" cannot be spread inside type ${this.parentType} as the runtime types do not intersect ${this.namedFragment.typeCondition}`);
2180
2223
  }
2181
2224
  toSelectionNode() {
2182
- const directiveNodes = this.spreadDirectives.length === 0
2183
- ? undefined
2184
- : this.spreadDirectives.map(directive => {
2185
- return {
2186
- kind: graphql_1.Kind.DIRECTIVE,
2187
- name: {
2188
- kind: graphql_1.Kind.NAME,
2189
- value: directive.name,
2190
- },
2191
- arguments: directive.argumentsToAST()
2192
- };
2193
- });
2225
+ const directiveNodes = (0, definitions_1.directivesToDirectiveNodes)(this.spreadDirectives);
2194
2226
  return {
2195
2227
  kind: graphql_1.Kind.FRAGMENT_SPREAD,
2196
2228
  name: { kind: graphql_1.Kind.NAME, value: this.namedFragment.name },
@@ -2266,9 +2298,7 @@ class FragmentSpreadSelection extends FragmentSelection {
2266
2298
  return (indent !== null && indent !== void 0 ? indent : '') + this.element + ' ' + this.selectionSet.toString(true, true, indent);
2267
2299
  }
2268
2300
  else {
2269
- const directives = this.spreadDirectives;
2270
- const directiveString = directives.length == 0 ? '' : ' ' + directives.join(' ');
2271
- return (indent !== null && indent !== void 0 ? indent : '') + '...' + this.namedFragment.name + directiveString;
2301
+ return (indent !== null && indent !== void 0 ? indent : '') + '...' + this.namedFragment.name + (0, definitions_1.directivesToString)(this.spreadDirectives);
2272
2302
  }
2273
2303
  }
2274
2304
  }
@@ -2321,6 +2351,7 @@ function selectionOfNode(parentType, node, variableDefinitions, fragments, field
2321
2351
  }
2322
2352
  function operationFromDocument(schema, document, options) {
2323
2353
  let operation;
2354
+ let operation_directives;
2324
2355
  const operationName = options === null || options === void 0 ? void 0 : options.operationName;
2325
2356
  const fragments = new NamedFragments();
2326
2357
  document.definitions.forEach(definition => {
@@ -2329,6 +2360,7 @@ function operationFromDocument(schema, document, options) {
2329
2360
  validate(!operation || operationName, () => 'Must provide operation name if query contains multiple operations.');
2330
2361
  if (!operationName || (definition.name && definition.name.value === operationName)) {
2331
2362
  operation = definition;
2363
+ operation_directives = directivesOfNodes(schema, definition.directives);
2332
2364
  }
2333
2365
  break;
2334
2366
  case graphql_1.Kind.FRAGMENT_DEFINITION:
@@ -2358,10 +2390,10 @@ function operationFromDocument(schema, document, options) {
2358
2390
  }
2359
2391
  });
2360
2392
  fragments.validate(variableDefinitions);
2361
- return operationFromAST({ schema, operation, variableDefinitions, fragments, validateInput: options === null || options === void 0 ? void 0 : options.validate });
2393
+ return operationFromAST({ schema, operation, operation_directives, variableDefinitions, fragments, validateInput: options === null || options === void 0 ? void 0 : options.validate });
2362
2394
  }
2363
2395
  exports.operationFromDocument = operationFromDocument;
2364
- function operationFromAST({ schema, operation, variableDefinitions, fragments, validateInput, }) {
2396
+ function operationFromAST({ schema, operation, operation_directives, variableDefinitions, fragments, validateInput, }) {
2365
2397
  var _a;
2366
2398
  const rootType = schema.schemaDefinition.root(operation.operation);
2367
2399
  validate(rootType, () => `The schema has no "${operation.operation}" root type defined`);
@@ -2372,7 +2404,7 @@ function operationFromAST({ schema, operation, variableDefinitions, fragments, v
2372
2404
  variableDefinitions,
2373
2405
  fragments: fragmentsIfAny,
2374
2406
  validate: validateInput,
2375
- }), variableDefinitions, fragmentsIfAny, (_a = operation.name) === null || _a === void 0 ? void 0 : _a.value);
2407
+ }), variableDefinitions, fragmentsIfAny, (_a = operation.name) === null || _a === void 0 ? void 0 : _a.value, operation_directives);
2376
2408
  }
2377
2409
  function parseOperation(schema, operation, options) {
2378
2410
  return operationFromDocument(schema, (0, graphql_1.parse)(operation), options);
@@ -2403,6 +2435,7 @@ function operationToDocument(operation) {
2403
2435
  name: operation.name ? { kind: graphql_1.Kind.NAME, value: operation.name } : undefined,
2404
2436
  selectionSet: operation.selectionSet.toSelectionSetNode(),
2405
2437
  variableDefinitions: operation.variableDefinitions.toVariableDefinitionNodes(),
2438
+ directives: (0, definitions_1.directivesToDirectiveNodes)(operation.directives),
2406
2439
  };
2407
2440
  const fragmentASTs = operation.fragments
2408
2441
  ? (_a = operation.fragments) === null || _a === void 0 ? void 0 : _a.toFragmentDefinitionNodes()