Skip to content

Commit

Permalink
[JSONSelection] Support -> method syntax for inline data transforms (
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn authored Aug 27, 2024
1 parent c68d56a commit 2e56be0
Show file tree
Hide file tree
Showing 57 changed files with 4,931 additions and 1,301 deletions.
98 changes: 67 additions & 31 deletions apollo-federation/src/sources/connect/expand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ mod helpers {
use crate::schema::position::TypeDefinitionPosition;
use crate::schema::FederationSchema;
use crate::schema::ValidFederationSchema;
use crate::sources::connect::json_selection::ExtractParameters;
use crate::sources::connect::json_selection::StaticParameter;
use crate::sources::connect::json_selection::KnownVariable;
use crate::sources::connect::url_template::Parameter;
use crate::sources::connect::ConnectSpecDefinition;
use crate::sources::connect::Connector;
Expand Down Expand Up @@ -514,6 +513,10 @@ mod helpers {
}
}

Parameter::Config { item: _, paths: _ } => {
// TODO Implement $config handling
}

// All sibling fields marked by $this in a transport must be carried over to the output type
// regardless of its use in the output selection.
Parameter::Sibling { field, paths } => {
Expand Down Expand Up @@ -799,36 +802,69 @@ mod helpers {
fn extract_params_from_body(
connector: &Connector,
) -> Result<HashSet<Parameter>, FederationError> {
let body_parameters = connector
.transport
.body
.as_ref()
.and_then(JSONSelection::extract_parameters)
.unwrap_or_default();

body_parameters
.iter()
.map(|StaticParameter { name, paths }| {
let mut parts = paths.iter();
let field = parts.next().ok_or(FederationError::internal(
"expected parameter in JSONSelection to contain a field",
))?;

match *name {
"$args" => Ok(Parameter::Argument {
argument: field,
paths: parts.copied().collect(),
}),
"$this" => Ok(Parameter::Sibling {
field,
paths: parts.copied().collect(),
}),
other => Err(FederationError::internal(format!(
"got unsupported parameter: {other}"
))),
let Some(body) = &connector.transport.body else {
return Ok(HashSet::default());
};

use crate::sources::connect::json_selection::ExternalVarPaths;
let var_paths = body.external_var_paths();

let mut results = HashSet::with_capacity_and_hasher(var_paths.len(), Default::default());

for var_path in var_paths {
match var_path.var_name_and_nested_keys() {
Some((KnownVariable::Args, keys)) => {
let mut keys_iter = keys.into_iter();
let first_key = keys_iter.next().ok_or(FederationError::internal(
"expected at least one key in $args",
))?;
results.insert(Parameter::Argument {
argument: first_key,
paths: keys_iter.collect(),
});
}
Some((KnownVariable::This, keys)) => {
let mut keys_iter = keys.into_iter();
let first_key = keys_iter.next().ok_or(FederationError::internal(
"expected at least one key in $this",
))?;
results.insert(Parameter::Sibling {
field: first_key,
paths: keys_iter.collect(),
});
}
})
.collect::<Result<HashSet<_>, _>>()
Some((KnownVariable::Config, keys)) => {
let mut keys_iter = keys.into_iter();
let first_key = keys_iter.next().ok_or(FederationError::internal(
"expected at least one key in $config",
))?;
results.insert(Parameter::Config {
item: first_key,
paths: keys_iter.collect(),
});
}
// To get the safety benefits of the KnownVariable enum, we need
// to enumerate all the cases explicitly, without wildcard
// matches. However, body.external_var_paths() only returns free
// (externally-provided) variables like $this, $args, and
// $config. The $ and @ variables, by contrast, are always bound
// to something within the input data.
Some((kv @ KnownVariable::Dollar, _)) | Some((kv @ KnownVariable::AtSign, _)) => {
return Err(FederationError::internal(format!(
"got unexpected non-external variable: {:?}",
kv,
)));
}
None => {
return Err(FederationError::internal(format!(
"could not extract variable from path: {:?}",
var_path,
)));
}
};
}

Ok(results)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ expression: connectors.by_service_name
body: None,
},
selection: Path(
Var(
"$",
Empty,
),
PathSelection {
path: Var(
$,
Empty,
),
},
),
config: None,
max_requests: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,17 @@ expression: connectors.by_service_name
Alias {
name: "emailDomain",
},
Var(
"$args",
Key(
Field(
"email",
PathSelection {
path: Var(
$args,
Key(
Field(
"email",
),
Empty,
),
Empty,
),
),
},
),
],
star: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,17 @@ expression: connectors.by_service_name
Alias {
name: "with_b",
},
Var(
"$this",
Key(
Field(
"b",
PathSelection {
path: Var(
$this,
Key(
Field(
"b",
),
Empty,
),
Empty,
),
),
},
),
],
star: None,
Expand All @@ -226,10 +228,12 @@ expression: connectors.by_service_name
),
},
selection: Path(
Var(
"$",
Empty,
),
PathSelection {
path: Var(
$,
Empty,
),
},
),
config: None,
max_requests: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,17 @@ expression: connectors.by_service_name
body: None,
},
selection: Path(
Var(
"$",
Key(
Field(
"phone",
PathSelection {
path: Var(
$,
Key(
Field(
"phone",
),
Empty,
),
Empty,
),
),
},
),
config: None,
max_requests: None,
Expand Down
Loading

0 comments on commit 2e56be0

Please sign in to comment.