diff --git a/src/HotChocolate/Fusion/src/Composition/Features/TagDirectiveFeature.cs b/src/HotChocolate/Fusion/src/Composition/Features/TagDirectiveFeature.cs
index 1ebec12768f..d203de798d5 100644
--- a/src/HotChocolate/Fusion/src/Composition/Features/TagDirectiveFeature.cs
+++ b/src/HotChocolate/Fusion/src/Composition/Features/TagDirectiveFeature.cs
@@ -3,23 +3,18 @@ namespace HotChocolate.Fusion.Composition.Features;
///
/// Specifies behavior of the @tag directive.
///
-public sealed class TagDirectiveFeature : IFusionFeature
+public sealed class TagDirectiveFeature(
+ IEnumerable? exclude = null,
+ bool makeTagsPublic = false)
+ : IFusionFeature
{
- public TagDirectiveFeature(
- IEnumerable? exclude = null,
- bool makeTagsPublic = false)
- {
- Excluded = new HashSet(exclude ?? Enumerable.Empty());
- MakeTagsPublic = makeTagsPublic;
- }
-
///
/// Gets the tags that shall be excluded from the public schema.
///
- public IReadOnlySet Excluded { get; }
+ public IReadOnlySet Excluded { get; } = new HashSet(exclude ?? Enumerable.Empty());
///
/// Defines if the tag directives should be exported to the public schema.
///
- public bool MakeTagsPublic { get; }
+ public bool MakeTagsPublic { get; } = makeTagsPublic;
}
\ No newline at end of file
diff --git a/src/HotChocolate/Fusion/src/Composition/FusionGraphComposer.cs b/src/HotChocolate/Fusion/src/Composition/FusionGraphComposer.cs
index 4d02dcf457c..b255cf4a60d 100644
--- a/src/HotChocolate/Fusion/src/Composition/FusionGraphComposer.cs
+++ b/src/HotChocolate/Fusion/src/Composition/FusionGraphComposer.cs
@@ -72,8 +72,8 @@ internal FusionGraphComposer(
.Use()
.Use()
.Use()
- .Use()
.Use()
+ .Use()
.Use()
.Build();
_logFactory = logFactory;
diff --git a/src/HotChocolate/Fusion/src/Composition/Pipeline/ApplyTagDirectiveMiddleware.cs b/src/HotChocolate/Fusion/src/Composition/Pipeline/ApplyTagDirectiveMiddleware.cs
index aa6dc2e43e4..9fe8c330ccb 100644
--- a/src/HotChocolate/Fusion/src/Composition/Pipeline/ApplyTagDirectiveMiddleware.cs
+++ b/src/HotChocolate/Fusion/src/Composition/Pipeline/ApplyTagDirectiveMiddleware.cs
@@ -8,21 +8,17 @@ namespace HotChocolate.Fusion.Composition.Pipeline;
internal sealed class ApplyTagDirectiveMiddleware : IMergeMiddleware
{
- public async ValueTask InvokeAsync(CompositionContext context, MergeDelegate next)
+ public ValueTask InvokeAsync(CompositionContext context, MergeDelegate next)
{
- if (context.Features.MakeTagsPublic())
- {
- Rewrite(context);
- }
-
- if (!context.Log.HasErrors)
- {
- await next(context);
- }
+ Rewrite(context, context.Features.MakeTagsPublic());
+ return !context.Log.HasErrors
+ ? next(context)
+ : ValueTask.CompletedTask;
}
private static void Rewrite(
- CompositionContext context)
+ CompositionContext context,
+ bool makePublic)
{
var needsDirectiveType = false;
@@ -54,7 +50,7 @@ private static void Rewrite(
}
var tags = new HashSet();
- Rewrite(context, tagDirectiveType, tags);
+ Rewrite(context, tagDirectiveType, tags, makePublic);
if (context.GetTagContext().HasTags && needsDirectiveType)
{
@@ -65,38 +61,39 @@ private static void Rewrite(
private static void Rewrite(
CompositionContext context,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var tagContext = context.GetTagContext();
- ApplyDirectives(tagContext, context.FusionGraph, context.Subgraphs, tagDirectiveType, tags);
+ ApplyDirectives(tagContext, context.FusionGraph, context.Subgraphs, tagDirectiveType, tags, makePublic);
foreach (var type in context.FusionGraph.Types)
{
switch (type)
{
case ObjectType objectType:
- Rewrite(context, tagContext, objectType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, objectType, tagDirectiveType, tags, makePublic);
break;
case InterfaceType interfaceType:
- Rewrite(context, tagContext, interfaceType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, interfaceType, tagDirectiveType, tags, makePublic);
break;
case UnionType unionType:
- Rewrite(context, tagContext, unionType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, unionType, tagDirectiveType, tags, makePublic);
break;
case InputObjectType inputObjectType:
- Rewrite(context, tagContext, inputObjectType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, inputObjectType, tagDirectiveType, tags, makePublic);
break;
case EnumType enumType:
- Rewrite(context, tagContext, enumType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, enumType, tagDirectiveType, tags, makePublic);
break;
case ScalarType scalarType:
- Rewrite(context, tagContext, scalarType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, scalarType, tagDirectiveType, tags, makePublic);
break;
default:
@@ -106,7 +103,7 @@ private static void Rewrite(
foreach (var directiveType in context.FusionGraph.DirectiveTypes)
{
- Rewrite(context, tagContext, directiveType, tagDirectiveType, tags);
+ Rewrite(context, tagContext, directiveType, tagDirectiveType, tags, makePublic);
}
}
@@ -115,15 +112,16 @@ private static void Rewrite(
TagContext tagContext,
ComplexType type,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = new SchemaCoordinate(type.Name);
- ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags);
+ ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags, makePublic);
foreach (var field in type.Fields)
{
- Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
}
}
@@ -132,23 +130,25 @@ private static void Rewrite(
TagContext tagContext,
UnionType type,
DirectiveType tagDirectiveType,
- HashSet tags)
- => ApplyDirectives(context, tagContext, type, new SchemaCoordinate(type.Name), tagDirectiveType, tags);
+ HashSet tags,
+ bool makePublic)
+ => ApplyDirectives(context, tagContext, type, new(type.Name), tagDirectiveType, tags, makePublic);
private static void Rewrite(
CompositionContext context,
TagContext tagContext,
InputObjectType type,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = new SchemaCoordinate(type.Name);
- ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags);
+ ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags, makePublic);
foreach (var field in type.Fields)
{
- Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
}
}
@@ -157,15 +157,16 @@ private static void Rewrite(
TagContext tagContext,
EnumType type,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = new SchemaCoordinate(type.Name);
- ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags);
+ ApplyDirectives(context, tagContext, type, coordinate, tagDirectiveType, tags, makePublic);
foreach (var field in type.Values)
{
- Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
}
}
@@ -174,21 +175,23 @@ private static void Rewrite(
TagContext tagContext,
ScalarType type,
DirectiveType tagDirectiveType,
- HashSet tags)
- => ApplyDirectives(context, tagContext, type, new SchemaCoordinate(type.Name), tagDirectiveType, tags);
+ HashSet tags,
+ bool makePublic)
+ => ApplyDirectives(context, tagContext, type, new(type.Name), tagDirectiveType, tags, makePublic);
private static void Rewrite(
CompositionContext context,
TagContext tagContext,
DirectiveType type,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = new SchemaCoordinate(type.Name, ofDirective: true);
foreach (var field in type.Arguments)
{
- Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ Rewrite(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
}
}
@@ -198,15 +201,16 @@ private static void Rewrite(
OutputField field,
SchemaCoordinate parent,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = new SchemaCoordinate(parent.Name, field.Name);
- ApplyDirectives(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ ApplyDirectives(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
foreach (var argument in field.Arguments)
{
- Rewrite(context, tagContext, argument, coordinate, tagDirectiveType, tags);
+ Rewrite(context, tagContext, argument, coordinate, tagDirectiveType, tags, makePublic);
}
}
@@ -216,7 +220,8 @@ private static void Rewrite(
InputField field,
SchemaCoordinate parent,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
{
var coordinate = parent switch
{
@@ -225,7 +230,7 @@ private static void Rewrite(
{ MemberName: not null } => new SchemaCoordinate(parent.Name, parent.MemberName, field.Name),
};
- ApplyDirectives(context, tagContext, field, coordinate, tagDirectiveType, tags);
+ ApplyDirectives(context, tagContext, field, coordinate, tagDirectiveType, tags, makePublic);
}
private static void Rewrite(
@@ -234,14 +239,16 @@ private static void Rewrite(
EnumValue value,
SchemaCoordinate parent,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
=> ApplyDirectives(
context,
tagContext,
value,
new SchemaCoordinate(parent.Name, value.Name),
tagDirectiveType,
- tags);
+ tags,
+ makePublic);
private static void ApplyDirectives(
CompositionContext context,
@@ -249,11 +256,12 @@ private static void ApplyDirectives(
T merged,
SchemaCoordinate coordinate,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
where T : ITypeSystemMember, IHasDirectives
{
var parts = context.GetSubgraphMembers(coordinate);
- ApplyDirectives(tagContext, merged, parts, tagDirectiveType, tags);
+ ApplyDirectives(tagContext, merged, parts, tagDirectiveType, tags, makePublic);
foreach (var tag in tags)
{
@@ -266,7 +274,8 @@ private static void ApplyDirectives(
T merged,
IEnumerable parts,
DirectiveType tagDirectiveType,
- HashSet tags)
+ HashSet tags,
+ bool makePublic)
where T : ITypeSystemMember, IHasDirectives
{
tags.Clear();
@@ -288,6 +297,11 @@ private static void ApplyDirectives(
value is StringValueNode name &&
tags.Add(name.Value))
{
+ if (!makePublic)
+ {
+ continue;
+ }
+
merged.Directives.Add(
new Directive(
tagDirectiveType,
diff --git a/src/HotChocolate/Fusion/src/Composition/Pipeline/TagContext.cs b/src/HotChocolate/Fusion/src/Composition/Pipeline/TagContext.cs
index 1e26f7ee9ff..1239fb99658 100644
--- a/src/HotChocolate/Fusion/src/Composition/Pipeline/TagContext.cs
+++ b/src/HotChocolate/Fusion/src/Composition/Pipeline/TagContext.cs
@@ -6,7 +6,7 @@ internal sealed class TagContext
private readonly Dictionary> _taggedTypes =
new(StringComparer.Ordinal);
- public bool HasTags { get; set; } = false;
+ public bool HasTags { get; set; }
public void RegisterTagCoordinate(string name, SchemaCoordinate coordinate)
{
@@ -16,10 +16,10 @@ public void RegisterTagCoordinate(string name, SchemaCoordinate coordinate)
}
else
{
- _taggedTypes.Add(name, new HashSet { coordinate });
+ _taggedTypes.Add(name, [coordinate]);
}
}
public IReadOnlySet GetTagCoordinates(string name)
- => _taggedTypes.TryGetValue(name, out var coordinates) ? coordinates : _empty;
+ => _taggedTypes.GetValueOrDefault(name, _empty);
}
\ No newline at end of file
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs b/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs
index 613901c50d0..bed5257e463 100644
--- a/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs
@@ -193,9 +193,9 @@ await PackageHelper.CreateSubgraphPackageAsync(
account.ExtensionFiles));
var packageFile = CreateTempFile(Extensions.FusionPackage);
- var settingsFile = System.IO.Path.Combine(
- System.IO.Path.GetDirectoryName(packageFile)!,
- $"{System.IO.Path.GetFileNameWithoutExtension(packageFile)}-settings.json");
+ var settingsFile = Path.Combine(
+ Path.GetDirectoryName(packageFile)!,
+ $"{Path.GetFileNameWithoutExtension(packageFile)}-settings.json");
await File.WriteAllTextAsync(
settingsFile,
@@ -328,4 +328,51 @@ await app.InvokeAsync(
snapshot.MatchSnapshot();
}
+
+ [Fact]
+ public async Task Compose_With_Tag()
+ {
+ // arrange
+ var subgraphDir = CreateTempDir();
+ Directory.CreateDirectory(subgraphDir);
+
+ var schemaFile = Path.Combine(subgraphDir, "schema.graphql");
+ var configFile = Path.Combine(subgraphDir, "subgraph-config.json");
+
+ await File.WriteAllTextAsync(schemaFile, FileResource.Open("test2.graphql"), Encoding.UTF8);
+ await File.WriteAllTextAsync(configFile, FileResource.Open("test2.subgraph-config.json"), Encoding.UTF8);
+
+ var packageFile = CreateTempFile(Extensions.FusionPackage);
+ var gatewayConfig = Path.Combine(
+ Path.GetDirectoryName(packageFile)!,
+ Path.GetFileNameWithoutExtension(packageFile) + "-settings.json");
+ File.Delete(packageFile);
+
+ await File.WriteAllTextAsync(gatewayConfig, FileResource.Open("test2.gateway-config.json"), Encoding.UTF8);
+
+ // act
+ var app = App.CreateBuilder().Build();
+ await app.InvokeAsync(new[] { "compose", "-p", packageFile, "-s", subgraphDir });
+
+ // assert
+ Assert.True(File.Exists(packageFile));
+
+ await using var package = FusionGraphPackage.Open(packageFile, FileAccess.Read);
+
+ var fusionGraph = await package.GetFusionGraphAsync();
+ var schema = await package.GetSchemaAsync();
+ var subgraphs = await package.GetSubgraphConfigurationsAsync();
+
+ var snapshot = new Snapshot();
+
+ snapshot.Add(schema, "Schema Document");
+ snapshot.Add(fusionGraph, "Fusion Graph Document");
+
+ foreach (var subgraph in subgraphs)
+ {
+ snapshot.Add(subgraph, $"{subgraph.Name} Subgraph Configuration");
+ }
+
+ snapshot.MatchSnapshot();
+ }
}
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj b/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj
index daad547f725..0f12f97b64f 100644
--- a/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj
@@ -17,13 +17,9 @@
Always
-
+
Always
-
-
-
-
-
+
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.gateway-config.json b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.gateway-config.json
new file mode 100644
index 00000000000..b3d1b1b90f4
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.gateway-config.json
@@ -0,0 +1,10 @@
+{
+ "fusionTypePrefix": null,
+ "fusionTypeSelf": false,
+ "nodeField": { "enabled": true },
+ "tagDirective": {
+ "enabled": true,
+ "makePublic": false,
+ "exclude": ["internal"]
+ }
+}
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.graphql b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.graphql
new file mode 100644
index 00000000000..a8818a52a97
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.graphql
@@ -0,0 +1,40 @@
+type Query {
+ node(id: ID!): Node
+ nodes(ids: [ID!]!): [Node]!
+ userById(id: ID!): User
+ userByName(name: String!): User
+ users(first: Int, after: String, last: Int, before: String): UsersConnection
+}
+
+type User implements Node {
+ id: ID!
+ name: String! @tag(name: "internal")
+ displayName: String!
+ birthdate: String!
+}
+
+interface Node {
+ id: ID!
+}
+
+type UsersConnection {
+ pageInfo: PageInfo!
+ edges: [UsersEdge!]
+ nodes: [User!]
+}
+
+type UsersEdge {
+ cursor: String!
+ node: User!
+}
+
+type PageInfo {
+ hasNextPage: Boolean!
+ hasPreviousPage: Boolean!
+ startCursor: String
+ endCursor: String
+}
+
+scalar DateTime
+
+directive @tag(name: String!) repeatable on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.subgraph-config.json b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.subgraph-config.json
new file mode 100644
index 00000000000..0029eede1e7
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__resources__/test2.subgraph-config.json
@@ -0,0 +1,4 @@
+{
+ "subgraph": "accounts",
+ "http": { "baseAddress": "https://localhost:3000/graphql" }
+}
diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_With_Tag.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_With_Tag.snap
new file mode 100644
index 00000000000..565e7d13537
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_With_Tag.snap
@@ -0,0 +1,105 @@
+Schema Document
+---------------
+schema {
+ query: Query
+}
+
+type Query {
+ node(id: ID!): Node
+ nodes(ids: [ID!]!): [Node]!
+ userById(id: ID!): User
+ userByName(name: String!): User
+ users(after: String before: String first: Int last: Int): UsersConnection
+}
+
+type PageInfo {
+ endCursor: String
+ hasNextPage: Boolean!
+ hasPreviousPage: Boolean!
+ startCursor: String
+}
+
+type User implements Node {
+ birthdate: String!
+ displayName: String!
+ id: ID!
+}
+
+type UsersConnection {
+ edges: [UsersEdge!]
+ nodes: [User!]
+ pageInfo: PageInfo!
+}
+
+type UsersEdge {
+ cursor: String!
+ node: User!
+}
+
+interface Node {
+ id: ID!
+}
+
+scalar DateTime
+---------------
+
+Fusion Graph Document
+---------------
+schema @fusion(version: 1) @transport(subgraph: "accounts", group: "Fusion", location: "https:\/\/localhost:3000\/graphql", kind: "HTTP") @node(subgraph: "accounts", types: [ "User" ]) {
+ query: Query
+}
+
+type Query {
+ node(id: ID!): Node @variable(subgraph: "accounts", name: "id", argument: "id") @resolver(subgraph: "accounts", select: "{ node(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
+ nodes(ids: [ID!]!): [Node]! @variable(subgraph: "accounts", name: "ids", argument: "ids") @resolver(subgraph: "accounts", select: "{ nodes(ids: $ids) }", arguments: [ { name: "ids", type: "[ID!]!" } ])
+ userById(id: ID!): User @variable(subgraph: "accounts", name: "id", argument: "id") @resolver(subgraph: "accounts", select: "{ userById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
+ userByName(name: String!): User @variable(subgraph: "accounts", name: "name", argument: "name") @resolver(subgraph: "accounts", select: "{ userByName(name: $name) }", arguments: [ { name: "name", type: "String!" } ])
+ users(after: String before: String first: Int last: Int): UsersConnection @variable(subgraph: "accounts", name: "after", argument: "after") @variable(subgraph: "accounts", name: "before", argument: "before") @variable(subgraph: "accounts", name: "first", argument: "first") @variable(subgraph: "accounts", name: "last", argument: "last") @resolver(subgraph: "accounts", select: "{ users(after: $after, before: $before, first: $first, last: $last) }", arguments: [ { name: "after", type: "String" }, { name: "before", type: "String" }, { name: "first", type: "Int" }, { name: "last", type: "Int" } ])
+}
+
+type PageInfo {
+ endCursor: String @source(subgraph: "accounts")
+ hasNextPage: Boolean! @source(subgraph: "accounts")
+ hasPreviousPage: Boolean! @source(subgraph: "accounts")
+ startCursor: String @source(subgraph: "accounts")
+}
+
+type User implements Node @variable(subgraph: "accounts", name: "User_id", select: "id") @variable(subgraph: "accounts", name: "User_name", select: "name") @resolver(subgraph: "accounts", select: "{ userById(id: $User_id) }", arguments: [ { name: "User_id", type: "ID!" } ]) @resolver(subgraph: "accounts", select: "{ userByName(name: $User_name) }", arguments: [ { name: "User_name", type: "String!" } ]) @resolver(subgraph: "accounts", select: "{ nodes(ids: $User_id) { ... on User { ... User } } }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH") {
+ birthdate: String! @source(subgraph: "accounts")
+ displayName: String! @source(subgraph: "accounts")
+ id: ID! @source(subgraph: "accounts")
+}
+
+type UsersConnection {
+ edges: [UsersEdge!] @source(subgraph: "accounts")
+ nodes: [User!] @source(subgraph: "accounts")
+ pageInfo: PageInfo! @source(subgraph: "accounts")
+}
+
+type UsersEdge {
+ cursor: String! @source(subgraph: "accounts")
+ node: User! @source(subgraph: "accounts")
+}
+
+interface Node {
+ id: ID!
+}
+
+scalar DateTime
+---------------
+
+accounts Subgraph Configuration
+---------------
+{
+ "Name": "accounts",
+ "Schema": "type Query {\n node(id: ID!): Node\n nodes(ids: [ID!]!): [Node]!\n userById(id: ID!): User\n userByName(name: String!): User\n users(first: Int after: String last: Int before: String): UsersConnection\n}\n\ntype User implements Node {\n id: ID!\n name: String! @tag(name: \"internal\")\n displayName: String!\n birthdate: String!\n}\n\ninterface Node {\n id: ID!\n}\n\ntype UsersConnection {\n pageInfo: PageInfo!\n edges: [UsersEdge!]\n nodes: [User!]\n}\n\ntype UsersEdge {\n cursor: String!\n node: User!\n}\n\ntype PageInfo {\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n startCursor: String\n endCursor: String\n}\n\nscalar DateTime\n\ndirective @tag(name: String!) repeatable on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION",
+ "Extensions": [],
+ "Clients": [
+ {
+ "ClientName": null,
+ "BaseAddress": "https://localhost:3000/graphql"
+ }
+ ],
+ "ConfigurationExtensions": null
+}
+---------------
diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag.graphql
index dc285df44c3..b32a04d247c 100644
--- a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag.graphql
+++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag.graphql
@@ -21,9 +21,6 @@ type Query {
@resolver(subgraph: "Reviews", select: "{ reviewOrAuthor }")
reviews: [Review!]!
@resolver(subgraph: "Reviews", select: "{ reviews }")
- someTypeById(id: ID!): SomeType!
- @variable(subgraph: "Accounts", name: "id", argument: "id")
- @resolver(subgraph: "Accounts", select: "{ someTypeById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
userById(id: ID!): User
@variable(subgraph: "Accounts", name: "id", argument: "id")
@resolver(subgraph: "Accounts", select: "{ userById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
@@ -42,7 +39,7 @@ type Mutation {
addReview(input: AddReviewInput!): AddReviewPayload!
@variable(subgraph: "Reviews", name: "input", argument: "input")
@resolver(subgraph: "Reviews", select: "{ addReview(input: $input) }", arguments: [ { name: "input", type: "AddReviewInput!" } ])
- addUser(input: AddUserInput!): AddUserPayload!
+ addUser: AddUserPayload!
@variable(subgraph: "Accounts", name: "input", argument: "input")
@resolver(subgraph: "Accounts", select: "{ addUser(input: $input) }", arguments: [ { name: "input", type: "AddUserInput!" } ])
}
@@ -90,14 +87,6 @@ type SomeData {
@source(subgraph: "Accounts")
}
-type SomeType
- @variable(subgraph: "Accounts", name: "SomeType_id", select: "id")
- @resolver(subgraph: "Accounts", select: "{ someTypeById(id: $SomeType_id) }", arguments: [ { name: "SomeType_id", type: "ID!" } ])
- @tag(name: "internal") {
- id: ID!
- @source(subgraph: "Accounts")
-}
-
type User implements Node
@source(subgraph: "Reviews", name: "Author")
@variable(subgraph: "Accounts", name: "User_id", select: "id")
@@ -106,9 +95,6 @@ type User implements Node
@resolver(subgraph: "Accounts", select: "{ usersById(ids: $User_id) }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH")
@resolver(subgraph: "Reviews", select: "{ authorById(id: $User_id) }", arguments: [ { name: "User_id", type: "ID!" } ])
@resolver(subgraph: "Reviews", select: "{ nodes(ids: $User_id) { ... on User { ... User } } }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH") {
- birthdate: Date!
- @source(subgraph: "Accounts")
- @tag(name: "internal")
id: ID!
@source(subgraph: "Accounts")
@source(subgraph: "Reviews")
@@ -141,13 +127,6 @@ input AddReviewInput {
upc: Int!
}
-input AddUserInput {
- birthdate: Date!
- @tag(name: "internal")
- name: String!
- username: String!
-}
-
"The `Date` scalar represents an ISO-8601 compliant date type."
scalar Date
diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag_Which_Is_Private.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag_Which_Is_Private.graphql
index c5d2932fa6b..772da05906e 100644
--- a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag_Which_Is_Private.graphql
+++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/TagTests.Exclude_Type_System_Members_With_Internal_Tag_Which_Is_Private.graphql
@@ -20,9 +20,6 @@ type Query {
@resolver(subgraph: "Reviews", select: "{ reviewOrAuthor }")
reviews: [Review!]!
@resolver(subgraph: "Reviews", select: "{ reviews }")
- someTypeById(id: ID!): SomeType!
- @variable(subgraph: "Accounts", name: "id", argument: "id")
- @resolver(subgraph: "Accounts", select: "{ someTypeById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
userById(id: ID!): User
@variable(subgraph: "Accounts", name: "id", argument: "id")
@resolver(subgraph: "Accounts", select: "{ userById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ])
@@ -41,7 +38,7 @@ type Mutation {
addReview(input: AddReviewInput!): AddReviewPayload!
@variable(subgraph: "Reviews", name: "input", argument: "input")
@resolver(subgraph: "Reviews", select: "{ addReview(input: $input) }", arguments: [ { name: "input", type: "AddReviewInput!" } ])
- addUser(input: AddUserInput!): AddUserPayload!
+ addUser: AddUserPayload!
@variable(subgraph: "Accounts", name: "input", argument: "input")
@resolver(subgraph: "Accounts", select: "{ addUser(input: $input) }", arguments: [ { name: "input", type: "AddUserInput!" } ])
}
@@ -89,13 +86,6 @@ type SomeData {
@source(subgraph: "Accounts")
}
-type SomeType
- @variable(subgraph: "Accounts", name: "SomeType_id", select: "id")
- @resolver(subgraph: "Accounts", select: "{ someTypeById(id: $SomeType_id) }", arguments: [ { name: "SomeType_id", type: "ID!" } ]) {
- id: ID!
- @source(subgraph: "Accounts")
-}
-
type User implements Node
@source(subgraph: "Reviews", name: "Author")
@variable(subgraph: "Accounts", name: "User_id", select: "id")
@@ -104,8 +94,6 @@ type User implements Node
@resolver(subgraph: "Accounts", select: "{ usersById(ids: $User_id) }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH")
@resolver(subgraph: "Reviews", select: "{ authorById(id: $User_id) }", arguments: [ { name: "User_id", type: "ID!" } ])
@resolver(subgraph: "Reviews", select: "{ nodes(ids: $User_id) { ... on User { ... User } } }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH") {
- birthdate: Date!
- @source(subgraph: "Accounts")
id: ID!
@source(subgraph: "Accounts")
@source(subgraph: "Reviews")
@@ -138,11 +126,5 @@ input AddReviewInput {
upc: Int!
}
-input AddUserInput {
- birthdate: Date!
- name: String!
- username: String!
-}
-
"The `Date` scalar represents an ISO-8601 compliant date type."
scalar Date
\ No newline at end of file
diff --git a/src/HotChocolate/Utilities/src/Utilities.DependencyInjection/ServiceCollectionExtensions.cs b/src/HotChocolate/Utilities/src/Utilities.DependencyInjection/ServiceCollectionExtensions.cs
index 9dd0e63c00f..96b22e9dad4 100644
--- a/src/HotChocolate/Utilities/src/Utilities.DependencyInjection/ServiceCollectionExtensions.cs
+++ b/src/HotChocolate/Utilities/src/Utilities.DependencyInjection/ServiceCollectionExtensions.cs
@@ -9,9 +9,9 @@ public static bool IsImplementationTypeRegistered(
this IServiceCollection services)
{
#if NET8_0_OR_GREATER
- return services.All(t => !t.IsKeyedService && t.ImplementationType != typeof(TService));
+ return services.Any(t => !t.IsKeyedService && t.ImplementationType == typeof(TService));
#else
- return services.All(t => t.ImplementationType != typeof(TService));
+ return services.Any(t => t.ImplementationType == typeof(TService));
#endif
}
@@ -19,9 +19,9 @@ public static bool IsServiceTypeRegistered(
this IServiceCollection services)
{
#if NET8_0_OR_GREATER
- return services.All(t => !t.IsKeyedService && t.ServiceType != typeof(TService));
+ return services.Any(t => !t.IsKeyedService && t.ServiceType == typeof(TService));
#else
- return services.All(t => t.ServiceType != typeof(TService));
+ return services.Any(t => t.ServiceType == typeof(TService));
#endif
}