@wundergraph/composition 0.24.0 → 0.25.1

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 (37) hide show
  1. package/dist/errors/errors.d.ts +20 -1
  2. package/dist/errors/errors.js +153 -7
  3. package/dist/errors/errors.js.map +1 -1
  4. package/dist/federation/federation-factory.d.ts +11 -2
  5. package/dist/federation/federation-factory.js +295 -4
  6. package/dist/federation/federation-factory.js.map +1 -1
  7. package/dist/federation/utils.d.ts +7 -2
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/normalization/normalization-factory.d.ts +2 -1
  12. package/dist/normalization/normalization-factory.js +26 -1
  13. package/dist/normalization/normalization-factory.js.map +1 -1
  14. package/dist/normalization/walkers.js +14 -2
  15. package/dist/normalization/walkers.js.map +1 -1
  16. package/dist/router-configuration/router-configuration.d.ts +12 -0
  17. package/dist/schema-building/ast.js +3 -3
  18. package/dist/schema-building/ast.js.map +1 -1
  19. package/dist/schema-building/type-merging.js +5 -5
  20. package/dist/schema-building/type-merging.js.map +1 -1
  21. package/dist/schema-building/utils.d.ts +4 -2
  22. package/dist/schema-building/utils.js +37 -9
  23. package/dist/schema-building/utils.js.map +1 -1
  24. package/dist/tsconfig.tsbuildinfo +1 -1
  25. package/dist/utils/constants.d.ts +5 -2
  26. package/dist/utils/constants.js +100 -4
  27. package/dist/utils/constants.js.map +1 -1
  28. package/dist/utils/integer-constants.d.ts +2 -0
  29. package/dist/utils/integer-constants.js +6 -0
  30. package/dist/utils/integer-constants.js.map +1 -0
  31. package/dist/utils/string-constants.d.ts +20 -0
  32. package/dist/utils/string-constants.js +23 -3
  33. package/dist/utils/string-constants.js.map +1 -1
  34. package/dist/utils/utils.d.ts +1 -0
  35. package/dist/utils/utils.js +57 -15
  36. package/dist/utils/utils.js.map +1 -1
  37. package/package.json +2 -2
@@ -16,6 +16,7 @@ const utils_5 = require("../schema-building/utils");
16
16
  const walkers_1 = require("./walkers");
17
17
  const lodash_1 = require("lodash");
18
18
  const type_merging_1 = require("../schema-building/type-merging");
