dotansimha / graphql-code-generator-community

MIT License
114 stars 144 forks source link

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

Open peer-f opened 1 year ago

peer-f commented 1 year ago

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!

Parables commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

@peer-f install the latest version: npm i @graphql-codegen/flutter-freezed@4.0.0-alpha-20230823221342-8db60f2d0

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

whlsxl commented 5 months ago

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,