Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ public static FieldDirective Parse(DirectiveNode directive)
break;

case "provides":
provides = Utf8GraphQLParser.Syntax.ParseSelectionSet(((StringValueNode)argument.Value).Value);
var providesValue = ((StringValueNode)argument.Value).Value;
provides = ParseProvidesSelectionSet(providesValue);
break;

case "external":
isExternal = ((BooleanValueNode)argument.Value).Value;
break;

case "partial":
// `partial` is the composition-time encoding for external source fields.
isExternal = ((BooleanValueNode)argument.Value).Value;
break;

default:
throw new DirectiveParserException(
$"The argument `{argument.Name.Value}` is not supported on @field.");
Expand All @@ -56,6 +62,20 @@ public static FieldDirective Parse(DirectiveNode directive)
return new FieldDirective(new SchemaKey(schemaKey), sourceName, sourceType, provides, isExternal);
}

private static SelectionSetNode ParseProvidesSelectionSet(string value)
{
try
{
// Fusion schemas can encode provides either as a raw selection set (`{ id }`) or as
// the legacy field-set form (`id`).
return Utf8GraphQLParser.Syntax.ParseSelectionSet(value);
}
catch (SyntaxException)
{
return Utf8GraphQLParser.Syntax.ParseSelectionSet($"{{ {value} }}");
}
}

public static ImmutableArray<FieldDirective> Parse(
IReadOnlyList<DirectiveNode> directiveNodes)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
using HotChocolate.Fusion.Types;

namespace HotChocolate.Fusion.Planning;

public class EntityChainTests : FusionTestBase
{
[Fact]
public void Complex_Entity_Call()
{
// arrange
var schema = CreateComplexEntityCallSchema();

// act
var plan = PlanOperation(
schema,
"""
{
topProducts {
products {
id
price {
price
}
}
}
}
""");

// assert
MatchSnapshot(plan);
}

[Fact]
public void Parent_Entity_Call_Complex()
{
// arrange
var schema = CreateParentEntityCallComplexSchema();

// act
var plan = PlanOperation(
schema,
"""
query {
productFromD(id: "1") {
id
name
category {
id
name
details
}
}
}
""");

// assert
MatchSnapshot(plan);
}

private static FusionSchemaDefinition CreateComplexEntityCallSchema()
{
return ComposeSchema(
"""
# name: products
schema {
query: Query
}

type Query {
topProducts: ProductList!
}

type ProductList {
products: [Product!]!
}

type Product @key(fields: "id") {
id: ID!
category: Category! @shareable
}

type Category {
id: ID! @shareable
tag: String @shareable
}
""",
"""
# name: link
schema {
query: Query
}

type Query {
productById(id: ID! @is(field: "id")): Product @lookup @internal
}

type Product @key(fields: "id") {
id: ID!
pid: ID! @shareable
}
""",
"""
# name: price
schema {
query: Query
}

type Query {
productByIdPidAndCategory(
id: ID! @is(field: "id")
pid: ID! @is(field: "pid")
categoryId: ID! @is(field: "category.id")
categoryTag: String @is(field: "category.tag")): Product @lookup @internal
}

type Product @key(fields: "id pid category { id tag }") {
id: ID!
pid: ID! @shareable
category: Category! @shareable
price: Price
}

type Category {
id: ID! @shareable
tag: String @shareable
}

type Price {
price: Float!
}
""");
}

private static FusionSchemaDefinition CreateParentEntityCallComplexSchema()
{
return ComposeSchema(
"""
# name: a
schema {
query: Query
}

type Query {
productById(id: ID! @is(field: "id")): Product @lookup @internal
}

type Product @key(fields: "id") {
id: ID!
category: Category @shareable
}

type Category {
details: String
}
""",
"""
# name: b
schema {
query: Query
}

type Query {
productById(id: ID! @is(field: "id")): Product @lookup @internal
}

type Product @key(fields: "id") {
id: ID!
category: Category @shareable
}

type Category @key(fields: "id") {
id: ID!
}
""",
"""
# name: c
schema {
query: Query
}

type Query {
categoryById(id: ID! @is(field: "id")): Category @lookup @internal
}

type Category @key(fields: "id") {
id: ID!
name: String
}
""",
"""
# name: d
schema {
query: Query
}

type Query {
productFromD(id: ID!): Product
productById(id: ID! @is(field: "id")): Product @lookup @internal
}

type Product @key(fields: "id") {
id: ID!
name: String
}
""");
}
}
Loading
Loading