19
+ const integer_constants_1 = require("../utils/integer-constants");
19
20
  class FederationFactory {
20
21
  authorizationDataByParentTypeName;
21
22
  concreteTypeNamesByAbstractTypeName;
@@ -50,6 +51,8 @@ class FederationFactory {
50
51
  potentialPersistedDirectiveDefinitionDataByDirectiveName = new Map();
51
52
  routerDefinitions = [constants_1.DEPRECATED_DEFINITION, constants_1.TAG_DEFINITION];
52
53
  shareableErrorTypeNames = new Map();
54
+ subscriptionFilterDataByFieldPath = new Map();
55
+ isMaxDepth = false;
53
56
  tagNamesByPath = new Map();
54
57
  warnings;
55
58
  constructor(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainersByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings) {
@@ -634,12 +637,30 @@ class FederationFactory {
634
637
  this.inaccessiblePaths.add(argumentPath);
635
638
  }
636
639
  }
640
+ handleSubscriptionFilterDirective(incomingData, fieldPath, baseData) {
641
+ const subscriptionFilters = incomingData.directivesByDirectiveName.get(string_constants_1.SUBSCRIPTION_FILTER);
642
+ if (subscriptionFilters) {
643
+ // There should only be a single entry in the set
644
+ const subgraphName = (0, utils_3.getSingleSetEntry)(incomingData.subgraphNames);
645
+ if (subgraphName === undefined) {
646
+ this.errors.push((0, errors_1.unknownFieldSubgraphNameError)(fieldPath));
647
+ return;
648
+ }
649
+ // @openfed__subscriptionFilter is non-repeatable
650
+ this.subscriptionFilterDataByFieldPath.set(fieldPath, {
651
+ directive: subscriptionFilters[0],
652
+ fieldData: baseData || incomingData,
653
+ directiveSubgraphName: subgraphName,
654
+ });
655
+ }
656
+ }
637
657
  upsertFieldData(fieldDataByFieldName, incomingData, isParentInaccessible) {
638
658
  const fieldPath = `${incomingData.renamedParentTypeName}.${incomingData.name}`;
639
659
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, incomingData.namedTypeName, () => new Set()).add(fieldPath);
640
660
  this.namedOutputTypeNames.add(incomingData.namedTypeName);
641
661
  const existingData = fieldDataByFieldName.get(incomingData.name);
642
662
  const baseData = existingData || incomingData;
663
+ this.handleSubscriptionFilterDirective(incomingData, fieldPath, baseData);
643
664
  (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
644
665
  const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(incomingData);
645
666
  if (isParentInaccessible || isFieldInaccessible) {
@@ -783,6 +804,7 @@ class FederationFactory {
783
804
  type: fieldData.type,
784
805
  };
785
806
  const fieldPath = `${fieldData.renamedParentTypeName}.${fieldData.name}`;
807
+ this.handleSubscriptionFilterDirective(fieldData, fieldPath);
786
808
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, fieldData.namedTypeName, () => new Set()).add(fieldPath);
787
809
  this.namedOutputTypeNames.add(fieldData.namedTypeName);
788
810
  (0, utils_5.extractPersistedDirectives)(fieldData.persistedDirectivesData, fieldData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
@@ -941,7 +963,7 @@ class FederationFactory {
941
963
  for (const [fieldName, fieldData] of data.fieldDataByFieldName) {
942
964
  const fieldPath = `${fieldData.renamedParentTypeName}.${fieldName}`;
943
965
  this.inaccessiblePaths.add(fieldPath);
944
- for (const [argumentName, inputValueData] of fieldData.argumentDataByArgumentName) {
966
+ for (const inputValueData of fieldData.argumentDataByArgumentName.values()) {
945
967
  this.inaccessiblePaths.add(inputValueData.renamedPath);
946
968
  }
947
969
  }
@@ -1327,7 +1349,7 @@ class FederationFactory {
1327
1349
  federateSubgraphData() {
1328
1350
  this.federateInternalSubgraphData();
1329
1351
  this.handleEntityInterfaces();
1330
- for (const [parentTypeName, objectExtensionData] of this.objectExtensionDataByTypeName) {
1352
+ for (const objectExtensionData of this.objectExtensionDataByTypeName.values()) {
1331
1353
  this.upsertValidObjectExtensionData(objectExtensionData);
1332
1354
  }
1333
1355
  // generate the map of tag data that is used by contracts
@@ -1336,8 +1358,7 @@ class FederationFactory {
1336
1358
  }
1337
1359
  validateInterfaceImplementationsAndPushToDocumentDefinitions(interfaceImplementations) {
1338
1360
  for (const { data, clientSchemaFieldNodes } of interfaceImplementations) {
1339
- const validInterfaces = this.getValidImplementedInterfaces(data);
1340
- data.node.interfaces = validInterfaces;
1361
+ data.node.interfaces = this.getValidImplementedInterfaces(data);
1341
1362
  this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(data, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1342
1363
  if ((0, utils_5.isNodeDataInaccessible)(data)) {
1343
1364
  this.validateReferencesOfInaccessibleType(data);
@@ -1404,7 +1425,274 @@ class FederationFactory {
1404
1425
  }
1405
1426
  this.errors.push(errors_1.noQueryRootTypeError);
1406
1427
  }
1428
+ validateSubscriptionFieldConditionFieldPath(conditionFieldPath, objectData, inputFieldPath, directiveSubgraphName, fieldErrorMessages) {
1429
+ const paths = conditionFieldPath.split(string_constants_1.PERIOD);
1430
+ if (paths.length < 1) {
1431
+ fieldErrorMessages.push((0, errors_1.invalidSubscriptionFieldConditionFieldPathErrorMessage)(inputFieldPath, conditionFieldPath));
1432
+ return [];
1433
+ }
1434
+ let lastData = objectData;
1435
+ if (this.inaccessiblePaths.has(lastData.renamedTypeName)) {
1436
+ fieldErrorMessages.push((0, errors_1.inaccessibleSubscriptionFieldConditionFieldPathFieldErrorMessage)(inputFieldPath, conditionFieldPath, paths[0], lastData.renamedTypeName));
1437
+ return [];
1438
+ }
1439
+ let partialConditionFieldPath = '';
1440
+ for (let i = 0; i < paths.length; i++) {
1441
+ const fieldName = paths[i];
1442
+ partialConditionFieldPath += partialConditionFieldPath.length > 0 ? `.${fieldName}` : fieldName;
1443
+ if (lastData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1444
+ fieldErrorMessages.push((0, errors_1.invalidSubscriptionFieldConditionFieldPathParentErrorMessage)(inputFieldPath, conditionFieldPath, partialConditionFieldPath));
1445
+ return [];
1446
+ }
1447
+ const fieldData = lastData.fieldDataByFieldName.get(fieldName);
1448
+ if (!fieldData) {
1449
+ fieldErrorMessages.push((0, errors_1.undefinedSubscriptionFieldConditionFieldPathFieldErrorMessage)(inputFieldPath, conditionFieldPath, partialConditionFieldPath, fieldName, lastData.renamedTypeName));
1450
+ return [];
1451
+ }
1452
+ const fieldPath = `${lastData.renamedTypeName}.${fieldName}`;
1453
+ if (!fieldData.subgraphNames.has(directiveSubgraphName)) {
1454
+ fieldErrorMessages.push((0, errors_1.invalidSubscriptionFieldConditionFieldPathFieldErrorMessage)(inputFieldPath, conditionFieldPath, partialConditionFieldPath, fieldPath, directiveSubgraphName));
1455
+ return [];
1456
+ }
1457
+ if (this.inaccessiblePaths.has(fieldPath)) {
1458
+ fieldErrorMessages.push((0, errors_1.inaccessibleSubscriptionFieldConditionFieldPathFieldErrorMessage)(inputFieldPath, conditionFieldPath, partialConditionFieldPath, fieldPath));
1459
+ return [];
1460
+ }
1461
+ if (constants_1.BASE_SCALARS.has(fieldData.namedTypeName)) {
1462
+ lastData = { kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION, name: fieldData.namedTypeName };
1463
+ continue;
1464
+ }
1465
+ lastData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, fieldData.namedTypeName, string_constants_1.PARENT_DEFINITION_DATA);
1466
+ }
1467
+ if (!(0, utils_5.isLeafKind)(lastData.kind)) {
1468
+ fieldErrorMessages.push((0, errors_1.nonLeafSubscriptionFieldConditionFieldPathFinalFieldErrorMessage)(inputFieldPath, conditionFieldPath, paths[paths.length - 1], (0, utils_3.kindToTypeString)(lastData.kind), lastData.name));
1469
+ return [];
1470
+ }
1471
+ return paths;
1472
+ }
1473
+ validateSubscriptionFieldCondition(objectValueNode, condition, objectData, depth, inputPath, directiveSubgraphName, errorMessages) {
1474
+ if (depth > integer_constants_1.MAX_SUBSCRIPTION_FILTER_DEPTH || this.isMaxDepth) {
1475
+ errorMessages.push((0, errors_1.subscriptionFilterConditionDepthExceededErrorMessage)(inputPath));
1476
+ this.isMaxDepth = true;
1477
+ return false;
1478
+ }
1479
+ let hasErrors = false;
1480
+ const validFieldNames = new Set([string_constants_1.FIELD_PATH, string_constants_1.VALUES]);
1481
+ const duplicatedFieldNames = new Set();
1482
+ const invalidFieldNames = new Set();
1483
+ const fieldErrorMessages = [];
1484
+ for (const objectFieldNode of objectValueNode.fields) {
1485
+ const inputFieldName = objectFieldNode.name.value;
1486
+ const inputFieldPath = inputPath + `.${inputFieldName}`;
1487
+ switch (inputFieldName) {
1488
+ case string_constants_1.FIELD_PATH: {
1489
+ if (validFieldNames.has(string_constants_1.FIELD_PATH)) {
1490
+ validFieldNames.delete(string_constants_1.FIELD_PATH);
1491
+ }
1492
+ else {
1493
+ hasErrors = true;
1494
+ duplicatedFieldNames.add(string_constants_1.FIELD_PATH);
1495
+ break;
1496
+ }
1497
+ if (objectFieldNode.value.kind !== graphql_1.Kind.STRING) {
1498
+ fieldErrorMessages.push((0, errors_1.invalidInputFieldTypeErrorMessage)(inputFieldPath, string_constants_1.STRING, (0, utils_3.kindToTypeString)(objectFieldNode.value.kind)));
1499
+ hasErrors = true;
1500
+ break;
1501
+ }
1502
+ const fieldPath = this.validateSubscriptionFieldConditionFieldPath(objectFieldNode.value.value, objectData, inputFieldPath, directiveSubgraphName, fieldErrorMessages);
1503
+ if (fieldPath.length < 1) {
1504
+ hasErrors = true;
1505
+ break;
1506
+ }
1507
+ condition.fieldPath = fieldPath;
1508
+ break;
1509
+ }
1510
+ case string_constants_1.VALUES: {
1511
+ if (validFieldNames.has(string_constants_1.VALUES)) {
1512
+ validFieldNames.delete(string_constants_1.VALUES);
1513
+ }
1514
+ else {
1515
+ hasErrors = true;
1516
+ duplicatedFieldNames.add(string_constants_1.VALUES);
1517
+ break;
1518
+ }
1519
+ const objectFieldValueKind = objectFieldNode.value.kind;
1520
+ if (objectFieldValueKind == graphql_1.Kind.NULL || objectFieldValueKind == graphql_1.Kind.OBJECT) {
1521
+ fieldErrorMessages.push((0, errors_1.invalidInputFieldTypeErrorMessage)(inputFieldPath, string_constants_1.LIST, (0, utils_3.kindToTypeString)(objectFieldNode.value.kind)));
1522
+ hasErrors = true;
1523
+ break;
1524
+ }
1525
+ // Coerce scalars into a list
1526
+ if (objectFieldValueKind !== graphql_1.Kind.LIST) {
1527
+ condition.values = [(0, utils_5.getSubscriptionFilterValue)(objectFieldNode.value)];
1528
+ break;
1529
+ }
1530
+ // Prevent duplicate values
1531
+ const values = new Set();
1532
+ const invalidIndices = [];
1533
+ for (let i = 0; i < objectFieldNode.value.values.length; i++) {
1534
+ const valueNode = objectFieldNode.value.values[i];
1535
+ if (valueNode.kind === graphql_1.Kind.OBJECT || valueNode.kind === graphql_1.Kind.LIST) {
1536
+ hasErrors = true;
1537
+ invalidIndices.push(i);
1538
+ continue;
1539
+ }
1540
+ values.add((0, utils_5.getSubscriptionFilterValue)(valueNode));
1541
+ }
1542
+ if (invalidIndices.length > 0) {
1543
+ fieldErrorMessages.push((0, errors_1.subscriptionFieldConditionInvalidValuesArrayErrorMessage)(inputFieldPath, invalidIndices));
1544
+ continue;
1545
+ }
1546
+ if (values.size < 1) {
1547
+ hasErrors = true;
1548
+ fieldErrorMessages.push((0, errors_1.subscriptionFieldConditionEmptyValuesArrayErrorMessage)(inputFieldPath));
1549
+ continue;
1550
+ }
1551
+ condition.values = [...values];
1552
+ break;
1553
+ }
1554
+ default: {
1555
+ hasErrors = true;
1556
+ invalidFieldNames.add(inputFieldName);
1557
+ }
1558
+ }
1559
+ }
1560
+ if (!hasErrors) {
1561
+ return true;
1562
+ }
1563
+ errorMessages.push((0, errors_1.subscriptionFieldConditionInvalidInputFieldErrorMessage)(inputPath, [...validFieldNames], [...duplicatedFieldNames], [...invalidFieldNames], fieldErrorMessages));
1564
+ return false;
1565
+ }
1566
+ validateSubscriptionFilterCondition(objectValueNode, configuration, objectData, depth, inputPath, directiveSubgraphName, errorMessages) {
1567
+ if (depth > integer_constants_1.MAX_SUBSCRIPTION_FILTER_DEPTH || this.isMaxDepth) {
1568
+ errorMessages.push((0, errors_1.subscriptionFilterConditionDepthExceededErrorMessage)(inputPath));
1569
+ this.isMaxDepth = true;
1570
+ return false;
1571
+ }
1572
+ depth += 1;
1573
+ if (objectValueNode.fields.length !== 1) {
1574
+ errorMessages.push((0, errors_1.subscriptionFilterConditionInvalidInputFieldNumberErrorMessage)(inputPath, objectValueNode.fields.length));
1575
+ return false;
1576
+ }
1577
+ const objectFieldNode = objectValueNode.fields[0];
1578
+ const fieldName = objectFieldNode.name.value;
1579
+ if (!string_constants_1.SUBSCRIPTION_FILTER_INPUT_NAMES.has(fieldName)) {
1580
+ errorMessages.push((0, errors_1.subscriptionFilterConditionInvalidInputFieldErrorMessage)(inputPath, fieldName));
1581
+ return false;
1582
+ }
1583
+ const inputFieldPath = inputPath + `.${fieldName}`;
1584
+ switch (objectFieldNode.value.kind) {
1585
+ case graphql_1.Kind.OBJECT: {
1586
+ switch (fieldName) {
1587
+ case string_constants_1.IN_UPPER: {
1588
+ configuration.in = { fieldPath: [], values: [] };
1589
+ return this.validateSubscriptionFieldCondition(objectFieldNode.value, configuration.in, objectData, depth, inputPath + `.IN`, directiveSubgraphName, errorMessages);
1590
+ }
1591
+ case string_constants_1.NOT_UPPER: {
1592
+ configuration.not = {};
1593
+ return this.validateSubscriptionFilterCondition(objectFieldNode.value, configuration.not, objectData, depth, inputPath + `.NOT`, directiveSubgraphName, errorMessages);
1594
+ }
1595
+ default:
1596
+ // The field is guaranteed to be an AND or an OR
1597
+ errorMessages.push((0, errors_1.subscriptionFilterConditionInvalidInputFieldTypeErrorMessage)(inputFieldPath, string_constants_1.LIST, string_constants_1.OBJECT));
1598
+ return false;
1599
+ }
1600
+ }
1601
+ case graphql_1.Kind.LIST: {
1602
+ const listConfigurations = [];
1603
+ switch (fieldName) {
1604
+ case string_constants_1.AND_UPPER: {
1605
+ configuration.and = listConfigurations;
1606
+ break;
1607
+ }
1608
+ case string_constants_1.OR_UPPER: {
1609
+ configuration.or = listConfigurations;
1610
+ break;
1611
+ }
1612
+ default:
1613
+ // The field is guaranteed to be an IN or a NOT
1614
+ errorMessages.push((0, errors_1.subscriptionFilterConditionInvalidInputFieldTypeErrorMessage)(inputFieldPath, string_constants_1.OBJECT, string_constants_1.LIST));
1615
+ return false;
1616
+ }
1617
+ const listLength = objectFieldNode.value.values.length;
1618
+ if (listLength < 1 || listLength > 5) {
1619
+ errorMessages.push((0, errors_1.subscriptionFilterArrayConditionInvalidLengthErrorMessage)(inputFieldPath, listLength));
1620
+ return false;
1621
+ }
1622
+ let isValid = true;
1623
+ const invalidIndices = [];
1624
+ for (let i = 0; i < objectFieldNode.value.values.length; i++) {
1625
+ const arrayIndexPath = inputFieldPath + `[${i}]`;
1626
+ const listValueNode = objectFieldNode.value.values[i];
1627
+ if (listValueNode.kind !== graphql_1.Kind.OBJECT) {
1628
+ invalidIndices.push(i);
1629
+ continue;
1630
+ }
1631
+ const listConfiguration = {};
1632
+ isValid &&= this.validateSubscriptionFilterCondition(listValueNode, listConfiguration, objectData, depth, arrayIndexPath, directiveSubgraphName, errorMessages);
1633
+ if (isValid) {
1634
+ listConfigurations.push(listConfiguration);
1635
+ }
1636
+ }
1637
+ if (invalidIndices.length > 0) {
1638
+ errorMessages.push((0, errors_1.subscriptionFilterArrayConditionInvalidItemTypeErrorMessage)(inputFieldPath, invalidIndices));
1639
+ return false;
1640
+ }
1641
+ return isValid;
1642
+ }
1643
+ default: {
1644
+ const expectedTypeString = string_constants_1.SUBSCRIPTION_FILTER_LIST_INPUT_NAMES.has(fieldName) ? string_constants_1.LIST : string_constants_1.OBJECT;
1645
+ errorMessages.push((0, errors_1.subscriptionFilterConditionInvalidInputFieldTypeErrorMessage)(inputFieldPath, expectedTypeString, (0, utils_3.kindToTypeString)(objectFieldNode.value.kind)));
1646
+ return false;
1647
+ }
1648
+ }
1649
+ }
1650
+ validateSubscriptionFilterAndGenerateConfiguration(directiveNode, objectData, fieldPath, fieldName, parentTypeName, directiveSubgraphName) {
1651
+ // directive validation occurs elsewhere
1652
+ if (!directiveNode.arguments || directiveNode.arguments.length !== 1) {
1653
+ return;
1654
+ }
1655
+ const argumentNode = directiveNode.arguments[0];
1656
+ if (argumentNode.value.kind !== graphql_1.Kind.OBJECT) {
1657
+ this.errors.push((0, errors_1.invalidSubscriptionFilterDirectiveError)(fieldPath, [
1658
+ (0, errors_1.subscriptionFilterConditionInvalidInputFieldTypeErrorMessage)(string_constants_1.CONDITION, 'object', (0, utils_3.kindToTypeString)(argumentNode.value.kind)),
1659
+ ]));
1660
+ return;
1661
+ }
1662
+ const condition = {};
1663
+ const errorMessages = [];
1664
+ if (!this.validateSubscriptionFilterCondition(argumentNode.value, condition, objectData, 0, string_constants_1.CONDITION, directiveSubgraphName, errorMessages)) {
1665
+ this.errors.push((0, errors_1.invalidSubscriptionFilterDirectiveError)(fieldPath, errorMessages));
1666
+ this.isMaxDepth = false;
1667
+ return;
1668
+ }
1669
+ (0, utils_3.getValueOrDefault)(this.fieldConfigurationByFieldPath, fieldPath, () => ({
1670
+ argumentNames: [],
1671
+ fieldName,
1672
+ typeName: parentTypeName,
1673
+ })).subscriptionFilterCondition = condition;
1674
+ }
1675
+ validateSubscriptionFiltersAndGenerateConfiguration() {
1676
+ for (const [fieldPath, data] of this.subscriptionFilterDataByFieldPath) {
1677
+ if (this.inaccessiblePaths.has(fieldPath)) {
1678
+ continue;
1679
+ }
1680
+ const namedTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, data.fieldData.namedTypeName, string_constants_1.PARENT_DEFINITION_DATA);
1681
+ if ((0, utils_5.isNodeDataInaccessible)(namedTypeData)) {
1682
+ // @inaccessible error are caught elsewhere
1683
+ continue;
1684
+ }
1685
+ // TODO handle Unions and Interfaces
1686
+ if (namedTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1687
+ continue;
1688
+ }
1689
+ this.validateSubscriptionFilterAndGenerateConfiguration(data.directive, namedTypeData, fieldPath, data.fieldData.name, data.fieldData.renamedParentTypeName, data.directiveSubgraphName);
1690
+ }
1691
+ }
1407
1692
  buildFederationResult() {
1693
+ if (this.subscriptionFilterDataByFieldPath.size > 0) {
1694
+ this.validateSubscriptionFiltersAndGenerateConfiguration();
1695
+ }
1408
1696
  if (this.invalidOrScopesHostPaths.size > 0) {
1409
1697
  this.errors.push((0, errors_1.orScopesLimitError)(utils_3.maxOrScopes, [...this.invalidOrScopesHostPaths]));
1410
1698
  }
@@ -1557,6 +1845,9 @@ class FederationFactory {
1557
1845
  }
1558
1846
  }
1559
1847
  }
1848
+ if (this.subscriptionFilterDataByFieldPath.size > 0) {
1849
+ this.validateSubscriptionFiltersAndGenerateConfiguration();
1850
+ }
1560
1851
  for (const data of this.potentialPersistedDirectiveDefinitionDataByDirectiveName.values()) {
1561
1852
  (0, utils_5.addValidPersistedDirectiveDefinitionNodeByData)(this.routerDefinitions, data, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1562
1853
  }