graphql-code-generator-community icon indicating copy to clipboard operation
graphql-code-generator-community copied to clipboard

[@graphql-codegen/flutter-freezed] Generated enums are not used in freezed models, advanced codegen configuration is not possible

Open peer-f opened this issue 2 years ago • 8 comments

Which packages are impacted by your issue?

@graphql-codegen/flutter-freezed

Describe the bug

I have the following schema:

enum REAL_ESTATE_TYPE {
    APARTMENT
    DETACHED_HOUSE
    APARTMENT_BUILDING
    PROPERTY
    COMMERCIAL
}

type RealEstate{
    type: REAL_ESTATE_TYPE!
    monthly_rent: Int!
    property_value: Int!
    year_of_purchase: Int!
    postal_code: String!
}

All of our enums are named in all caps and snake case. The enum gets generated correctly and looks like this:

enum RealEstateType {
  @JsonKey(name: 'APARTMENT')
  apartment,
  @JsonKey(name: 'APARTMENT_BUILDING')
  apartmentBuilding,
  @JsonKey(name: 'COMMERCIAL')
  commercial,
  @JsonKey(name: 'DETACHED_HOUSE')
  detachedHouse,
  @JsonKey(name: 'PROPERTY')
  property,
}

Unfortunately this enum is not used and reflected in the resulting class:

@Freezed(
  copyWith: true,
)
class RealEstate with _$RealEstate {
  const RealEstate._();

  const factory RealEstate({
    @JsonKey(name: 'monthly_rent')
    required int monthlyRent,
    @JsonKey(name: 'postal_code')
    required String postalCode,
    @JsonKey(name: 'property_value')
    required int propertyValue,
    required REAL_ESTATE_TYPE type,
    @JsonKey(name: 'year_of_purchase')
    required int yearOfPurchase,
  }) = _RealEstate;

  factory RealEstate.fromJson(Map<String, dynamic> json) => _$RealEstateFromJson(json);
}

Your Example Website or App

https://stackblitz.com/edit/github-wt29hz?file=schema.graphql

Steps to Reproduce the Bug or Issue

npm run generate

Expected behavior

I would like to do more customization via the codegen.ts file but I'm unable to do that since the types used for advanced configuration options are not exported by the flutter-freezed package itself as mentioned in this issue. Because of this I'm not able to used the Config type that is used in the guide.

How can I customize the naming of enums in my GraphQL schema and how should this be configured in my codegen.ts? Should the building block APPLIES_ON_ENUM be used?

Screenshots or Videos

No response

Platform

"dependencies": { "graphql": "^16.2.0" }, "devDependencies": { "@graphql-codegen/cli": "^3.3.0", "@graphql-codegen/flutter-freezed": "^3.0.2", "typescript": "^4.8.4" }

Codegen Config File

import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'schema.graphql',
  generates: {
    'entities_gen.dart': {
      plugins: {
        'flutter-freezed': {
          copyWith: true,
        },
      },
    },
  },
};
export default config;

Additional context

I would really appreciate a small example on how to configure this correctly in my codegen.ts file. Thank you!

peer-f avatar Apr 20 '23 15:04 peer-f

@peer-f

I apologize for the delay in my response. I was away for some time but I am back now and ready to assist you.

Thank you for bringing the issue to my attention. I assure you that I will resolve it as soon as possible.

I am grateful that you tried out the flutter-freezed plugin. Thank you again.

Parables avatar Aug 13 '23 03:08 Parables

To address your issue flutter-freezed v3.1.0 will include a renameAs option in the config, allowing you to map the TypeNames and FieldNames in your GraphQL schema to custom ones.

I will give you a sample and update your stackblitz example .

Parables avatar Aug 13 '23 04:08 Parables

@peer-f

a temporal workaround to fix this issue until flutter-freezed v3.1.0 is released, use the customScalar option to treat the current type as a custom type.

