diff --git a/compiler/crates/relay-transforms/src/assignable_fragment_spread/errors.rs b/compiler/crates/relay-transforms/src/assignable_fragment_spread/errors.rs index 7e141cb5604bb..8900b69140231 100644 --- a/compiler/crates/relay-transforms/src/assignable_fragment_spread/errors.rs +++ b/compiler/crates/relay-transforms/src/assignable_fragment_spread/errors.rs @@ -59,6 +59,11 @@ pub enum ValidationMessage { outer_type_plural: &'static str, }, + #[error( + "Fields defined using Relay Resolvers are not not allowed within @updatable operations." + )] + UpdatableDisallowRealyResolvers, + #[error("The directives @include and @skip are not allowed within {outer_type_plural}.")] UpdatableNoConditions { outer_type_plural: &'static str }, diff --git a/compiler/crates/relay-transforms/src/assignable_fragment_spread/validate_updatable_directive.rs b/compiler/crates/relay-transforms/src/assignable_fragment_spread/validate_updatable_directive.rs index d5dfc7aa4488c..e5570814e866e 100644 --- a/compiler/crates/relay-transforms/src/assignable_fragment_spread/validate_updatable_directive.rs +++ b/compiler/crates/relay-transforms/src/assignable_fragment_spread/validate_updatable_directive.rs @@ -23,6 +23,7 @@ use graphql_ir::InlineFragment; use graphql_ir::LinkedField; use graphql_ir::OperationDefinition; use graphql_ir::Program; +use graphql_ir::ScalarField; use graphql_ir::Selection; use graphql_ir::Validator; use intern::string_key::Intern; @@ -33,6 +34,7 @@ use schema::Schema; use super::ValidationMessage; use super::ASSIGNABLE_DIRECTIVE; use super::UPDATABLE_DIRECTIVE; +use crate::RELAY_RESOLVER_DIRECTIVE_NAME; lazy_static! { static ref ALLOW_LISTED_DIRECTIVES: Vec = vec![ @@ -309,10 +311,43 @@ impl<'a> Validator for UpdatableDirective<'a> { } } + fn validate_scalar_field(&mut self, field: &ScalarField) -> DiagnosticsResult<()> { + let field_def = self.program.schema.field(field.definition.item); + if field_def + .directives + .named(*RELAY_RESOLVER_DIRECTIVE_NAME) + .is_some() + { + return Err(vec![ + Diagnostic::error( + ValidationMessage::UpdatableDisallowRealyResolvers, + field.definition.location, + ) + .annotate("The field is defined here:", field_def.name.location), + ]); + } + self.default_validate_scalar_field(field) + } + fn validate_linked_field(&mut self, linked_field: &LinkedField) -> DiagnosticsResult<()> { let fragment_spreads = filter_fragment_spreads(linked_field.selections.iter()); let inline_fragments = filter_inline_fragments(linked_field.selections.iter()); + let field_def = self.program.schema.field(linked_field.definition.item); + if field_def + .directives + .named(*RELAY_RESOLVER_DIRECTIVE_NAME) + .is_some() + { + return Err(vec![ + Diagnostic::error( + ValidationMessage::UpdatableDisallowRealyResolvers, + linked_field.definition.location, + ) + .annotate("The field is defined here:", field_def.name.location), + ]); + } + validate!( self.validate_fragment_spreads_with_parent(linked_field, fragment_spreads), self.validate_inline_fragments_with_parent(linked_field, inline_fragments.collect()), diff --git a/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.expected b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.expected new file mode 100644 index 0000000000000..73513bfa6bb4e --- /dev/null +++ b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.expected @@ -0,0 +1,29 @@ +==================================== INPUT ==================================== +# expected-to-throw +query resolverQuery @updatable { + resolver_field { + id + } +} + +# %extensions% + +extend type Query { + resolver_field: User @relay_resolver(import_path: "ResolverModule") +} +==================================== ERROR ==================================== +✖︎ Fields defined using Relay Resolvers are not not allowed within @updatable operations. + + resolver-linked.invalid.graphql:3:3 + 2 │ query resolverQuery @updatable { + 3 │ resolver_field { + │ ^^^^^^^^^^^^^^ + 4 │ id + + ℹ︎ The field is defined here: + + :2:5 + 1 │ # expected-to-throw + 2 │ query resolverQuery @updatable { + │ ^^^^^^^^^^^^^^ + 3 │ resolver_field { diff --git a/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.graphql b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.graphql new file mode 100644 index 0000000000000..42d3b0f8b1083 --- /dev/null +++ b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-linked.invalid.graphql @@ -0,0 +1,12 @@ +# expected-to-throw +query resolverQuery @updatable { + resolver_field { + id + } +} + +# %extensions% + +extend type Query { + resolver_field: User @relay_resolver(import_path: "ResolverModule") +} diff --git a/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.expected b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.expected new file mode 100644 index 0000000000000..a23bb0bd08dfa --- /dev/null +++ b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.expected @@ -0,0 +1,27 @@ +==================================== INPUT ==================================== +# expected-to-throw +query resolverQuery @updatable { + resolver_field +} + +# %extensions% + +extend type Query { + resolver_field: Boolean @relay_resolver(import_path: "ResolverModule") +} +==================================== ERROR ==================================== +✖︎ Fields defined using Relay Resolvers are not not allowed within @updatable operations. + + resolver-scalar.invalid.graphql:3:3 + 2 │ query resolverQuery @updatable { + 3 │ resolver_field + │ ^^^^^^^^^^^^^^ + 4 │ } + + ℹ︎ The field is defined here: + + :2:5 + 1 │ # expected-to-throw + 2 │ query resolverQuery @updatable { + │ ^^^^^^^^^^^^^^ + 3 │ resolver_field diff --git a/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.graphql b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.graphql new file mode 100644 index 0000000000000..0bd9ece707e25 --- /dev/null +++ b/compiler/crates/relay-transforms/tests/updatable_directive/fixtures/resolver-scalar.invalid.graphql @@ -0,0 +1,10 @@ +# expected-to-throw +query resolverQuery @updatable { + resolver_field +} + +# %extensions% + +extend type Query { + resolver_field: Boolean @relay_resolver(import_path: "ResolverModule") +} diff --git a/compiler/crates/relay-transforms/tests/updatable_directive_test.rs b/compiler/crates/relay-transforms/tests/updatable_directive_test.rs index d5dc3209f6052..67392e904a92b 100644 --- a/compiler/crates/relay-transforms/tests/updatable_directive_test.rs +++ b/compiler/crates/relay-transforms/tests/updatable_directive_test.rs @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ mod updatable_directive; @@ -124,6 +124,20 @@ fn non_assignable_fragment_spreads_invalid() { test_fixture(transform_fixture, "non-assignable-fragment-spreads.invalid.graphql", "updatable_directive/fixtures/non-assignable-fragment-spreads.invalid.expected", input, expected); } +#[test] +fn resolver_linked_invalid() { + let input = include_str!("updatable_directive/fixtures/resolver-linked.invalid.graphql"); + let expected = include_str!("updatable_directive/fixtures/resolver-linked.invalid.expected"); + test_fixture(transform_fixture, "resolver-linked.invalid.graphql", "updatable_directive/fixtures/resolver-linked.invalid.expected", input, expected); +} + +#[test] +fn resolver_scalar_invalid() { + let input = include_str!("updatable_directive/fixtures/resolver-scalar.invalid.graphql"); + let expected = include_str!("updatable_directive/fixtures/resolver-scalar.invalid.expected"); + test_fixture(transform_fixture, "resolver-scalar.invalid.graphql", "updatable_directive/fixtures/resolver-scalar.invalid.expected", input, expected); +} + #[test] fn skip_invalid() { let input = include_str!("updatable_directive/fixtures/skip.invalid.graphql");