mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-11 10:46:25 +03:00
Argument presets for DataConnectorLink Pt. 2 (#675)
## Description This PR implements argument presets for `DataConnectorLink`, which can be used to forward request headers as function/procedure arguments to NDC. This PR implements the execution part. **Note**: response header forwarding is not implemented yet. V3_GIT_ORIGIN_REV_ID: ff69129aee3e3052367ca42acdec3922cbc2cb0c
This commit is contained in:
parent
d090331be2
commit
8bc5c01961
1
v3/Cargo.lock
generated
1
v3/Cargo.lock
generated
@ -725,6 +725,7 @@ dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"ndc-models",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
@ -20,6 +20,7 @@ indexmap = "2"
|
||||
ndc-models = { git = "https://github.com/hasura/ndc-spec.git", rev = "622c643b4f0b6bbe4601c0f065d6d93a4bd3e9db" }
|
||||
regex = "1"
|
||||
serde_json = "1"
|
||||
serde = "1"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
||||
[lints]
|
||||
|
@ -5,6 +5,7 @@ use ndc_models;
|
||||
|
||||
use crate::{query::Result, state::AppState};
|
||||
|
||||
pub mod login;
|
||||
pub mod noop_procedure;
|
||||
pub mod update_actor_name_by_id;
|
||||
pub mod uppercase_actor_name_by_id;
|
||||
@ -16,6 +17,7 @@ pub(crate) fn get_procedures() -> Vec<ndc_models::ProcedureInfo> {
|
||||
vec![
|
||||
upsert_actor::procedure_info(),
|
||||
update_actor_name_by_id::procedure_info(),
|
||||
login::procedure_info(),
|
||||
noop_procedure::procedure_info(),
|
||||
// TODO: Looks like the other procedures where never added to the schema?
|
||||
]
|
||||
@ -42,6 +44,7 @@ pub(crate) fn execute_procedure(
|
||||
"uppercase_all_actor_names_return_names_list" => {
|
||||
uppercase_all_actor_names_return_names_list::execute(state)
|
||||
}
|
||||
"login" => login::execute(arguments),
|
||||
"noop_procedure" => noop_procedure::execute(),
|
||||
_ => Err((
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
90
v3/crates/custom-connector/src/procedures/login.rs
Normal file
90
v3/crates/custom-connector/src/procedures/login.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use axum::{http::StatusCode, Json};
|
||||
use ndc_models;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::{
|
||||
query::Result,
|
||||
types::login::{LoginResponse, ResponseHeaders},
|
||||
};
|
||||
|
||||
pub(crate) fn procedure_info() -> ndc_models::ProcedureInfo {
|
||||
ndc_models::ProcedureInfo {
|
||||
name: "login".into(),
|
||||
description: Some("Perform a user login".into()),
|
||||
arguments: BTreeMap::from_iter([
|
||||
(
|
||||
"headers".into(),
|
||||
ndc_models::ArgumentInfo {
|
||||
description: Some("headers required for authentication".into()),
|
||||
argument_type: ndc_models::Type::Named {
|
||||
name: "HeaderMap".into(),
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
"username".into(),
|
||||
ndc_models::ArgumentInfo {
|
||||
description: Some("username of the user".into()),
|
||||
argument_type: ndc_models::Type::Named {
|
||||
name: "String".into(),
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
"password".into(),
|
||||
ndc_models::ArgumentInfo {
|
||||
description: Some("password of the user".into()),
|
||||
argument_type: ndc_models::Type::Named {
|
||||
name: "String".into(),
|
||||
},
|
||||
},
|
||||
),
|
||||
]),
|
||||
result_type: ndc_models::Type::Named {
|
||||
name: "login_response".into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn execute(
|
||||
arguments: &BTreeMap<String, serde_json::Value>,
|
||||
) -> Result<serde_json::Value> {
|
||||
let _headers = arguments.get("headers").ok_or((
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ndc_models::ErrorResponse {
|
||||
message: "required argument field 'headers' is missing".into(),
|
||||
details: serde_json::Value::Null,
|
||||
}),
|
||||
))?;
|
||||
let _username = arguments.get("username").ok_or((
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ndc_models::ErrorResponse {
|
||||
message: "required argument field 'username' is missing".into(),
|
||||
details: serde_json::Value::Null,
|
||||
}),
|
||||
))?;
|
||||
let _password = arguments.get("password").ok_or((
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ndc_models::ErrorResponse {
|
||||
message: "required argument field 'password' is missing".into(),
|
||||
details: serde_json::Value::Null,
|
||||
}),
|
||||
))?;
|
||||
|
||||
let login_response = LoginResponse {
|
||||
response: true,
|
||||
headers: ResponseHeaders {
|
||||
cookie: "Set-Cookie: cookie_name=cookie_val;".to_string(),
|
||||
session_token: "abcdefghi".to_string(),
|
||||
},
|
||||
};
|
||||
serde_json::to_value(login_response).map_err(|_| {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(ndc_models::ErrorResponse {
|
||||
message: "cannot encode response".into(),
|
||||
details: serde_json::Value::Null,
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
@ -4,6 +4,7 @@ use std::collections::BTreeMap;
|
||||
pub mod actor;
|
||||
pub mod institution;
|
||||
pub mod location;
|
||||
pub mod login;
|
||||
pub mod name_query;
|
||||
pub mod staff_member;
|
||||
|
||||
@ -53,6 +54,21 @@ pub(crate) fn scalar_types() -> BTreeMap<String, ndc_models::ScalarType> {
|
||||
comparison_operators: BTreeMap::from_iter([]),
|
||||
},
|
||||
),
|
||||
(
|
||||
"Bool".into(),
|
||||
ndc_models::ScalarType {
|
||||
representation: Some(ndc_models::TypeRepresentation::Boolean),
|
||||
aggregate_functions: BTreeMap::new(),
|
||||
comparison_operators: BTreeMap::from_iter([(
|
||||
"eq".into(),
|
||||
ndc_models::ComparisonOperatorDefinition::Custom {
|
||||
argument_type: ndc_models::Type::Named {
|
||||
name: "Bool".into(),
|
||||
},
|
||||
},
|
||||
)]),
|
||||
},
|
||||
),
|
||||
(
|
||||
"Actor_Name".into(),
|
||||
ndc_models::ScalarType {
|
||||
@ -61,6 +77,14 @@ pub(crate) fn scalar_types() -> BTreeMap<String, ndc_models::ScalarType> {
|
||||
comparison_operators: BTreeMap::new(),
|
||||
},
|
||||
),
|
||||
(
|
||||
"HeaderMap".into(),
|
||||
ndc_models::ScalarType {
|
||||
representation: Some(ndc_models::TypeRepresentation::JSON),
|
||||
aggregate_functions: BTreeMap::new(),
|
||||
comparison_operators: BTreeMap::new(),
|
||||
},
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
@ -104,5 +128,6 @@ pub(crate) fn object_types() -> BTreeMap<String, ndc_models::ObjectType> {
|
||||
("institution".into(), institution::definition()),
|
||||
("location".into(), location::definition()),
|
||||
("staff_member".into(), staff_member::definition()),
|
||||
("login_response".into(), login::definition()),
|
||||
])
|
||||
}
|
||||
|
43
v3/crates/custom-connector/src/types/login.rs
Normal file
43
v3/crates/custom-connector/src/types/login.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use ndc_models;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LoginResponse {
|
||||
pub headers: ResponseHeaders,
|
||||
pub response: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ResponseHeaders {
|
||||
pub cookie: String,
|
||||
pub session_token: String,
|
||||
}
|
||||
|
||||
pub(crate) fn definition() -> ndc_models::ObjectType {
|
||||
ndc_models::ObjectType {
|
||||
description: Some("Response to a login action".into()),
|
||||
fields: BTreeMap::from_iter([
|
||||
(
|
||||
"headers".into(),
|
||||
ndc_models::ObjectField {
|
||||
description: Some("Response headers to be forwarded".into()),
|
||||
r#type: ndc_models::Type::Named {
|
||||
name: "HeaderMap".into(),
|
||||
},
|
||||
arguments: BTreeMap::new(),
|
||||
},
|
||||
),
|
||||
(
|
||||
"response".into(),
|
||||
ndc_models::ObjectField {
|
||||
description: Some("Authentication successful or not".into()),
|
||||
r#type: ndc_models::Type::Named {
|
||||
name: "Bool".into(),
|
||||
},
|
||||
arguments: BTreeMap::new(),
|
||||
},
|
||||
),
|
||||
]),
|
||||
}
|
||||
}
|
@ -62,6 +62,7 @@ pub fn bench_execute(
|
||||
variables: None,
|
||||
};
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session = Identity::admin(Role::new("admin"))
|
||||
.get_role_authorization(None)
|
||||
.unwrap()
|
||||
@ -127,12 +128,13 @@ pub fn bench_execute(
|
||||
BenchmarkId::new("bench_execute", "Generate IR"),
|
||||
&(&runtime, &schema),
|
||||
|b, (runtime, schema)| {
|
||||
b.to_async(*runtime)
|
||||
.iter(|| async { generate_ir(schema, &session, &normalized_request).unwrap() })
|
||||
b.to_async(*runtime).iter(|| async {
|
||||
generate_ir(schema, &session, &request_headers, &normalized_request).unwrap()
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let ir = generate_ir(&schema, &session, &normalized_request).unwrap();
|
||||
let ir = generate_ir(&schema, &session, &request_headers, &normalized_request).unwrap();
|
||||
|
||||
// Generate Query Plan
|
||||
group.bench_with_input(
|
||||
@ -168,9 +170,16 @@ pub fn bench_execute(
|
||||
&(&runtime, &schema, raw_request),
|
||||
|b, (runtime, schema, request)| {
|
||||
b.to_async(*runtime).iter(|| async {
|
||||
execute_query_internal(&http_context, schema, &session, request.clone(), None)
|
||||
.await
|
||||
.unwrap()
|
||||
execute_query_internal(
|
||||
&http_context,
|
||||
schema,
|
||||
&session,
|
||||
&request_headers,
|
||||
request.clone(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
})
|
||||
},
|
||||
);
|
||||
|
@ -475,6 +475,7 @@ async fn graphiql() -> Html<&'static str> {
|
||||
}
|
||||
|
||||
async fn handle_request(
|
||||
headers: axum::http::header::HeaderMap,
|
||||
State(state): State<Arc<EngineState>>,
|
||||
Extension(session): Extension<Session>,
|
||||
Json(request): Json<gql::http::RawRequest>,
|
||||
@ -490,6 +491,7 @@ async fn handle_request(
|
||||
&state.http_context,
|
||||
&state.schema,
|
||||
&session,
|
||||
&headers,
|
||||
request,
|
||||
None,
|
||||
))
|
||||
@ -508,6 +510,7 @@ async fn handle_request(
|
||||
}
|
||||
|
||||
async fn handle_explain_request(
|
||||
headers: axum::http::header::HeaderMap,
|
||||
State(state): State<Arc<EngineState>>,
|
||||
Extension(session): Extension<Session>,
|
||||
Json(request): Json<gql::http::RawRequest>,
|
||||
@ -523,6 +526,7 @@ async fn handle_explain_request(
|
||||
&state.http_context,
|
||||
&state.schema,
|
||||
&session,
|
||||
&headers,
|
||||
request,
|
||||
))
|
||||
},
|
||||
|
@ -89,6 +89,7 @@ pub fn test_execution_expectation_legacy(
|
||||
|
||||
let query = fs::read_to_string(request_path)?;
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session = {
|
||||
let session_vars_path = &test_path.join("session_variables.json");
|
||||
let session_variables: HashMap<SessionVariable, SessionVariableValue> =
|
||||
@ -104,8 +105,15 @@ pub fn test_execution_expectation_legacy(
|
||||
|
||||
// Execute the test
|
||||
|
||||
let response =
|
||||
execute_query(&test_ctx.http_context, &schema, &session, raw_request, None).await;
|
||||
let response = execute_query(
|
||||
&test_ctx.http_context,
|
||||
&schema,
|
||||
&session,
|
||||
&request_headers,
|
||||
raw_request,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut expected = test_ctx.mint.new_goldenfile_with_differ(
|
||||
response_path,
|
||||
@ -174,6 +182,7 @@ pub(crate) fn test_introspection_expectation(
|
||||
|
||||
let query = fs::read_to_string(request_path)?;
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session_vars_path = &test_path.join("session_variables.json");
|
||||
let sessions: Vec<HashMap<SessionVariable, SessionVariableValue>> =
|
||||
json::from_str(fs::read_to_string(session_vars_path)?.as_ref())?;
|
||||
@ -200,6 +209,7 @@ pub(crate) fn test_introspection_expectation(
|
||||
&test_ctx.http_context,
|
||||
&schema,
|
||||
session,
|
||||
&request_headers,
|
||||
raw_request.clone(),
|
||||
None,
|
||||
)
|
||||
@ -289,6 +299,7 @@ pub fn test_execution_expectation(
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session_vars_path = &test_path.join("session_variables.json");
|
||||
let sessions: Vec<HashMap<SessionVariable, SessionVariableValue>> =
|
||||
json::from_str(fs::read_to_string(session_vars_path)?.as_ref())?;
|
||||
@ -317,6 +328,7 @@ pub fn test_execution_expectation(
|
||||
&test_ctx.http_context,
|
||||
&schema,
|
||||
session,
|
||||
&request_headers,
|
||||
raw_request.clone(),
|
||||
None,
|
||||
)
|
||||
@ -335,6 +347,7 @@ pub fn test_execution_expectation(
|
||||
&test_ctx.http_context,
|
||||
&schema,
|
||||
session,
|
||||
&request_headers,
|
||||
raw_request.clone(),
|
||||
None,
|
||||
)
|
||||
@ -403,6 +416,7 @@ pub fn test_execute_explain(
|
||||
let gds = GDS::new_with_default_flags(open_dds::traits::OpenDd::deserialize(metadata)?)?;
|
||||
|
||||
let schema = GDS::build_schema(&gds)?;
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session = {
|
||||
let session_variables_raw = r#"{
|
||||
"x-hasura-role": "admin"
|
||||
@ -417,8 +431,14 @@ pub fn test_execute_explain(
|
||||
query,
|
||||
variables: None,
|
||||
};
|
||||
let raw_response =
|
||||
execute::execute_explain(&test_ctx.http_context, &schema, &session, raw_request).await;
|
||||
let raw_response = execute::execute_explain(
|
||||
&test_ctx.http_context,
|
||||
&schema,
|
||||
&session,
|
||||
&request_headers,
|
||||
raw_request,
|
||||
)
|
||||
.await;
|
||||
|
||||
let response = execute::redact_ndc_explain(raw_response);
|
||||
|
||||
|
@ -64,6 +64,28 @@
|
||||
"type": "custom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Bool": {
|
||||
"representation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"aggregate_functions": {},
|
||||
"comparison_operators": {
|
||||
"eq": {
|
||||
"type": "custom",
|
||||
"argument_type": {
|
||||
"type": "named",
|
||||
"name": "Bool"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"HeaderMap": {
|
||||
"representation": {
|
||||
"type": "json"
|
||||
},
|
||||
"aggregate_functions": {},
|
||||
"comparison_operators": {}
|
||||
}
|
||||
},
|
||||
"object_types": {
|
||||
@ -254,6 +276,25 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"login_response": {
|
||||
"description": "Response to a login action",
|
||||
"fields": {
|
||||
"headers": {
|
||||
"description": "Response headers to be forwarded",
|
||||
"type": {
|
||||
"type": "named",
|
||||
"name": "HeaderMap"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"description": "Authentication successful or not",
|
||||
"type": {
|
||||
"type": "named",
|
||||
"name": "Bool"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"collections": [
|
||||
@ -666,6 +707,37 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "login",
|
||||
"description": "Perform a user login",
|
||||
"arguments": {
|
||||
"headers": {
|
||||
"description": "headers required for authentication",
|
||||
"type": {
|
||||
"type": "named",
|
||||
"name": "HeaderMap"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"description": "password of the user",
|
||||
"type": {
|
||||
"type": "named",
|
||||
"name": "String"
|
||||
}
|
||||
},
|
||||
"username": {
|
||||
"description": "username of the user",
|
||||
"type": {
|
||||
"type": "named",
|
||||
"name": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"result_type": {
|
||||
"type": "named",
|
||||
"name": "login_response"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -24,6 +24,7 @@ pub fn bench_generate_ir(c: &mut Criterion) {
|
||||
group.sample_size(20);
|
||||
group.sampling_mode(SamplingMode::Flat);
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let session = Identity::admin(Role::new("admin"))
|
||||
.get_role_authorization(None)
|
||||
.unwrap()
|
||||
@ -61,7 +62,10 @@ pub fn bench_generate_ir(c: &mut Criterion) {
|
||||
BenchmarkId::new("generate_ir", test_name),
|
||||
&(&schema, &normalized_request),
|
||||
|b, (schema, normalized_request)| {
|
||||
b.iter(|| execute::generate_ir(schema, &session, normalized_request).unwrap())
|
||||
b.iter(|| {
|
||||
execute::generate_ir(schema, &session, &request_headers, normalized_request)
|
||||
.unwrap()
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -21,9 +21,10 @@ pub async fn execute_explain(
|
||||
http_context: &HttpContext,
|
||||
schema: &Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
request: RawRequest,
|
||||
) -> types::ExplainResponse {
|
||||
super::explain_query_internal(http_context, schema, session, request)
|
||||
super::explain_query_internal(http_context, schema, session, request_headers, request)
|
||||
.await
|
||||
.unwrap_or_else(|e| types::ExplainResponse::error(e.to_graphql_error()))
|
||||
}
|
||||
|
@ -16,11 +16,13 @@ use serde_json as json;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use super::arguments;
|
||||
use super::error::InternalDeveloperError;
|
||||
use super::selection_set;
|
||||
use crate::ir::error;
|
||||
use crate::ir::permissions;
|
||||
use crate::model_tracking::{count_command, UsagesCounts};
|
||||
use metadata_resolve;
|
||||
use metadata_resolve::http::SerializableHeaderMap;
|
||||
use metadata_resolve::{ConnectorArgumentName, Qualified, QualifiedTypeReference};
|
||||
use schema::ArgumentNameAndPath;
|
||||
use schema::ArgumentPresets;
|
||||
@ -87,6 +89,7 @@ pub(crate) fn generate_command_info<'n, 's>(
|
||||
result_base_type_kind: TypeKind,
|
||||
command_source: &'s CommandSourceDetail,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<CommandInfo<'s>, error::Error> {
|
||||
let mut command_arguments = BTreeMap::new();
|
||||
@ -100,7 +103,8 @@ pub(crate) fn generate_command_info<'n, 's>(
|
||||
command_arguments.insert(ndc_arg_name, ndc_val);
|
||||
}
|
||||
|
||||
// fetch argument presets from namespace annotation
|
||||
// preset arguments from permissions presets (both command permission argument
|
||||
// presets and input field presets)
|
||||
if let Some(ArgumentPresets { argument_presets }) =
|
||||
permissions::get_argument_presets(field_call.info.namespaced)?
|
||||
{
|
||||
@ -148,6 +152,48 @@ pub(crate) fn generate_command_info<'n, 's>(
|
||||
}
|
||||
}
|
||||
|
||||
// preset arguments from `DataConnectorLink` argument presets
|
||||
for dc_argument_preset in &command_source.data_connector.argument_presets {
|
||||
let mut headers_argument = reqwest::header::HeaderMap::new();
|
||||
|
||||
// add headers from the request to be forwarded
|
||||
for header_name in &dc_argument_preset.value.http_headers.forward {
|
||||
if let Some(header_value) = request_headers.get(&header_name.0) {
|
||||
headers_argument.insert(header_name.0.clone(), header_value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// add additional headers from `ValueExpression`
|
||||
for (header_name, value_expression) in &dc_argument_preset.value.http_headers.additional {
|
||||
// TODO: have helper functions to create types
|
||||
let string_type = QualifiedTypeReference {
|
||||
nullable: false,
|
||||
underlying_type: metadata_resolve::QualifiedBaseType::Named(
|
||||
metadata_resolve::QualifiedTypeName::Inbuilt(
|
||||
open_dds::types::InbuiltType::String,
|
||||
),
|
||||
),
|
||||
};
|
||||
let value = permissions::make_value_from_value_expression(
|
||||
value_expression,
|
||||
&string_type,
|
||||
session_variables,
|
||||
usage_counts,
|
||||
)?;
|
||||
let header_value =
|
||||
reqwest::header::HeaderValue::from_str(serde_json::to_string(&value)?.as_str())
|
||||
.map_err(|_e| {
|
||||
InternalDeveloperError::UnableToConvertValueExpressionToHeaderValue
|
||||
})?;
|
||||
headers_argument.insert(header_name.0.clone(), header_value);
|
||||
}
|
||||
|
||||
command_arguments.insert(
|
||||
dc_argument_preset.name.to_string(),
|
||||
serde_json::to_value(SerializableHeaderMap(headers_argument))?,
|
||||
);
|
||||
}
|
||||
|
||||
// Add the name of the root command
|
||||
let mut usage_counts = UsagesCounts::new();
|
||||
count_command(command_name, &mut usage_counts);
|
||||
@ -159,6 +205,7 @@ pub(crate) fn generate_command_info<'n, 's>(
|
||||
&command_source.data_connector,
|
||||
&command_source.type_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
||||
@ -183,6 +230,7 @@ pub(crate) fn generate_function_based_command<'n, 's>(
|
||||
result_base_type_kind: TypeKind,
|
||||
command_source: &'s CommandSourceDetail,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FunctionBasedCommand<'s>, error::Error> {
|
||||
let command_info = generate_command_info(
|
||||
@ -193,6 +241,7 @@ pub(crate) fn generate_function_based_command<'n, 's>(
|
||||
result_base_type_kind,
|
||||
command_source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
|
||||
@ -213,6 +262,7 @@ pub(crate) fn generate_procedure_based_command<'n, 's>(
|
||||
result_base_type_kind: TypeKind,
|
||||
command_source: &'s CommandSourceDetail,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<ProcedureBasedCommand<'s>, error::Error> {
|
||||
let mut usage_counts = UsagesCounts::new();
|
||||
|
||||
@ -224,6 +274,7 @@ pub(crate) fn generate_procedure_based_command<'n, 's>(
|
||||
result_base_type_kind,
|
||||
command_source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
||||
|
@ -150,6 +150,9 @@ pub enum InternalDeveloperError {
|
||||
argument_name: ArgumentName,
|
||||
},
|
||||
|
||||
#[error("The value expression could not be converted to header value. Error: ")]
|
||||
UnableToConvertValueExpressionToHeaderValue,
|
||||
|
||||
// we'll be adding them shortly, and not advertising the feature until they are complete
|
||||
// however temporarily emitting the error allows merging the work in chunks
|
||||
#[error("boolean expressions not implemented")]
|
||||
|
@ -58,6 +58,7 @@ pub(crate) fn model_selection_ir<'s>(
|
||||
offset: Option<u32>,
|
||||
order_by: Option<ResolvedOrderBy<'s>>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<ModelSelection<'s>, error::Error> {
|
||||
match permissions_predicate {
|
||||
@ -98,6 +99,7 @@ pub(crate) fn model_selection_ir<'s>(
|
||||
&model_source.type_mappings,
|
||||
field_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
|
||||
|
@ -17,6 +17,7 @@ use schema::{OutputAnnotation, RootFieldAnnotation};
|
||||
pub fn generate_ir<'n, 's>(
|
||||
selection_set: &'s gql::normalized_ast::SelectionSet<'s, GDS>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<IndexMap<ast::Alias, root_field::RootField<'n, 's>>, error::Error> {
|
||||
let tracer = tracing_util::global_tracer();
|
||||
tracer.in_span(
|
||||
@ -70,6 +71,7 @@ pub fn generate_ir<'n, 's>(
|
||||
*result_base_type_kind,
|
||||
source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ pub mod select_one;
|
||||
pub fn generate_ir<'n, 's>(
|
||||
schema: &'s gql::schema::Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
selection_set: &'s gql::normalized_ast::SelectionSet<'s, GDS>,
|
||||
) -> Result<IndexMap<ast::Alias, root_field::RootField<'n, 's>>, error::Error> {
|
||||
let type_name = selection_set
|
||||
@ -62,7 +63,14 @@ pub fn generate_ir<'n, 's>(
|
||||
name: model_name,
|
||||
} => {
|
||||
let ir = generate_model_rootfield_ir(
|
||||
&type_name, source, data_type, kind, field, field_call, session,
|
||||
&type_name,
|
||||
source,
|
||||
data_type,
|
||||
kind,
|
||||
field,
|
||||
field_call,
|
||||
session,
|
||||
request_headers,
|
||||
model_name,
|
||||
)?;
|
||||
Ok(ir)
|
||||
@ -84,6 +92,7 @@ pub fn generate_ir<'n, 's>(
|
||||
field,
|
||||
field_call,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
)?;
|
||||
Ok(ir)
|
||||
}
|
||||
@ -93,6 +102,7 @@ pub fn generate_ir<'n, 's>(
|
||||
field_call,
|
||||
typename_mappings,
|
||||
session,
|
||||
request_headers,
|
||||
)?;
|
||||
Ok(ir)
|
||||
}
|
||||
@ -104,6 +114,7 @@ pub fn generate_ir<'n, 's>(
|
||||
field_call,
|
||||
typename_mappings,
|
||||
session,
|
||||
request_headers,
|
||||
)?;
|
||||
Ok(ir)
|
||||
}
|
||||
@ -173,6 +184,7 @@ fn generate_model_rootfield_ir<'n, 's>(
|
||||
field: &'n gql::normalized_ast::Field<'s, GDS>,
|
||||
field_call: &'s gql::normalized_ast::FieldCall<'s, GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
model_name: &'s metadata_resolve::Qualified<models::ModelName>,
|
||||
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
|
||||
let source =
|
||||
@ -191,6 +203,7 @@ fn generate_model_rootfield_ir<'n, 's>(
|
||||
data_type,
|
||||
source,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
model_name,
|
||||
)?,
|
||||
},
|
||||
@ -202,6 +215,7 @@ fn generate_model_rootfield_ir<'n, 's>(
|
||||
data_type,
|
||||
source,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
model_name,
|
||||
)?,
|
||||
},
|
||||
@ -219,6 +233,7 @@ fn generate_command_rootfield_ir<'n, 's>(
|
||||
field: &'n gql::normalized_ast::Field<'s, GDS>,
|
||||
field_call: &'s gql::normalized_ast::FieldCall<'s, GDS>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
|
||||
let mut usage_counts = UsagesCounts::new();
|
||||
let source =
|
||||
@ -247,6 +262,7 @@ fn generate_command_rootfield_ir<'n, 's>(
|
||||
*result_base_type_kind,
|
||||
source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
&mut usage_counts,
|
||||
)?,
|
||||
};
|
||||
@ -258,12 +274,14 @@ fn generate_nodefield_ir<'n, 's>(
|
||||
field_call: &'n gql::normalized_ast::FieldCall<'s, GDS>,
|
||||
typename_mappings: &'s HashMap<ast::TypeName, NodeFieldTypeNameMapping>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
|
||||
let ir = root_field::QueryRootField::NodeSelect(node_field::relay_node_ir(
|
||||
field,
|
||||
field_call,
|
||||
typename_mappings,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
)?);
|
||||
Ok(ir)
|
||||
}
|
||||
@ -273,6 +291,7 @@ fn generate_entities_ir<'n, 's>(
|
||||
field_call: &'n gql::normalized_ast::FieldCall<'s, GDS>,
|
||||
typename_mappings: &'s HashMap<ast::TypeName, EntityFieldTypeNameMapping>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
|
||||
let ir = root_field::QueryRootField::ApolloFederation(
|
||||
root_field::ApolloFederationRootFields::EntitiesSelect(apollo_federation::entities_ir(
|
||||
@ -280,6 +299,7 @@ fn generate_entities_ir<'n, 's>(
|
||||
field_call,
|
||||
typename_mappings,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
)?),
|
||||
);
|
||||
Ok(ir)
|
||||
|
@ -80,6 +80,7 @@ pub(crate) fn entities_ir<'n, 's>(
|
||||
field_call: &'n normalized_ast::FieldCall<'s, GDS>,
|
||||
typename_mappings: &'s HashMap<ast::TypeName, EntityFieldTypeNameMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<Vec<EntitySelect<'n, 's>>, error::Error> {
|
||||
let representations = field_call
|
||||
.expected_argument(&lang_graphql::mk_name!("representations"))?
|
||||
@ -178,6 +179,7 @@ pub(crate) fn entities_ir<'n, 's>(
|
||||
None, // offset
|
||||
None, // order_by
|
||||
session_variables,
|
||||
request_headers,
|
||||
// Get all the models/commands that were used as relationships
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
@ -77,6 +77,7 @@ pub(crate) fn relay_node_ir<'n, 's>(
|
||||
field_call: &'n normalized_ast::FieldCall<'s, GDS>,
|
||||
typename_mappings: &'s HashMap<ast::TypeName, NodeFieldTypeNameMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
) -> Result<Option<NodeSelect<'n, 's>>, error::Error> {
|
||||
let id_arg_value = field_call
|
||||
.expected_argument(&lang_graphql::mk_name!("id"))?
|
||||
@ -161,6 +162,7 @@ pub(crate) fn relay_node_ir<'n, 's>(
|
||||
None, // offset
|
||||
None, // order_by
|
||||
session_variables,
|
||||
request_headers,
|
||||
// Get all the models/commands that were used as relationships
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
@ -47,6 +47,7 @@ pub(crate) fn select_many_generate_ir<'n, 's>(
|
||||
data_type: &Qualified<open_dds::types::CustomTypeName>,
|
||||
model_source: &'s metadata_resolve::ModelSource,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
model_name: &'s Qualified<open_dds::models::ModelName>,
|
||||
) -> Result<ModelSelectMany<'n, 's>, error::Error> {
|
||||
let mut limit = None;
|
||||
@ -153,6 +154,7 @@ pub(crate) fn select_many_generate_ir<'n, 's>(
|
||||
offset,
|
||||
order_by,
|
||||
session_variables,
|
||||
request_headers,
|
||||
// Get all the models/commands that were used as relationships
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
@ -47,6 +47,7 @@ pub(crate) fn select_one_generate_ir<'n, 's>(
|
||||
data_type: &Qualified<open_dds::types::CustomTypeName>,
|
||||
model_source: &'s metadata_resolve::ModelSource,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
model_name: &'s Qualified<open_dds::models::ModelName>,
|
||||
) -> Result<ModelSelectOne<'n, 's>, error::Error> {
|
||||
let mut filter_clause_expressions = vec![];
|
||||
@ -122,6 +123,7 @@ pub(crate) fn select_one_generate_ir<'n, 's>(
|
||||
None, // offset
|
||||
None, // order_by
|
||||
session_variables,
|
||||
request_headers,
|
||||
// Get all the models/commands that were used as relationships
|
||||
&mut usage_counts,
|
||||
)?;
|
||||
|
@ -79,6 +79,7 @@ pub(crate) fn generate_model_relationship_ir<'s>(
|
||||
source_data_connector: &'s metadata_resolve::DataConnectorLink,
|
||||
source_type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, metadata_resolve::TypeMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
// Add the target model being used in the usage counts
|
||||
@ -177,6 +178,7 @@ pub(crate) fn generate_model_relationship_ir<'s>(
|
||||
offset,
|
||||
order_by,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
),
|
||||
metadata_resolve::RelationshipExecutionCategory::RemoteForEach => {
|
||||
@ -191,6 +193,7 @@ pub(crate) fn generate_model_relationship_ir<'s>(
|
||||
offset,
|
||||
order_by,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)
|
||||
}
|
||||
@ -203,6 +206,7 @@ pub(crate) fn generate_command_relationship_ir<'s>(
|
||||
source_data_connector: &'s metadata_resolve::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, metadata_resolve::TypeMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
count_command(&annotation.command_name, usage_counts);
|
||||
@ -235,6 +239,7 @@ pub(crate) fn generate_command_relationship_ir<'s>(
|
||||
type_mappings,
|
||||
target_source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
),
|
||||
metadata_resolve::RelationshipExecutionCategory::RemoteForEach => {
|
||||
@ -245,6 +250,7 @@ pub(crate) fn generate_command_relationship_ir<'s>(
|
||||
type_mappings,
|
||||
target_source,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)
|
||||
}
|
||||
@ -264,6 +270,7 @@ pub(crate) fn build_local_model_relationship<'s>(
|
||||
offset: Option<u32>,
|
||||
order_by: Option<ResolvedOrderBy<'s>>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
let relationships_ir = model_selection_ir(
|
||||
@ -277,6 +284,7 @@ pub(crate) fn build_local_model_relationship<'s>(
|
||||
offset,
|
||||
order_by,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
let rel_info = LocalModelRelationshipInfo {
|
||||
@ -306,6 +314,7 @@ pub(crate) fn build_local_command_relationship<'s>(
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, metadata_resolve::TypeMapping>,
|
||||
target_source: &'s CommandTargetSource,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
let relationships_ir = generate_function_based_command(
|
||||
@ -317,6 +326,7 @@ pub(crate) fn build_local_command_relationship<'s>(
|
||||
annotation.target_base_type_kind,
|
||||
&target_source.details,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
|
||||
@ -353,6 +363,7 @@ pub(crate) fn build_remote_relationship<'n, 's>(
|
||||
offset: Option<u32>,
|
||||
order_by: Option<ResolvedOrderBy<'s>>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
let mut join_mapping: Vec<(SourceField, TargetField)> = vec![];
|
||||
@ -392,6 +403,7 @@ pub(crate) fn build_remote_relationship<'n, 's>(
|
||||
offset,
|
||||
order_by,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
|
||||
@ -435,6 +447,7 @@ pub(crate) fn build_remote_command_relationship<'n, 's>(
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, metadata_resolve::TypeMapping>,
|
||||
target_source: &'s CommandTargetSource,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
let mut join_mapping: Vec<(SourceField, ArgumentName)> = vec![];
|
||||
@ -462,6 +475,7 @@ pub(crate) fn build_remote_command_relationship<'n, 's>(
|
||||
annotation.target_base_type_kind,
|
||||
&target_source.details,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
|
||||
|
@ -153,6 +153,7 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
metadata_resolve::TypeMapping,
|
||||
>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<Option<NestedSelection<'s>>, error::Error> {
|
||||
match &qualified_type_reference.underlying_type {
|
||||
@ -164,6 +165,7 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
data_connector,
|
||||
type_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
Ok(array_selection.map(|a| NestedSelection::Array(Box::new(a))))
|
||||
@ -189,6 +191,7 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
type_mappings,
|
||||
field_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
Ok(Some(NestedSelection::Object(nested_selection)))
|
||||
@ -213,6 +216,7 @@ pub(crate) fn generate_selection_set_ir<'s>(
|
||||
>,
|
||||
field_mappings: &BTreeMap<FieldName, metadata_resolve::FieldMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<ResultSelectionSet<'s>, error::Error> {
|
||||
let mut fields = IndexMap::new();
|
||||
@ -237,6 +241,7 @@ pub(crate) fn generate_selection_set_ir<'s>(
|
||||
data_connector,
|
||||
type_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?;
|
||||
fields.insert(
|
||||
@ -293,6 +298,7 @@ pub(crate) fn generate_selection_set_ir<'s>(
|
||||
data_connector,
|
||||
type_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?,
|
||||
);
|
||||
@ -306,6 +312,7 @@ pub(crate) fn generate_selection_set_ir<'s>(
|
||||
data_connector,
|
||||
type_mappings,
|
||||
session_variables,
|
||||
request_headers,
|
||||
usage_counts,
|
||||
)?,
|
||||
);
|
||||
|
@ -80,12 +80,20 @@ pub async fn execute_query(
|
||||
http_context: &HttpContext,
|
||||
schema: &Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
request: RawRequest,
|
||||
project_id: Option<&ProjectId>,
|
||||
) -> GraphQLResponse {
|
||||
execute_query_internal(http_context, schema, session, request, project_id)
|
||||
.await
|
||||
.unwrap_or_else(|e| GraphQLResponse(Response::error(e.to_graphql_error())))
|
||||
execute_query_internal(
|
||||
http_context,
|
||||
schema,
|
||||
session,
|
||||
request_headers,
|
||||
request,
|
||||
project_id,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_else(|e| GraphQLResponse(Response::error(e.to_graphql_error())))
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -112,6 +120,7 @@ pub async fn execute_query_internal(
|
||||
http_context: &HttpContext,
|
||||
schema: &gql::schema::Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
raw_request: gql::http::RawRequest,
|
||||
project_id: Option<&ProjectId>,
|
||||
) -> Result<GraphQLResponse, error::RequestError> {
|
||||
@ -141,7 +150,7 @@ pub async fn execute_query_internal(
|
||||
normalize_request(schema, session, query, raw_request)?;
|
||||
|
||||
// generate IR
|
||||
let ir = build_ir(schema, session, &normalized_request)?;
|
||||
let ir = build_ir(schema, session, request_headers, &normalized_request)?;
|
||||
|
||||
// construct a plan to execute the request
|
||||
let request_plan = build_request_plan(&ir)?;
|
||||
@ -198,6 +207,7 @@ pub async fn explain_query_internal(
|
||||
http_context: &HttpContext,
|
||||
schema: &gql::schema::Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
raw_request: gql::http::RawRequest,
|
||||
) -> Result<explain::types::ExplainResponse, error::RequestError> {
|
||||
let tracer = tracing_util::global_tracer();
|
||||
@ -226,7 +236,7 @@ pub async fn explain_query_internal(
|
||||
normalize_request(schema, session, query, raw_request)?;
|
||||
|
||||
// generate IR
|
||||
let ir = build_ir(schema, session, &normalized_request)?;
|
||||
let ir = build_ir(schema, session, request_headers, &normalized_request)?;
|
||||
|
||||
// construct a plan to execute the request
|
||||
let request_plan = build_request_plan(&ir)?;
|
||||
@ -341,6 +351,7 @@ pub(crate) fn normalize_request<'s>(
|
||||
pub(crate) fn build_ir<'n, 's>(
|
||||
schema: &'s gql::schema::Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
normalized_request: &'s Operation<'s, GDS>,
|
||||
) -> Result<IndexMap<ast::Alias, ir::root_field::RootField<'n, 's>>, ir::error::Error> {
|
||||
let tracer = tracing_util::global_tracer();
|
||||
@ -348,7 +359,7 @@ pub(crate) fn build_ir<'n, 's>(
|
||||
"generate_ir",
|
||||
"Generate IR for the request",
|
||||
SpanVisibility::Internal,
|
||||
|| generate_ir(schema, session, normalized_request),
|
||||
|| generate_ir(schema, session, request_headers, normalized_request),
|
||||
)?;
|
||||
Ok(ir)
|
||||
}
|
||||
@ -370,15 +381,21 @@ pub(crate) fn build_request_plan<'n, 's, 'ir>(
|
||||
pub fn generate_ir<'n, 's>(
|
||||
schema: &'s gql::schema::Schema<GDS>,
|
||||
session: &Session,
|
||||
request_headers: &reqwest::header::HeaderMap,
|
||||
normalized_request: &'s Operation<'s, GDS>,
|
||||
) -> Result<IndexMap<ast::Alias, ir::root_field::RootField<'n, 's>>, ir::error::Error> {
|
||||
let ir = match &normalized_request.ty {
|
||||
ast::OperationType::Query => {
|
||||
ir::query_root::generate_ir(schema, session, &normalized_request.selection_set)?
|
||||
}
|
||||
ast::OperationType::Mutation => {
|
||||
ir::mutation_root::generate_ir(&normalized_request.selection_set, &session.variables)?
|
||||
}
|
||||
ast::OperationType::Query => ir::query_root::generate_ir(
|
||||
schema,
|
||||
session,
|
||||
request_headers,
|
||||
&normalized_request.selection_set,
|
||||
)?,
|
||||
ast::OperationType::Mutation => ir::mutation_root::generate_ir(
|
||||
&normalized_request.selection_set,
|
||||
&session.variables,
|
||||
request_headers,
|
||||
)?,
|
||||
ast::OperationType::Subscription => {
|
||||
Err(ir::error::InternalEngineError::SubscriptionsNotSupported)?
|
||||
}
|
||||
@ -418,6 +435,7 @@ mod tests {
|
||||
let path = input_file?.path();
|
||||
assert!(path.is_dir());
|
||||
|
||||
let request_headers = reqwest::header::HeaderMap::new();
|
||||
let test_name = path
|
||||
.file_name()
|
||||
.ok_or_else(|| format!("{path:?} is not a normal file or directory"))?;
|
||||
@ -444,7 +462,7 @@ mod tests {
|
||||
&request,
|
||||
)?;
|
||||
|
||||
let ir = generate_ir(&schema, &session, &normalized_request)?;
|
||||
let ir = generate_ir(&schema, &session, &request_headers, &normalized_request)?;
|
||||
let mut expected = mint.new_goldenfile_with_differ(
|
||||
expected_path,
|
||||
Box::new(|file1, file2| {
|
||||
|
@ -304,7 +304,8 @@ pub fn validate_ndc_command(
|
||||
|
||||
// Check if the arguments are correctly mapped
|
||||
for (open_dd_argument_name, ndc_argument_name) in &command_source.argument_mappings {
|
||||
// OpenDD command argument should not be also used in DataConnectorLink.argumentPresets
|
||||
// Arguments already used in DataConnectorLink.argumentPresets can't be
|
||||
// used as command arguments
|
||||
if dc_link_argument_presets.contains(&open_dd_argument_name) {
|
||||
return Err(
|
||||
NDCValidationError::CannotUseDataConnectorLinkArgumentPresetInCommand {
|
||||
|
@ -11,6 +11,7 @@ mod helpers;
|
||||
mod stages;
|
||||
mod types;
|
||||
|
||||
pub use helpers::http;
|
||||
pub use helpers::ndc_validation::NDCValidationError;
|
||||
pub use helpers::types::{
|
||||
get_type_representation, mk_name, object_type_exists, unwrap_custom_type_name,
|
||||
|
Loading…
Reference in New Issue
Block a user