Skip to content
Draft
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
6 changes: 5 additions & 1 deletion bin/dev-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use query_planner::graph::PlannerOverrideContext;
use query_planner::planner::best::find_best_combination;
use query_planner::planner::fetch::fetch_graph::build_fetch_graph_from_query_tree;
use query_planner::planner::fetch::fetch_graph::FetchGraph;
use query_planner::planner::fetch::state::MultiTypeFetchStep;
use query_planner::planner::plan_nodes::QueryPlan;
use query_planner::planner::query_plan::build_query_plan_from_fetch_graph;
use query_planner::planner::tree::query_tree::QueryTree;
Expand Down Expand Up @@ -124,7 +125,10 @@ fn process_consumer_schema(path: &str) {
println!("{}", consumer_schema.document);
}

fn process_fetch_graph(supergraph_path: &str, operation_path: &str) -> FetchGraph {
fn process_fetch_graph(
supergraph_path: &str,
operation_path: &str,
) -> FetchGraph<MultiTypeFetchStep> {
let (graph, query_tree, supergraph_state) =
process_merged_tree(supergraph_path, operation_path);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
@link(url: "https://specs.apollo.dev/inaccessible/v0.2", for: SECURITY) {
query: Query
}

directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE

directive @join__field(
graph: join__Graph
requires: join__FieldSet
provides: join__FieldSet
type: String
external: Boolean
override: String
usedOverridden: Boolean
) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

directive @join__implements(
graph: join__Graph!
interface: String!
) repeatable on OBJECT | INTERFACE

directive @join__type(
graph: join__Graph!
key: join__FieldSet
extension: Boolean! = false
resolvable: Boolean! = true
isInterfaceObject: Boolean! = false
) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR

directive @join__unionMember(
graph: join__Graph!
member: String!
) repeatable on UNION

directive @link(
url: String
as: String
for: link__Purpose
import: [link__Import]
) repeatable on SCHEMA

type Agency @join__type(graph: AGENCY, key: "id") @join__type(graph: PRODUCTS) {
id: ID!
companyName: String @join__field(graph: AGENCY)
email: Email @join__field(graph: AGENCY)
}

type Book implements Product & Similar
@join__implements(graph: INVENTORY, interface: "Product")
@join__implements(graph: PRODUCTS, interface: "Product")
@join__implements(graph: PRODUCTS, interface: "Similar")
@join__implements(graph: REVIEWS, interface: "Product")
@join__implements(graph: REVIEWS, interface: "Similar")
@join__type(graph: BOOKS, key: "id")
@join__type(graph: INVENTORY, key: "id")
@join__type(graph: PRODUCTS, key: "id")
@join__type(graph: REVIEWS, key: "id") {
id: ID!
title: String @join__field(graph: BOOKS)
dimensions: ProductDimension
@join__field(graph: INVENTORY, external: true)
@join__field(graph: PRODUCTS)
delivery(zip: String): DeliveryEstimates
@join__field(graph: INVENTORY, requires: "dimensions { size weight }")
sku: String @join__field(graph: PRODUCTS)
createdBy: User @join__field(graph: PRODUCTS)
similar: [Book]
@join__field(graph: PRODUCTS)
@join__field(graph: REVIEWS, external: true)
hidden: Boolean @join__field(graph: PRODUCTS)
publisherType: PublisherType @join__field(graph: PRODUCTS)
reviewsCount: Int! @join__field(graph: REVIEWS)
reviewsScore: Float! @join__field(graph: REVIEWS)
reviews: [Review!]! @join__field(graph: REVIEWS)
reviewsOfSimilar: [Review!]!
@join__field(graph: REVIEWS, requires: "similar { id }")
}

type DeliveryEstimates @join__type(graph: INVENTORY) {
estimatedDelivery: String
fastestDelivery: String
}

type Email @join__type(graph: AGENCY) {
address: String
}

type Group @join__type(graph: AGENCY, key: "id") {
id: ID!
name: String
email: String
}

scalar join__FieldSet

enum join__Graph {
AGENCY
@join__graph(
name: "agency"
url: "http://localhost:4200/abstract-types/agency"
)
BOOKS
@join__graph(
name: "books"
url: "http://localhost:4200/abstract-types/books"
)
INVENTORY
@join__graph(
name: "inventory"
url: "http://localhost:4200/abstract-types/inventory"
)
MAGAZINES
@join__graph(
name: "magazines"
url: "http://localhost:4200/abstract-types/magazines"
)
PRODUCTS
@join__graph(
name: "products"
url: "http://localhost:4200/abstract-types/products"
)
REVIEWS
@join__graph(
name: "reviews"
url: "http://localhost:4200/abstract-types/reviews"
)
USERS
@join__graph(
name: "users"
url: "http://localhost:4200/abstract-types/users"
)
}

scalar link__Import

enum link__Purpose {
"""
`SECURITY` features provide metadata necessary to securely resolve fields.
"""
SECURITY

"""
`EXECUTION` features provide metadata necessary for operation execution.
"""
EXECUTION
}

type Magazine implements Product & Similar
@join__implements(graph: INVENTORY, interface: "Product")
@join__implements(graph: PRODUCTS, interface: "Product")
@join__implements(graph: PRODUCTS, interface: "Similar")
@join__implements(graph: REVIEWS, interface: "Product")
@join__implements(graph: REVIEWS, interface: "Similar")
@join__type(graph: INVENTORY, key: "id")
@join__type(graph: MAGAZINES, key: "id")
@join__type(graph: PRODUCTS, key: "id")
@join__type(graph: REVIEWS, key: "id") {
id: ID!
dimensions: ProductDimension
@join__field(graph: INVENTORY, external: true)
@join__field(graph: PRODUCTS)
delivery(zip: String): DeliveryEstimates
@join__field(graph: INVENTORY, requires: "dimensions { size weight }")
title: String @join__field(graph: MAGAZINES)
sku: String @join__field(graph: PRODUCTS)
createdBy: User @join__field(graph: PRODUCTS)
similar: [Magazine]
@join__field(graph: PRODUCTS)
@join__field(graph: REVIEWS, external: true)
hidden: Boolean @join__field(graph: PRODUCTS)
publisherType: PublisherType @join__field(graph: PRODUCTS)
reviewsCount: Int! @join__field(graph: REVIEWS)
reviewsScore: Float! @join__field(graph: REVIEWS)
reviews: [Review!]! @join__field(graph: REVIEWS)
reviewsOfSimilar: [Review!]!
@join__field(graph: REVIEWS, requires: "similar { id }")
}

interface Product
@join__type(graph: INVENTORY)
@join__type(graph: PRODUCTS)
@join__type(graph: REVIEWS) {
id: ID!
dimensions: ProductDimension
@join__field(graph: INVENTORY)
@join__field(graph: PRODUCTS)
delivery(zip: String): DeliveryEstimates @join__field(graph: INVENTORY)
sku: String @join__field(graph: PRODUCTS)
createdBy: User @join__field(graph: PRODUCTS)
hidden: Boolean @inaccessible @join__field(graph: PRODUCTS)
reviewsCount: Int! @join__field(graph: REVIEWS)
reviewsScore: Float! @join__field(graph: REVIEWS)
reviews: [Review!]! @join__field(graph: REVIEWS)
}

type ProductDimension
@join__type(graph: INVENTORY)
@join__type(graph: PRODUCTS) {
size: String
weight: Float
}

union PublisherType
@join__type(graph: AGENCY)
@join__type(graph: PRODUCTS)
@join__unionMember(graph: AGENCY, member: "Agency")
@join__unionMember(graph: PRODUCTS, member: "Agency")
@join__unionMember(graph: AGENCY, member: "Group")
@join__unionMember(graph: PRODUCTS, member: "Self") =
| Agency
| Group
| Self

type Query
@join__type(graph: AGENCY)
@join__type(graph: BOOKS)
@join__type(graph: INVENTORY)
@join__type(graph: MAGAZINES)
@join__type(graph: PRODUCTS)
@join__type(graph: REVIEWS)
@join__type(graph: USERS) {
books: [Book] @join__field(graph: BOOKS)
magazines: [Magazine] @join__field(graph: MAGAZINES)
products: [Product] @join__field(graph: PRODUCTS)
similar(id: ID!): [Product] @join__field(graph: PRODUCTS)
review(id: Int!): Review @join__field(graph: REVIEWS)
}

type Review @join__type(graph: REVIEWS) {
id: Int!
body: String!
product: Product
}

type Self @join__type(graph: PRODUCTS) {
email: String
}

interface Similar @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS) {
similar: [Product]
}

type User
@join__type(graph: PRODUCTS, key: "email")
@join__type(graph: USERS, key: "email") {
email: ID!
totalProductsCreated: Int
name: String @join__field(graph: USERS)
}
11 changes: 11 additions & 0 deletions lib/query-planner/src/ast/merge_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ impl MergePath {
}
self.common_prefix_len(other) == other.len()
}

pub fn without_type_castings(&self) -> Self {
let new_segments = self
.inner
.iter()
.filter(|segment| !matches!(segment, Segment::Cast(_, _)))
.cloned()
.collect::<Vec<_>>();

Self::new(new_segments)
}
}

impl Display for MergePath {
Expand Down
4 changes: 2 additions & 2 deletions lib/query-planner/src/ast/minification/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ pub enum MinificationError {
FieldNotFound(String, String),
#[error("Unsupported fragment spread")]
UnsupportedFragmentSpread,
#[error("Unsupported field in `_entities`: {0}")]
UnsupportedFieldInEntities(String),
#[error("Unsupported field in `_entities`: {0}.{1}")]
UnsupportedFieldInEntities(String, String),
}
1 change: 1 addition & 0 deletions lib/query-planner/src/ast/minification/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ fn walk_and_collect_stats(
}

return Err(MinificationError::UnsupportedFieldInEntities(
type_def.name().to_string(),
field.name.clone(),
));
}
Expand Down
1 change: 1 addition & 0 deletions lib/query-planner/src/ast/minification/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ fn transform_field(
}

return Err(MinificationError::UnsupportedFieldInEntities(
type_name.to_string(),
field.name.clone(),
));
}
Expand Down
Loading
Loading