-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[client-preset] allowed options and defaults #8562
Comments
|
E.g. the correct type for query MeQuery {
me {
id
}
} is type MeQuery = {
me: {
id: string
}
} not type MeQuery = {
me: {
__typename?: "User",
id: string
}
} or type MeQuery = {
me: {
__typename: "User",
id: string
}
} However, GraphQL clients such as apollo and urql ADD Having that said, for me, the following makes the most sense:
Adding the In order to make the apollo/urql users happy this means we will kind of need an This is a potential proposal that groups the configuration under one object property: type AutoTypenamesSelectionConfig = boolean | {
skipRootTypes?: boolean
} I don't event think we need to allow adding Curious to hear the use-cases of having |
Regarding If data masking is only implemented on the type level, I'm not sure how useful it is. If we look at the reasoning behind the data masking that is stated in the Relay docs (see below), I think that as long as you have types generated at all, if we were to remove a property from one component that was used in another component, but wasn't specified in that component, it would be caught during type checking. If we are depending on it in a way that is not checkable by TypeScript, would it be caught if we had fragment masking on? You could argue that it's more "correct" to force people to specify all the data deps for each component. And maybe there is a better chance that if you are forced to initially add all the data deps you need to the component itself, there is a lower chance that you will remove it by accident when changing another component. But it won't get enforced on the runtime level like Relay does it. |
It helps a lot building scalable and isolated components and I use it even without runtime type masking. So to me it is very helpful. Sometimes it is better to force people to use something that leads to better patterns. I would prefer to have it on by default but allow people to opt-out if they really need to. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, my whole argument above doesn't apply to the generated types. The only reason I want |
I don't think Am I missing something? |
@sfarthin We discussed internally that we want to set |
enumsAsConst: true, I would propose these. Its a common patter to use |
@ShravanSunder I agree with all your proposals - except |
For maybe values this is how I prefer to use type settings:
The reason for this configuration is that I can detect the difference in the returned data: if it is null it means that I requested it in the query or in a fragment so it is nulled by the server explicitly, if it is undefined (which can not be in theory because of the avoidOptionals and the typings unless I do some dynamic typing/indexing with any/unknown and casting) the field is missing from the response since I haven't requested it. If I would use both avoidOptionals with false for fields and maybeValue with null then I need to use types like this in components, functions, hooks and anything: T | null | undefined. The settings above are consistent, and I can expect T | null type in the returned data for GraphQL nullable types. The other part is input data, I prefer to set inputMaybeValue to T | undefined and the avoidOptionals for inputValue and object to false since I don't want to set them to null explicitly in the code, I just leave them out so that they will be undefined. A great example is Relay's Cursor Connections Specification (https://relay.dev/graphql/connections.htm) where I don't want to set first/after and last/before together. So instead of this
I can write this
Or for the first page I can write this (leaving out the after cursor too):
I think these are the defaults which make sense but I can imagine other coding styles or preferences. |
Currently using the client preset and am unable to get
Are there any plans to support this option for client-preset? |
Hi @efreila, Could you provide a minimal repro? |
I really think fragment masking should be disabled by default. IMO the cost far outweighs any benefit: the extra types and hooks are a significant code smell, the hooks add unnecessarily runtime complexity, and interop is now much harder (how do I write Storybook stories now?). All this to prevent something structural types already handle perfectly well. No thanks. If we wanted to use Relay, we would use Relay! |
Depends who you ask. I disagree there are lot of benefits fragment masking brings and working on large projects and trying to on-board someone I have found it useful.
You can still mock your queries. Agreed there is some noise to make types happy. |
I would love some way to split apart the large generated typescript files into smaller chunks somehow (eg by fragments and queries found in code; or by some simple way to mash the near-operation-preset with the client-preset, which idk how I would do it), so that the typescript compiler with the incremental flag on can better cache code that won’t change when the schema changes. I use Hasura, the schema it outputs can get very large as the project grows, and since I mostly get a giant output file, any change forces typescript to reevaluate all of the schema types, which causes updates to lock up for a while and VSCode performance to tank if I make the mistake of looking at the generated gql file. |
What about |
@osdiab you can try adding these two options and that should help shrink size of autogenerated file. preResolveTypes: true,
onlyOperationTypes: true There is a bigger performance improvement change which I have a discussion for here #8693 which will help even more. |
|
I am wanting to set 'maybeValue' - can this be added too? It seems silly to not include all of the properties of the underlying plugins, otherwise you cant setup your project as previously! |
Why do you want to set maybeValue? |
Dont worry, i can do it what i need with: Thanks for the great lib & new feature (if it is new!) |
having queries return values that are |
Does unmaskFunctionName default name really have to be a hook? From the looks of it, it's not actually a hook, but if the function name starts with Setting the config below fixes the problem, but maybe this could be the default?
|
I want to use I know that client-preset is intentionally limiting the options, so I am not directly publishing PRs, but sharing use cases. |
Very much agreed. What do you mean by previously? Is there an old way to configure that I can revert back to, in order to leverage |
+1 to |
+1 for enum EnumFromCodegen {
Dog = "dog",
Cat = "cat"
}
enum EnumFromCodebase {
Dog = "dog",
Cat = "cat"
}
function foo(pet: EnumFromCodebase) {
return pet;
}
foo(EnumFromCodegen.Dog);
// ^ Argument of type 'EnumFromCodegen.Dog' is not assignable to parameter of type 'EnumFromCodebase'. |
I'm not understanding why EDIT: I think I'm going to (gross) use |
I don't think this is true, and I was also unable to use that setting. I've opened #9653, which adds a line of code that allows that option to be passed upstream to where it needs to go. |
I created a pull request to forward I also wrote about it here: 📚 GraphQL Enums Are Unsafe. |
I'm just getting caught up with all the latest and greatest in the ecosystem. Overall I'm really excited about this direction but one thing that I feel like I'm missing right now is the ability to leverage the I also use Hasura so I have a very big schema and I like to have the base types for the schema code-generated into their own library in my NX monorepos. That way I can keep operations in another lib and just import my core schema types from eg Additionally I sometimes have multiple apps or feature libraries inside a monorepo. With my normal approach I only need to have one copy of the types for the Schema and then each app or lib owns its own operation types but with the new client preset it seems like I'm going to get multiple copies of all the types from the whole schema for each one I think this would also help out with the situation @osdiab is describing. It looks like the preset is just a collection of plugins composed so I can probably reverse engineer and build my own that allows me to use |
Seem like I've again used |
What is the status of this change?
|
+1 to above, experiencing same issue right now while integrating with 3rd party API which apparently doesn't follow UniqueInputFieldNamesRule. Attempts to skip validation with config at various levels is failing. |
+1 to above as well, |
Would be nice to have |
The current default output is TypeScript's
OutputGraphQL:
Default output: export enum Color {
RED = 'RED',
BLUE = 'BLUE',
GREEN = 'GREEN',
}
export type Color = 'RED' | 'BLUE' | 'GREEN';
export const Color = {
RED: 'RED',
BLUE: 'BLUE',
GREEN: 'GREEN',
} as const;
export type Color = typeof Color[keyof typeof Color]; UsageDefault output: import { Color } from './generated/graphql';
const color = "...";
if (color === Color.RED) {
console.log('Red color');
}
const color = "...";
if (color === 'RED') {
console.log('Red color');
}
import { Color } from './generated/graphql';
const color = "...";
if (color === Color.RED) {
console.log('Red color');
}
Default output and |
can we add fragment UserCard_User on User
{
name
age
}
|
I would like the ability to rename the masking function From the recommended nickname of the masking function In other words:
|
Awesome list of options and defaults proposal! |
Also add isolatedDeclarations |
This issue is the place to discuss allowed options and default values when using the
preset: 'client'
setup.Currently supported options
scalars
strictScalars
namingConvention
useTypeImports
skipTypename
enumsAsTypes
arrayInputCoercion
presetConfig.fragmentMasking
presetConfig.gqlTagName
presetConfig.unmaskFunctionName
emitLegacyCommonJSImports
Requested options support
nonOptionalTypename
(GraphQL Code Generator v5 Roadmap #8296 (comment))immutableTypes
(GraphQL Code Generator v5 Roadmap #8296 (comment))Current defaults
presetConfig.fragmentMasking: true
inlineFragmentTypes: true
(if fragment masking is enabled)emitLegacyCommonJSImports: true
Requested defaults
ignoreNoDocuments: true
(@charlypoly)presetConfig.fragmentMasking
befalse
by default? (@charlypoly)dedupeFragments: true
(duplicate fragments within queries #8103 (comment))enumsAsTypes: true
(@n1ru4l)The text was updated successfully, but these errors were encountered: