diff --git a/apollo-federation/src/sources/connect/spec/mod.rs b/apollo-federation/src/sources/connect/spec/mod.rs index 127e4f4edd..e975f198b1 100644 --- a/apollo-federation/src/sources/connect/spec/mod.rs +++ b/apollo-federation/src/sources/connect/spec/mod.rs @@ -30,6 +30,7 @@ pub(crate) use directives::extract_connect_directive_arguments; pub(crate) use directives::extract_source_directive_arguments; pub(crate) use schema::ConnectHTTPArguments; pub(crate) use schema::SourceHTTPArguments; +use strum_macros::EnumIter; use self::schema::CONNECT_DIRECTIVE_NAME_IN_SPEC; use self::schema::SOURCE_DIRECTIVE_NAME_IN_SPEC; @@ -43,13 +44,13 @@ use crate::link::Link; use crate::schema::FederationSchema; /// The known versions of the connect spec -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, EnumIter)] pub enum ConnectSpec { V0_1, } impl ConnectSpec { - pub const fn as_str(&self) -> &'static str { + pub const fn as_str(self) -> &'static str { match self { Self::V0_1 => "0.1", } diff --git a/apollo-federation/src/sources/connect/validation/mod.rs b/apollo-federation/src/sources/connect/validation/mod.rs index 8cf5beb103..07717e668a 100644 --- a/apollo-federation/src/sources/connect/validation/mod.rs +++ b/apollo-federation/src/sources/connect/validation/mod.rs @@ -50,6 +50,7 @@ use entity::EntityKeyChecker; use extended_type::validate_extended_type; use itertools::Itertools; use source_name::SourceName; +use strum::IntoEnumIterator; use strum_macros::Display; use strum_macros::IntoStaticStr; use url::Url; @@ -110,6 +111,32 @@ pub fn validate(source_text: &str, file_name: &str) -> ValidationResult { }; }; + if let Err(err) = ConnectSpec::try_from(&link.url.version) { + let available_versions = ConnectSpec::iter().map(ConnectSpec::as_str).collect_vec(); + let message = if available_versions.len() == 1 { + // TODO: No need to branch here once multiple spec versions are available + format!("{err}; should be {version}.", version = ConnectSpec::V0_1) + } else { + // This won't happen today, but it's prepping for 0.2 so we don't forget + format!( + "{err}; should be one of {available_versions}.", + available_versions = available_versions.join(", "), + ) + }; + return ValidationResult { + errors: vec![Message { + code: Code::UnknownConnectorsVersion, + message, + locations: link_directive + .line_column_range(&schema.sources) + .into_iter() + .collect(), + }], + has_connectors: true, + schema, + }; + } + let federation = Link::for_identity(&schema, &Identity::federation_identity()); let external_directive_name = federation .map(|(link, _)| link.directive_name_in_schema(&EXTERNAL_DIRECTIVE_NAME)) @@ -609,6 +636,8 @@ pub enum Code { UnsupportedVariableType, /// A variable is nullable in a location which requires non-null at runtime NullabilityMismatch, + /// The version set in the connectors `@link` URL is not recognized + UnknownConnectorsVersion, } impl Code { diff --git a/apollo-federation/src/sources/connect/validation/snapshots/validation_tests@connect_spec_version_error.graphql.snap b/apollo-federation/src/sources/connect/validation/snapshots/validation_tests@connect_spec_version_error.graphql.snap new file mode 100644 index 0000000000..197484540c --- /dev/null +++ b/apollo-federation/src/sources/connect/validation/snapshots/validation_tests@connect_spec_version_error.graphql.snap @@ -0,0 +1,14 @@ +--- +source: apollo-federation/src/sources/connect/validation/mod.rs +expression: "format!(\"{:#?}\", result.errors)" +input_file: apollo-federation/src/sources/connect/validation/test_data/connect_spec_version_error.graphql +--- +[ + Message { + code: UnknownConnectorsVersion, + message: "Unknown connect version: 0.2; should be 0.1.", + locations: [ + 2:3..5:4, + ], + }, +] diff --git a/apollo-federation/src/sources/connect/validation/test_data/connect_spec_version_error.graphql b/apollo-federation/src/sources/connect/validation/test_data/connect_spec_version_error.graphql new file mode 100644 index 0000000000..e2f13cf81f --- /dev/null +++ b/apollo-federation/src/sources/connect/validation/test_data/connect_spec_version_error.graphql @@ -0,0 +1,6 @@ +extend schema + @link( + url: "https://specs.apollo.dev/connect/v0.2" + import: ["@connect", "@source"] + ) +