Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate client pointer param types #434

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 74 additions & 97 deletions crates/generate_artifacts/src/generate_artifacts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use common_lang_types::{
derive_display, ArtifactFileName, ArtifactFilePrefix, ArtifactPathAndContent, DescriptionValue,
Location, ObjectTypeAndFieldName, Span, WithLocation, WithSpan,
FieldNameOrAlias, Location, ObjectTypeAndFieldName, Span, WithLocation, WithSpan,
};
use graphql_lang_types::{
GraphQLNamedTypeAnnotation, GraphQLNonNullTypeAnnotation, GraphQLTypeAnnotation,
Expand All @@ -11,8 +11,8 @@ use core::panic;
use isograph_config::CompilerConfig;
use isograph_lang_types::{
ArgumentKeyAndValue, ClientFieldId, NonConstantValue, ScalarFieldSelection,
SelectableServerFieldId, SelectionType, ServerFieldSelection, TypeAnnotation, UnionVariant,
VariableDefinition,
SelectableServerFieldId, SelectionType, ServerFieldSelection, ServerObjectId, TypeAnnotation,
UnionVariant, VariableDefinition,
};
use isograph_schema::{
get_provided_arguments, selection_map_wrapped, ClientFieldVariant, ClientType,
Expand Down Expand Up @@ -627,44 +627,40 @@ fn write_param_type_from_selection<TOutputFormat: OutputFormat>(
}
}
ServerFieldSelection::LinkedField(linked_field) => {
let parent_field = parent_type
.encountered_fields
.get(&linked_field.name.item.into())
.expect("parent_field should exist 2")
.as_server_field()
.expect("Parent field should exist and be server field");
let field = schema.server_field(*parent_field);
let field = match linked_field.associated_data.field_id {
FieldType::ServerField(server_field_id) => {
FieldType::ServerField(schema.server_field(server_field_id))
}
FieldType::ClientField(client_pointer_id) => {
FieldType::ClientField(schema.client_pointer(client_pointer_id))
}
};

write_optional_description(
field.description,
field.description(),
query_type_declaration,
indentation_level,
);
query_type_declaration.push_str(&" ".repeat(indentation_level as usize).to_string());
let name_or_alias = linked_field.name_or_alias().item;

let type_annotation =
match &field.associated_data {
SelectionType::Scalar(_) => panic!(
"output_type_id should be an object. \
This is indicative of a bug in Isograph.",
),
SelectionType::Object(associated_data) => associated_data
.type_name
.clone()
.map(&mut |output_type_id| {
let object_id = output_type_id;
let object = schema.server_field_data.object(object_id);
generate_client_field_parameter_type(
schema,
&linked_field.selection_set,
object,
nested_client_field_imports,
loadable_fields,
indentation_level,
link_fields,
)
}),
};
field
.output_type_annotation()
.clone()
.map(&mut |output_type_id| {
let object_id = output_type_id;
let object = schema.server_field_data.object(object_id);
generate_client_field_parameter_type(
schema,
&linked_field.selection_set,
object,
nested_client_field_imports,
loadable_fields,
indentation_level,
link_fields,
)
});

query_type_declaration.push_str(&format!(
"readonly {}: {},\n",
Expand Down Expand Up @@ -838,93 +834,74 @@ fn write_updatable_data_type_from_selection<TOutputFormat: OutputFormat>(
}
}
ServerFieldSelection::LinkedField(linked_field) => {
let parent_field = parent_type
.encountered_fields
.get(&linked_field.name.item.into())
.expect("parent_field should exist 2")
.as_server_field()
.expect("Parent field should exist and be server field");
let field = schema.server_field(*parent_field);
let field = schema.linked_type(linked_field.associated_data.field_id);

write_optional_description(
field.description,
field.description(),
query_type_declaration,
indentation_level,
);
query_type_declaration.push_str(&" ".repeat(indentation_level as usize).to_string());
let name_or_alias = linked_field.name_or_alias().item;

match &field.associated_data {
SelectionType::Scalar(_) => panic!(
"output_type_id should be an object. \
This is indicative of a bug in Isograph.",
),
SelectionType::Object(associated_data) => {
let type_annotation =
associated_data
.type_name
.clone()
.map(&mut |output_type_id| {
let object_id = output_type_id;
let object = schema.server_field_data.object(object_id);
generate_client_field_updatable_data_type(
schema,
&linked_field.selection_set,
object,
nested_client_field_imports,
loadable_fields,
indentation_level,
link_fields,
updatable_fields,
)
});

match linked_field.associated_data.selection_variant {
ValidatedIsographSelectionVariant::Loadable(_) => {
panic!("@loadable server fields are not supported")
}
ValidatedIsographSelectionVariant::Updatable => {
*updatable_fields = true;
write_getter_and_setter(
query_type_declaration,
indentation_level,
name_or_alias,
associated_data,
&type_annotation,
);
}
ValidatedIsographSelectionVariant::Regular => {
query_type_declaration.push_str(&format!(
"readonly {}: {},\n",
name_or_alias,
print_javascript_type_declaration(&type_annotation),
));
}
}
let type_annotation =
field
.output_type_annotation()
.clone()
.map(&mut |output_type_id| {
let object_id = output_type_id;
let object = schema.server_field_data.object(object_id);
generate_client_field_updatable_data_type(
schema,
&linked_field.selection_set,
object,
nested_client_field_imports,
loadable_fields,
indentation_level,
link_fields,
updatable_fields,
)
});

match linked_field.associated_data.selection_variant {
ValidatedIsographSelectionVariant::Loadable(_) => {
panic!("@loadable server fields are not supported")
}
};
ValidatedIsographSelectionVariant::Updatable => {
*updatable_fields = true;
write_getter_and_setter(
query_type_declaration,
indentation_level,
name_or_alias,
field.output_type_annotation(),
&type_annotation,
);
}
ValidatedIsographSelectionVariant::Regular => {
query_type_declaration.push_str(&format!(
"readonly {}: {},\n",
name_or_alias,
print_javascript_type_declaration(&type_annotation),
));
}
}
}
}
}

fn write_getter_and_setter(
query_type_declaration: &mut String,
indentation_level: u8,
name_or_alias: common_lang_types::FieldNameOrAlias,
associated_data: &isograph_schema::ServerFieldTypeAssociatedData<
TypeAnnotation<isograph_lang_types::ServerObjectId>,
>,
name_or_alias: FieldNameOrAlias,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, good catch!

output_type_annotation: TypeAnnotation<ServerObjectId>,
type_annotation: &TypeAnnotation<ClientFieldUpdatableDataType>,
) {
query_type_declaration.push_str(&format!(
"get {}(): {},\n",
name_or_alias,
print_javascript_type_declaration(type_annotation),
));
let setter_type_annotation = associated_data
.type_name
.clone()
.map(&mut |_| "{ link: Link }");
let setter_type_annotation = output_type_annotation.map(&mut |_| "{ link: Link }");
query_type_declaration.push_str(&" ".repeat(indentation_level as usize).to_string());
query_type_declaration.push_str(&format!(
"set {}(value: {}),\n",
Expand Down
8 changes: 7 additions & 1 deletion crates/generate_artifacts/src/reader_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ fn linked_field_ast_node<TOutputFormat: OutputFormat>(
let indent_2 = " ".repeat((indentation_level + 1) as usize);

let condition = match linked_field.associated_data.field_id {
FieldType::ClientField(_) => todo!(),
FieldType::ClientField(client_pointer_id) => {
let client_pointer = schema.client_pointer(client_pointer_id);
format!(
"{}__resolver_reader",
client_pointer.type_and_field.underscore_separated()
)
}
FieldType::ServerField(server_field_id) => {
match &schema.server_field(server_field_id).associated_data {
SelectionType::Scalar(_) => panic!("Expected object"),
Expand Down
89 changes: 88 additions & 1 deletion crates/isograph_schema/src/isograph_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use lazy_static::lazy_static;
use crate::{
refetch_strategy::RefetchStrategy, schema_validation_state::SchemaValidationState,
ClientFieldVariant, NormalizationKey, OutputFormat, ServerFieldTypeAssociatedData,
ValidatedClientField, ValidatedClientPointer,
ValidatedClientField, ValidatedClientPointer, ValidatedSchemaServerField,
};

lazy_static! {
Expand Down Expand Up @@ -134,12 +134,79 @@ pub enum FieldType<TServer, TClient> {
ClientField(TClient),
}

pub type LinkedType<
'a,
ServerFieldTypeAssociatedData,
ClientTypeSelectionScalarFieldAssociatedData,
ClientTypeSelectionLinkedFieldAssociatedData,
VariableDefinitionInnerType,
TOutputFormat,
> = FieldType<
&'a SchemaServerField<
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it makes me sad that SchemaServerField is both linked and scalar :/ We should eventually fix that #436

ServerFieldTypeAssociatedData,
VariableDefinitionInnerType,
TOutputFormat,
>,
&'a ClientPointer<
ClientTypeSelectionScalarFieldAssociatedData,
ClientTypeSelectionLinkedFieldAssociatedData,
VariableDefinitionInnerType,
TOutputFormat,
>,
>;

#[derive(Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq, Hash)]
pub enum ClientType<TField, TPointer> {
ClientField(TField),
ClientPointer(TPointer),
}

impl<
ServerFieldTypeAssociatedData,
TClientTypeSelectionScalarFieldAssociatedData,
TClientTypeSelectionLinkedFieldAssociatedData,
TClientTypeVariableDefinitionAssociatedData: Ord + Debug,
TOutputFormat: OutputFormat,
>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird rust fmt behavior ! Anyway, all good (it's formatting it), just surprising

FieldType<
&SchemaServerField<
ServerFieldTypeAssociatedData,
TClientTypeVariableDefinitionAssociatedData,
TOutputFormat,
>,
&ClientPointer<
TClientTypeSelectionScalarFieldAssociatedData,
TClientTypeSelectionLinkedFieldAssociatedData,
TClientTypeVariableDefinitionAssociatedData,
TOutputFormat,
>,
>
{
pub fn description(&self) -> Option<DescriptionValue> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's at some point consolidate these into an interface, so that e.g. the second param here can be ClientField or ClientType and we still have a .description method

match self {
FieldType::ServerField(server_field) => server_field.description,
FieldType::ClientField(client_field) => client_field.description,
}
}
}

impl<TOutputFormat: OutputFormat>
FieldType<&ValidatedSchemaServerField<TOutputFormat>, &ValidatedClientPointer<TOutputFormat>>
{
pub fn output_type_annotation(&self) -> TypeAnnotation<ServerObjectId> {
match self {
FieldType::ClientField(client_pointer) => client_pointer.to.clone(),
FieldType::ServerField(server_field) => match &server_field.associated_data {
SelectionType::Scalar(_) => panic!(
"output_type_id should be an object. \
This is indicative of a bug in Isograph.",
),
SelectionType::Object(associated_data) => associated_data.type_name.clone(),
},
}
}
}

pub type ClientTypeId = ClientType<ClientFieldId, ClientPointerId>;

pub type ValidatedClientType<'a, TOutputFormat> =
Expand Down Expand Up @@ -299,6 +366,26 @@ impl<TSchemaValidationState: SchemaValidationState, TOutputFormat: OutputFormat>
}
}

pub fn linked_type(
&self,
field_id: FieldType<ServerFieldId, ClientPointerId>,
) -> LinkedType<
TSchemaValidationState::ServerFieldTypeAssociatedData,
TSchemaValidationState::ClientTypeSelectionScalarFieldAssociatedData,
TSchemaValidationState::ClientTypeSelectionLinkedFieldAssociatedData,
TSchemaValidationState::VariableDefinitionInnerType,
TOutputFormat,
> {
match field_id {
FieldType::ServerField(server_field_id) => {
FieldType::ServerField(self.server_field(server_field_id))
}
FieldType::ClientField(client_pointer_id) => {
FieldType::ClientField(self.client_pointer(client_pointer_id))
}
}
}

/// Get a reference to a given client pointer by its id.
pub fn client_pointer(
&self,
Expand Down
Loading