fn write_fragment_type_exports_section()

in compiler/crates/relay-typegen/src/lib.rs [388:502]


    fn write_fragment_type_exports_section(
        &mut self,
        fragment_definition: &FragmentDefinition,
    ) -> FmtResult {
        // Assignable fragments do not require $data and $ref type exports, and their aliases
        let is_assignable_fragment = fragment_definition
            .directives
            .named(*ASSIGNABLE_DIRECTIVE)
            .is_some();

        let mut selections = self.visit_selections(&fragment_definition.selections);
        if !fragment_definition.type_condition.is_abstract_type() {
            let num_concrete_selections = selections
                .iter()
                .filter(|sel| sel.get_enclosing_concrete_type().is_some())
                .count();
            if num_concrete_selections <= 1 {
                for selection in selections.iter_mut().filter(|sel| sel.is_typename()) {
                    selection.set_concrete_type(fragment_definition.type_condition);
                }
            }
        }
        self.generated_fragments
            .insert(fragment_definition.name.item);

        let data_type = fragment_definition.name.item;
        let data_type_name = format!("{}$data", data_type);

        let ref_type_data_property = Prop::KeyValuePair(KeyValuePairProp {
            key: *KEY_DATA,
            optional: true,
            read_only: true,
            value: AST::Identifier(data_type_name.as_str().intern()),
        });
        let fragment_name = fragment_definition.name.item;
        let ref_type_fragment_spreads_property = Prop::KeyValuePair(KeyValuePairProp {
            key: *KEY_FRAGMENT_SPREADS,
            optional: false,
            read_only: true,
            value: AST::FragmentReference(SortedStringKeyList::new(
                vec![fragment_name],
                self.should_sort_typegen_items,
            )),
        });
        let is_plural_fragment = is_plural(fragment_definition);
        let mut ref_type = AST::InexactObject(InexactObject::new(
            vec![ref_type_data_property, ref_type_fragment_spreads_property],
            self.should_sort_typegen_items,
        ));
        if is_plural_fragment {
            ref_type = AST::ReadOnlyArray(Box::new(ref_type));
        }

        let unmasked = RelayDirective::is_unmasked_fragment_definition(fragment_definition);

        let base_type = self.selections_to_babel(
            selections.into_iter(),
            unmasked,
            if unmasked { None } else { Some(fragment_name) },
        );
        let type_ = if is_plural_fragment {
            AST::ReadOnlyArray(base_type.into())
        } else {
            base_type
        };

        let type_ = match fragment_definition
            .directives
            .named(*CHILDREN_CAN_BUBBLE_METADATA_KEY)
        {
            Some(_) => AST::Nullable(type_.into()),
            None => type_,
        };

        self.runtime_imports.fragment_reference = true;
        self.write_import_actor_change_point()?;
        self.write_fragment_imports()?;
        self.write_enum_definitions()?;
        self.write_runtime_imports()?;
        self.write_relay_resolver_imports()?;

        let refetchable_metadata = RefetchableMetadata::find(&fragment_definition.directives);
        let fragment_type_name = format!("{}$fragmentType", fragment_name);
        self.writer
            .write_export_fragment_type(&fragment_type_name)?;
        if let Some(refetchable_metadata) = refetchable_metadata {
            let variables_name = format!("{}$variables", refetchable_metadata.operation_name);
            match self.js_module_format {
                JsModuleFormat::CommonJS => {
                    if self.has_unified_output {
                        self.writer.write_import_fragment_type(
                            &[&variables_name],
                            &format!("./{}.graphql", refetchable_metadata.operation_name),
                        )?;
                    } else {
                        self.writer.write_any_type_definition(&variables_name)?;
                    }
                }
                JsModuleFormat::Haste => {
                    self.writer.write_import_fragment_type(
                        &[&variables_name],
                        &format!("{}.graphql", refetchable_metadata.operation_name),
                    )?;
                }
            }
        }

        if !is_assignable_fragment {
            self.writer.write_export_type(&data_type_name, &type_)?;
            self.writer
                .write_export_type(&format!("{}$key", fragment_definition.name.item), &ref_type)?;
        }

        Ok(())
    }