createClassProperty function

ClassProperty createClassProperty({
  1. required ClassPropertyName fieldName,
  2. ClassPropertyName? fieldAlias,
  3. required Context context,
  4. OnNewClassFoundCallback? onNewClassFound,
  5. bool markAsUsed = true,
})

Creates a class property object from GraphQL field information.

This function analyzes a GraphQL field and creates the corresponding Dart class property with proper type mapping, annotations, and validation. It handles both regular object fields and input object fields by delegating to the appropriate specialized generators.

Parameters:

  • fieldName - The name of the field to create a property for
  • fieldAlias - Optional alias for the field (used in queries)
  • context - The current generation context containing schema and type information
  • onNewClassFound - Optional callback for when new classes need to be generated
  • markAsUsed - Whether to mark related types as used (default: true)

Returns: A ClassProperty object representing the Dart property

Throws:

  • Exception if the field is not found in the GraphQL type
  • Exception if unable to determine the field type

Special Handling:

  • __typename fields are automatically handled with proper JSON annotations
  • Input object fields are processed using InputGenerator
  • Regular object fields are processed using ClassGenerator

Example:

final property = createClassProperty(
  fieldName: ClassPropertyName(name: 'userId'),
  context: generationContext,
  onNewClassFound: (context) => print('New class: ${context.currentClassName}'),
);

Implementation

ClassProperty createClassProperty({
  required ClassPropertyName fieldName,
  ClassPropertyName? fieldAlias,
  required Context context,
  OnNewClassFoundCallback? onNewClassFound,
  bool markAsUsed = true,
}) {
  // Handle __typename field
  if (fieldName.name == context.schemaMap.typeNameField) {
    return ClassProperty(
      type: TypeName(name: 'String'),
      name: fieldName,
      annotations: ['JsonKey(name: \'${context.schemaMap.typeNameField}\')'],
      isResolveType: true,
    );
  }

  // Determine field type and directives based on current type
  var finalFields = <Node>[];
  if (context.currentType is ObjectTypeDefinitionNode) {
    finalFields = (context.currentType! as ObjectTypeDefinitionNode).fields;
  } else if (context.currentType is InterfaceTypeDefinitionNode) {
    finalFields = (context.currentType! as InterfaceTypeDefinitionNode).fields;
  } else if (context.currentType is InputObjectTypeDefinitionNode) {
    finalFields =
        (context.currentType! as InputObjectTypeDefinitionNode).fields;
  }

  final regularField = finalFields
      .whereType<FieldDefinitionNode>()
      .firstWhereOrNull((f) => f.name.value == fieldName.name);
  final regularInputField = finalFields
      .whereType<InputValueDefinitionNode>()
      .firstWhereOrNull((f) => f.name.value == fieldName.name);

  final fieldType = regularField?.type ?? regularInputField?.type;
  final fieldDirectives =
      regularField?.directives ?? regularInputField?.directives;

  if (fieldType == null) {
    throw Exception(
      '''Field $fieldName was not found in GraphQL type ${context.currentType?.name.value}.
Make sure your query is correct and your schema is updated.''',
    );
  }

  // Use ClassGenerator or InputGenerator based on context
  if (context.currentType is InputObjectTypeDefinitionNode &&
      regularInputField != null) {
    // Use InputGenerator for input object fields
    return InputGenerator.createInputClassProperty(
      fieldName: fieldName,
      fieldType: fieldType,
      fieldDirectives: regularInputField.directives,
      context: context,
    );
  } else if (regularField != null) {
    // Use ClassGenerator for regular object fields
    return ClassGenerator.createClassProperty(
      fieldName: fieldName,
      fieldAlias: fieldAlias,
      fieldType: fieldType,
      fieldDirectives: fieldDirectives,
      context: context,
      onNewClassFound: onNewClassFound ?? (_) {},
      markAsUsed: markAsUsed,
    );
  } else {
    throw Exception(
      '''Unable to determine field type for $fieldName in ${context.currentType?.name.value}''',
    );
  }
}