I forked and updated your Stackblitz demo

import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'schema.graphql',
  generates: {
    'entities_gen.dart': {
      plugins: {
        'flutter-freezed': {
          copyWith: true,
          customScalars: {
            REAL_ESTATE_TYPE: 'RealEstateType',
          },
        },
      },
    },
  },
};
export default config;

which produces the following output

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'entities_gen.freezed.dart';
part 'entities_gen.g.dart';

enum RealEstateType {
  @JsonKey(name: 'APARTMENT')
  apartment,
  @JsonKey(name: 'APARTMENT_BUILDING')
  apartmentBuilding,
  @JsonKey(name: 'COMMERCIAL')
  commercial,
  @JsonKey(name: 'DETACHED_HOUSE')
  detachedHouse,
  @JsonKey(name: 'PROPERTY')
  property,
}

@Freezed(
  copyWith: true,
)
class RealEstate with _$RealEstate {
  const RealEstate._();

  const factory RealEstate({
    @JsonKey(name: 'monthly_rent')
    required int monthlyRent,
    @JsonKey(name: 'postal_code')
    required String postalCode,
    @JsonKey(name: 'property_value')
    required int propertyValue,
    required RealEstateType type,
    @JsonKey(name: 'year_of_purchase')
    required int yearOfPurchase,
  }) = _RealEstate;

  factory RealEstate.fromJson(Map<String, dynamic> json) => _$RealEstateFromJson(json);
}

Parables avatar Aug 13 '23 09:08 Parables

After carefully looking at the issue, here is what is caused the issue:

This plugin tries to follow Dart recommended linting rules. Therefore: classes and Enums are PascalCased all fields/properties/parameters are camelCased except for Enum values which can be configured using the camelCasedEnums option

In your graphql schema, your Enum was named REAL_ESTATE_TYPE and that's why the plugin PascalCased it to RealEstateType

This is not a bug with the plugin. On the contrary, it is a feature.

If you have control over the GraphQL Schema, I suggest you stick with standard naming conventions: PascalCase for your GraphQL Types and camelCase for the fields.

If not, then what I earlier on called a workaround is your only solution.

The customScalar option will allow you to specify how to handle custom types. The GraphQL TypeName is specified as the key, and how it should be generated as the value. If the key is missing in the customScalar config option, then the GraphQL TypeName is used as it is.

That is why the plugin generated REAL_ESTATE_TYPE as the dart type of the type parameter instead of RealEstateType.

Implementing a config option renameAs as I proposed earlier will make this plugin quite complex and would take some time to get it done right so I am dropping that feature.

Please close this issue if I have addressed your problem.

Thank you for surfacing this up.

Parables avatar Aug 13 '23 13:08 Parables

P.s: I have fixed this issue so update the plugin once the PR is merged and released

https://github.com/dotansimha/graphql-code-generator-community/issues/319

Parables avatar Aug 13 '23 13:08 Parables

@peer-f install the latest version: npm i @graphql-codegen/[email protected]

https://www.npmjs.com/package/@graphql-codegen/flutter-freezed/v/4.0.0-alpha-20230823221342-8db60f2d0

https://stackblitz.com/edit/github-jzk7hh-emmwwm?file=package.json

Parables avatar Aug 24 '23 11:08 Parables

Schema.graphql

enum BookCategory {
  BusinessCareer
  Family
}

Generate

enum BookCategory {
  @JsonKey(name: 'BusinessCareer')
  businessCareer,
  @JsonKey(name: 'Family')
  family,
}

freezed generate


const _$BookCategoryEnumMap = {
  BookCategory.businessCareer: 'businessCareer',
  BookCategory.family: 'family',
}

freezed use $enumDecode(_$BookCategoryEnumMap, e); to trans from json.

got error

Invalid argument(s): `BusinessCareer` is not one of the supported values: businessCareer, family,

whlsxl avatar Apr 22 '24 22:04 whlsxl