[Idea] Opinionated (graphql) transformer
Is your feature request related to a problem? Please describe.
At the moment 98% of our graphql transformers use the addFields to set the __typename.
Describe the solution you'd like
Maybe we should provide a preconfigured graphql transformer that always sets the __typename.
For example:
Transformer.graphql('Author')
Transformer.graphql('Author', {
buildFields: ['books'],
})
Describe alternatives you've considered
Instead of Transformer.graphql, we can have a GraphqlTransformer.
@pa3 @tdeekens any thoughts about this?
I like the idea but I also like that all transformers have the same API no matter their type 🤔.
One thing, unrelated to this, is that I wonder if we should "auto-build" nested fields if possible. That removes already quite a bit of cruft.
I encountered a use case where having __typename in the generated data is not convenient. It's when generating data related to GraphQL Input Types, such as AttributeGroupDraft which is used as an argument to the createAttributeGroup mutation. Because __typename is not allowed on Input Types, the related mutation will fail. To solve this, __typenames can be stripped from the generated data by transformers.
// Generator
const generator = Generator({
fields: {
name: fake(() => LocalizedString.random()),
description: fake((f) =>
f.random.arrayElement([null, LocalizedString.random()])
),
},
});
// Transformers
function omitTypename(object) {
return omitDeep(object, '__typename');
}
const transformers = {
graphql: Transformer('graphql', {
replaceFields({ fields }) {
return {
...fields,
name: buildField(fields.name, 'graphql').map(omitTypename),
description:
fields.description &&
buildField(fields.description, 'graphql').map(omitTypename),
};
},
}),
};
// Usage
const attributeGroupDraft = AttributeGroupDraft.random().buildGraphql();
However, this is not ideal as doing this will become redundant (needs to be done for each generated GraphQL data). One way to solve this is to get inspired by how Apollo GraphQL handles __typename, and provide a new addTypename option to the buildGraphql builder, with a default value of true. This way, the consumer can correctly generate input types by setting the option value to false.
// Generator
const generator = Generator({
fields: {
name: fake(() => LocalizedString.random()),
description: fake((f) =>
f.random.arrayElement([null, LocalizedString.random()])
),
},
});
// Transformers
-function omitTypename(object) {
- return omitDeep(object, '__typename');
-}
const transformers = {
graphql: Transformer('graphql', {
- replaceFields({ fields }) {
- return {
- ...fields,
- name: buildField(fields.name, 'graphql').map(omitTypename),
- description:
- fields.description &&
- buildField(fields.description, 'graphql').map(omitTypename),
- };
- },
+ buildFields: ['name', 'description'],
}),
};
// Usage
- const attributeGroupDraft = AttributeGroupDraft.random().buildGraphql();
+ const attributeGroupDraft = AttributeGroupDraft.random().buildGraphql({ addTypename: false });