From 3c31a60971a971af1ec1c22617bfde59af1af080 Mon Sep 17 00:00:00 2001 From: PatrykWalach <35966385+PatrykWalach@users.noreply.github.com> Date: Mon, 24 Feb 2025 22:33:02 +0100 Subject: [PATCH] generate client pointer param types --- .../src/generate_artifacts.rs | 171 ++++++++---------- crates/generate_artifacts/src/reader_ast.rs | 8 +- crates/isograph_schema/src/isograph_schema.rs | 89 ++++++++- 3 files changed, 169 insertions(+), 99 deletions(-) diff --git a/crates/generate_artifacts/src/generate_artifacts.rs b/crates/generate_artifacts/src/generate_artifacts.rs index 62a3a109..29b2a094 100644 --- a/crates/generate_artifacts/src/generate_artifacts.rs +++ b/crates/generate_artifacts/src/generate_artifacts.rs @@ -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, @@ -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, @@ -627,15 +627,17 @@ 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, ); @@ -643,28 +645,22 @@ fn write_param_type_from_selection<TOutputFormat: OutputFormat>( 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", @@ -838,71 +834,57 @@ 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), + )); + } + } } } } @@ -910,10 +892,8 @@ fn write_updatable_data_type_from_selection<TOutputFormat: OutputFormat>( 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, + output_type_annotation: TypeAnnotation<ServerObjectId>, type_annotation: &TypeAnnotation<ClientFieldUpdatableDataType>, ) { query_type_declaration.push_str(&format!( @@ -921,10 +901,7 @@ fn write_getter_and_setter( 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", diff --git a/crates/generate_artifacts/src/reader_ast.rs b/crates/generate_artifacts/src/reader_ast.rs index b66a93cf..02cc7f6c 100644 --- a/crates/generate_artifacts/src/reader_ast.rs +++ b/crates/generate_artifacts/src/reader_ast.rs @@ -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"), diff --git a/crates/isograph_schema/src/isograph_schema.rs b/crates/isograph_schema/src/isograph_schema.rs index 6814435e..d7dfe578 100644 --- a/crates/isograph_schema/src/isograph_schema.rs +++ b/crates/isograph_schema/src/isograph_schema.rs @@ -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! { @@ -134,12 +134,79 @@ pub enum FieldType<TServer, TClient> { ClientField(TClient), } +pub type LinkedType< + 'a, + ServerFieldTypeAssociatedData, + ClientTypeSelectionScalarFieldAssociatedData, + ClientTypeSelectionLinkedFieldAssociatedData, + VariableDefinitionInnerType, + TOutputFormat, +> = FieldType< + &'a SchemaServerField< + 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, + > + FieldType< + &SchemaServerField< + ServerFieldTypeAssociatedData, + TClientTypeVariableDefinitionAssociatedData, + TOutputFormat, + >, + &ClientPointer< + TClientTypeSelectionScalarFieldAssociatedData, + TClientTypeSelectionLinkedFieldAssociatedData, + TClientTypeVariableDefinitionAssociatedData, + TOutputFormat, + >, + > +{ + pub fn description(&self) -> Option<DescriptionValue> { + 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> = @@ -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,