Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
Generate filter input objects per type; cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
deekerno committed Dec 13, 2023
1 parent 829fa86 commit a2941aa
Show file tree
Hide file tree
Showing 8 changed files with 367 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type Transaction @entity {

type Block @entity {
id: ID!
height: U64!
height: U64! @search
hash: Bytes32! @unique
transactions: [Transaction!]!
}
49 changes: 0 additions & 49 deletions packages/fuel-indexer-graphql/src/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,55 +41,6 @@ lazy_static! {
"UID",
]);

/// Scalar types that are represented by a numeric type. This ensures that the
/// value type provided for a field filter matches the type of the scalar itself.
static ref NUMERIC_SCALAR_TYPES: HashSet<&'static str> = HashSet::from([
"I128",
"I16",
"I32",
"I64",
"U128",
"U16",
"U32",
"U64",
]);

/// Scalar types that are represented by a string type. This ensures that the
/// value type provided for a field filter matches the type of the scalar itself.
static ref STRING_SCALAR_TYPES: HashSet<&'static str> = HashSet::from([
"Address",
"AssetId",
"Bytes",
"Bytes32",
"Bytes4",
"Bytes64",
"Bytes64",
"Bytes8",
"ContractId",
"ID",
"Identity",
"Json",
"UID",
]);

/// Scalar types that can be sorted.
static ref SORTABLE_SCALAR_TYPES: HashSet<&'static str> = HashSet::from([
"Address",
"AssetId",
"ContractId",
"I128",
"I16",
"I32",
"I64",
"ID",
"Identity",
"U128",
"U16",
"U32",
"U64",
"UID",
]);

/// Entity types that should be ignored when building the dynamic schema,
/// so that they do not appear in the generated documentation. This is done
/// to hide internal Fuel indexer entity types.
Expand Down
16 changes: 14 additions & 2 deletions packages/fuel-indexer-graphql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type GraphqlResult<T> = Result<T, GraphqlError>;

#[derive(Debug, Error)]
pub enum GraphqlError {
#[error("GraphQl Parser error: {0:?}")]
#[error("GraphQL parser error: {0:?}")]
ParseError(#[from] async_graphql_parser::Error),
#[error("Error building dynamic schema: {0:?}")]
DynamicSchemaBuildError(#[from] async_graphql::dynamic::SchemaError),
Expand Down Expand Up @@ -38,7 +38,9 @@ pub enum GraphqlError {
MissingPartnerForBinaryLogicalOperator,
#[error("Paginated query must have an order applied to at least one field")]
UnorderedPaginatedQuery,
#[error("Query error: {0:?}")]
#[error("Querying for the entire range is not supported")]
NoCompleteRangeQueriesAllowed,
#[error("{0:?}")]
QueryError(String),
#[error("Scalar fields require a parent object")]
ScalarsRequireAParent,
Expand All @@ -48,4 +50,14 @@ pub enum GraphqlError {
CouldNotGetBaseEntityType(String),
#[error("Undefined variable: {0:?}")]
UndefinedVariable(String),
#[error("Cannot have cycles in query")]
NoCyclesAllowedInQuery,
#[error("Root level node should be a query type")]
RootNeedsToBeAQuery,
#[error("Improper reference to root name")]
RootNameOnNonRootObj,
#[error("Parsing error with internal type - {0:?}")]
InternalTypeParseError(String),
#[error("Object query requires an ID argument")]
ObjectQueryNeedsIdArg,
}
9 changes: 6 additions & 3 deletions packages/fuel-indexer-graphql/src/query/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,13 @@ impl QueryParams {
match db_type {
DbType::Postgres => {
if self.sorts.is_empty() {
return Err(GraphqlError::QueryError(
"Pagination needs a sort order".to_string(),
));
return Err(GraphqlError::UnorderedPaginatedQuery);
}

if self.limit.is_none() {
return Err(GraphqlError::NoCompleteRangeQueriesAllowed);
}

if let Some(pagination) = &self.pagination {
match pagination.direction {
Direction::Forward => {
Expand Down
10 changes: 3 additions & 7 deletions packages/fuel-indexer-graphql/src/query/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ fn parse_selections(
}
}
_ => {
return Err(GraphqlError::QueryError("FIXME".to_string()))
return Err(GraphqlError::InternalTypeParseError(entity))
}
}
} else if has_no_subselections {
Expand Down Expand Up @@ -395,9 +395,7 @@ fn parse_selections(
if !arguments.iter().any(|a| {
matches!(a, ParamType::Filter(FilterType::IdSelection(_)))
}) {
return Err(GraphqlError::QueryError(
"Query needs ID argument".to_string(),
));
return Err(GraphqlError::ObjectQueryNeedsIdArg);
} else {
arguments.push(ParamType::Limit(1));
}
Expand All @@ -413,9 +411,7 @@ fn parse_selections(
});
return Ok(v);
} else {
return Err(GraphqlError::QueryError(
"Root level must be a query".to_string(),
));
return Err(GraphqlError::RootNeedsToBeAQuery);
}
}
Selection::FragmentSpread(frag_spread) => {
Expand Down
20 changes: 5 additions & 15 deletions packages/fuel-indexer-graphql/src/query/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,7 @@ impl DependencyGraph {
if let Ok(sorted) = petgraph::algo::toposort(&self.graph, None) {
sorted
} else {
return Err(GraphqlError::QueryError(
"Cannot have cycles in query".to_string(),
));
return Err(GraphqlError::NoCyclesAllowedInQuery);
};

if toposorted_nodes.is_empty() {
Expand Down Expand Up @@ -531,7 +529,7 @@ impl PreparedSelection {
if let Some(n) = &o.name {
n.to_owned()
} else {
todo!()
unreachable!()
}
}
PreparedSelection::Root(r) => r.root_entity.clone(),
Expand All @@ -543,9 +541,7 @@ impl PreparedSelection {
fn root_name(&self) -> GraphqlResult<String> {
match &self {
PreparedSelection::Root(r) => Ok(r.root_entity.to_lowercase()),
_ => Err(GraphqlError::QueryError(
"Non-root type cannot have a root name".to_string(),
)),
_ => Err(GraphqlError::RootNameOnNonRootObj),
}
}
}
Expand Down Expand Up @@ -576,11 +572,7 @@ fn prepare_query_selections(
&mut common_tables,
kind,
)?,
_ => {
return Err(GraphqlError::QueryError(
"Root level node needs to be a root object".to_string(),
))
}
_ => return Err(GraphqlError::RootNeedsToBeAQuery),
};

Ok((
Expand Down Expand Up @@ -716,9 +708,7 @@ pub fn prepare_selection(
obj_type: _,
} => {
if let ParsedSelection::List { .. } = *node {
return Err(GraphqlError::QueryError(
"Lists of lists are not supported".to_string(),
));
return Err(GraphqlError::ListsOfLists);
}

let field_name = alias
Expand Down
2 changes: 2 additions & 0 deletions packages/fuel-indexer-lib/src/graphql/base.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ directive @join(on: String) on OBJECT
directive @unique on FIELD_DEFINITION | ENUM_VALUE

directive @virtual on FIELD_DEFINITION

directive @search on FIELD_DEFINITION
Loading

0 comments on commit a2941aa

Please sign in to comment.