A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
MIT License
Bot releases are visible (Hide)
68ea5d4
Thanks @renovate! - dependencies updates:
moment@~2.30.0
↗︎ (from ~2.29.1
, in dependencies
)cd60e14
Thanks @Sojaner! - Omit __typename
from being added on the root node of a subscription when using addTypenameSelectionDocumentTransform
with documentTransforms since a single root node is expected and the code generator fails because of that (refer to https://spec.graphql.org/draft/#sec-Single-root-field)Published by theguild-bot 8 months ago
ed9c205
Thanks @henryqdineen! - properly handle aliased conditionals920b443
, ed9c205
]:
920b443
, ed9c205
]:
#9842 ed9c205
Thanks @henryqdineen! - properly handle aliased conditionals
Updated dependencies [920b443
, ed9c205
]:
920b443
, ed9c205
]:
920b443
, ed9c205
]:
920b443
, ed9c205
]:
920b443
, ed9c205
]:
920b443
, ed9c205
]:
#9627 422e2a7
Thanks @renovate! - dependencies updates:
[email protected]
↗︎ (from 13.3.1
, in dependencies
)#9851 217ed56
Thanks @renovate! - dependencies updates:
[email protected]
↗︎ (from 13.3.6
, in dependencies
)Published by theguild-bot 8 months ago
53f270a
]:
53f270a
Thanks @productdevbook! - path starts with "#"53f270a
]:
53f270a
]:
53f270a
]:
53f270a
]:
53f270a
]:
53f270a
]:
53f270a
]:
53f270a
]:
Published by theguild-bot 9 months ago
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Updated dependencies [4e69568
]:
Published by theguild-bot 9 months ago
7718a8113
Thanks @maclockard! - Respect avoidOptionals when all arguments are optional7718a8113
]:
7718a8113
]:
7718a8113
]:
#9673 7718a8113
Thanks @maclockard! - Respect avoidOptionals when all arguments are optional
Updated dependencies [7718a8113
]:
7718a8113
]:
7718a8113
]:
#9557 48ddaeae1
Thanks @konomae! - Add eslint-disable comment to fragment-masking.ts
Updated dependencies [7718a8113
]:
7718a8113
]:
Published by theguild-bot about 1 year ago
#9513 fdd19d24d
Thanks @cichelero! - Update yaml dependency to 2.3.1
Updated dependencies [bb1e0e96e
]:
#9562 5beee9794
Thanks @n1ru4l! - Add the addTypenameSelectionDocumentTransform
for automatically adding __typename
selections to all objct type selection sets.
This is useful for GraphQL Clients such as Apollo Client or urql that need typename information for their cache to function.
Example Usage
import { addTypenameSelectionDocumentTransform } from '@graphql-codegen/client-preset';
import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "YOUR_GRAPHQL_ENDPOINT",
documents: ["./**/*.{ts,tsx}"],
ignoreNoDocuments: true,
generates: {
"./gql/": {
preset: "client",
plugins: [],
presetConfig: {
persistedDocuments: true,
},
documentTransforms: [addTypenameSelectionDocumentTransform],
},
},
};
export default config;
bb1e0e96e
]:
Published by theguild-bot over 1 year ago
#9497 2276708d0
Thanks @eddeee888! - Revert default ID scalar input type to string
We changed the ID Scalar input type from string
to string | number
in the latest major version of typescript
plugin. This causes issues for server plugins (e.g. typescript-resolvers) that depends on typescript
plugin. This is because the scalar type needs to be manually inverted on setup which is confusing.
2276708d0
]:
2276708d0
]:
#9497 2276708d0
Thanks @eddeee888! - Revert default ID scalar input type to string
We changed the ID Scalar input type from string
to string | number
in the latest major version of typescript
plugin. This causes issues for server plugins (e.g. typescript-resolvers) that depends on typescript
plugin. This is because the scalar type needs to be manually inverted on setup which is confusing.
Updated dependencies [2276708d0
]:
#9497 2276708d0
Thanks @eddeee888! - Revert default ID scalar input type to string
We changed the ID Scalar input type from string
to string | number
in the latest major version of typescript
plugin. This causes issues for server plugins (e.g. typescript-resolvers) that depends on typescript
plugin. This is because the scalar type needs to be manually inverted on setup which is confusing.
Updated dependencies [2276708d0
]:
2276708d0
]:
#9497 2276708d0
Thanks @eddeee888! - Revert default ID scalar input type to string
We changed the ID Scalar input type from string
to string | number
in the latest major version of typescript
plugin. This causes issues for server plugins (e.g. typescript-resolvers) that depends on typescript
plugin. This is because the scalar type needs to be manually inverted on setup which is confusing.
Updated dependencies [2276708d0
]:
#9497 2276708d0
Thanks @eddeee888! - Revert default ID scalar input type to string
We changed the ID Scalar input type from string
to string | number
in the latest major version of typescript
plugin. This causes issues for server plugins (e.g. typescript-resolvers) that depends on typescript
plugin. This is because the scalar type needs to be manually inverted on setup which is confusing.
Updated dependencies [2276708d0
]:
2276708d0
]:
Published by theguild-bot over 1 year ago
#9479 0aa444b5d
Thanks @gilgardosh! - dependencies updates:
graphql-config@^5.0.2
↗︎ (from ^5.0.1
, in dependencies
)#9479 0aa444b5d
Thanks @gilgardosh! - Update graphql-config to v^5.0.2
Published by theguild-bot over 1 year ago
#9449 4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
graphql-config@^5.0.0
↗︎ (from ^4.5.0
, in dependencies
)#9449 4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/apollo-engine-loader@^8.0.0
↗︎ (from ^7.3.6
, in dependencies
)@graphql-tools/code-file-loader@^8.0.0
↗︎ (from ^7.3.17
, in dependencies
)@graphql-tools/git-loader@^8.0.0
↗︎ (from ^7.2.13
, in dependencies
)@graphql-tools/github-loader@^8.0.0
↗︎ (from ^7.3.28
, in dependencies
)@graphql-tools/graphql-file-loader@^8.0.0
↗︎ (from ^7.5.0
, in dependencies
)@graphql-tools/json-file-loader@^8.0.0
↗︎ (from ^7.4.1
, in dependencies
)@graphql-tools/load@^8.0.0
↗︎ (from ^7.8.0
, in dependencies
)@graphql-tools/prisma-loader@^8.0.0
↗︎ (from ^7.2.69
, in dependencies
)@graphql-tools/url-loader@^8.0.0
↗︎ (from ^7.17.17
, in dependencies
)@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)cosmiconfig@^8.1.3
↗︎ (from ^7.0.0
, in dependencies
)graphql-config@^5.0.1
↗︎ (from ^4.5.0
, in dependencies
)#9371 d431f426e
Thanks @Axxxx0n! - Fixed option ignoreNoDocuments when using graphql configs
#9275 2a5da5894
Thanks @milesrichardson! - Trigger rebuilds in watch mode while respecting rules of precedence and negation, both in terms of global (top-level) config vs. local (per-output target) config, and in terms of watch patterns (higher priority) vs. documents/schemas (lower priority). This fixes an issue with overly-aggressive rebuilds during watch mode.
Updated dependencies [4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/schema@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)@graphql-tools/utils@^10.0.0
↗︎ (from ^9.1.1
, in dependencies
)4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
#9375 ba84a3a27
Thanks @eddeee888! - Implement Scalars with input/output types
In GraphQL, Scalar types can be different for client and server. For example, given the native GraphQL ID:
string
or number
in the inputstring
in its selection set (i.e output)string
in the resolver (GraphQL parses string
or number
received from the client to string
)string
or number
(GraphQL serializes the value to string
before sending it to the client )Currently, we represent every Scalar with only one type. This is what codegen generates as base type:
export type Scalars = {
ID: string;
};
Then, this is used in both input and output type e.g.
export type Book = {
__typename?: 'Book';
id: Scalars['ID']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']; // Input's ID can be `string` or `number`. However, the type is only `string` here 👎
};
This PR extends each Scalar to have input and output:
export type Scalars = {
ID: {
input: string | number;
output: string;
};
};
Then, each input/output GraphQL type can correctly refer to the correct input/output scalar type:
export type Book = {
__typename?: 'Book';
id: Scalars['ID']['output']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']['input']; // Input's ID can be `string` or `number` 👍
};
Note that for typescript-resolvers
, the type of ID needs to be inverted. However, the referenced types in GraphQL input/output types should still work correctly:
export type Scalars = {
ID: {
input: string;
output: string | number;
}
}
export type Book = {
__typename?: "Book";
id: Scalars["ID"]['output']; // Resolvers can return `string` or `number` in ID fields 👍
};
export type QueryBookArgs = {
id: Scalars["ID"]['input']; // Resolvers receive `string` in ID fields 👍
};
export type ResolversTypes = {
ID: ID: ResolverTypeWrapper<Scalars['ID']['output']>; // Resolvers can return `string` or `number` in ID fields 👍
}
export type ResolversParentTypes = {
ID: Scalars['ID']['output']; // Resolvers receive `string` or `number` from parents 👍
};
Config changes:
config: {
scalars: {
ID: {
input: 'string',
output: 'string | number'
}
}
}
config: {
scalars: {
ID: 'string'; // This means `string` will be used for both ID's input and output types
}
}
config: {
scalars: {
ID: './path/to/scalar-module';
}
}
If correctly, wired up, the following will be generated:
// Previously, imported `ID` type can be a primitive type, now it must be an object with input/output fields
import { ID } from './path/to/scalar-module';
export type Scalars = {
ID: { input: ID['input']; output: ID['output'] };
};
BREAKING CHANGE: This changes Scalar types which could be referenced in other plugins. If you are a plugin maintainer and reference Scalar, please update your plugin to use the correct input/output types.
bb66c2a31
Thanks @n1ru4l! - Require Node.js >= 16
. Drop support for Node.js 14
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
#9339 50471e651
Thanks @AaronMoat! - Add excludeTypes config to resolversNonOptionalTypename
This disables the adding of __typename
in resolver types for any specified typename. This could be useful e.g. if you're wanting to enable this for all new types going forward but not do a big migration.
Usage example:
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: {
unionMember: true,
excludeTypes: ['MyType'],
},
},
},
},
};
#9229 5aa95aa96
Thanks @eddeee888! - Use generic to simplify ResolversUnionTypes
This follows the ResolversInterfaceTypes
's approach where the RefType
generic is used to refer back to ResolversTypes
or ResolversParentTypes
in cases of nested Union types
#9304 e1dc75f3c
Thanks @esfomeado! - Added support for disabling suffixes on Enums.
#9229 5aa95aa96
Thanks @eddeee888! - Extract interfaces to ResolversInterfaceTypes and add to resolversNonOptionalTypename
ResolversInterfaceTypes
is a new type that keeps track of a GraphQL interface and its implementing types.For example, consider this schema:
extend type Query {
character(id: ID!): CharacterNode
}
interface CharacterNode {
id: ID!
}
type Wizard implements CharacterNode {
id: ID!
screenName: String!
spells: [String!]!
}
type Fighter implements CharacterNode {
id: ID!
screenName: String!
powerLevel: Int!
}
The generated types will look like this:
export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = {
CharacterNode: Fighter | Wizard;
};
export type ResolversTypes = {
// other types...
CharacterNode: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['CharacterNode']>;
Fighter: ResolverTypeWrapper<Fighter>;
Wizard: ResolverTypeWrapper<Wizard>;
// other types...
};
export type ResolversParentTypes = {
// other types...
CharacterNode: ResolversInterfaceTypes<ResolversParentTypes>['CharacterNode'];
Fighter: Fighter;
Wizard: Wizard;
// other types...
};
The RefType
generic is used to reference back to ResolversTypes
and ResolversParentTypes
in some cases such as field returning a Union.
resolversNonOptionalTypename
also affects ResolversInterfaceTypes
Using the schema above, if we use resolversNonOptionalTypename
option:
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: true, // Or `resolversNonOptionalTypename: { interfaceImplementingType: true }`
},
},
},
};
Then, the generated type looks like this:
export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = {
CharacterNode: (Fighter & { __typename: 'Fighter' }) | (Wizard & { __typename: 'Wizard' });
};
export type ResolversTypes = {
// other types...
CharacterNode: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['CharacterNode']>;
Fighter: ResolverTypeWrapper<Fighter>;
Wizard: ResolverTypeWrapper<Wizard>;
// other types...
};
export type ResolversParentTypes = {
// other types...
CharacterNode: ResolversInterfaceTypes<ResolversParentTypes>['CharacterNode'];
Fighter: Fighter;
Wizard: Wizard;
// other types...
};
#9449 4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/optimize@^2.0.0
↗︎ (from ^1.3.0
, in dependencies
)@graphql-tools/relay-operation-optimizer@^7.0.0
↗︎ (from ^6.5.0
, in dependencies
)@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)#9414 ca02ad172
Thanks @beerose! - Include nested fragments in string documentMode
#9369 5950f5a68
Thanks @asmundg! - Output valid type names with mergeFragmentTypes
Updated dependencies [4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
#9375 ba84a3a27
Thanks @eddeee888! - Implement Scalars with input/output types
In GraphQL, Scalar types can be different for client and server. For example, given the native GraphQL ID:
string
or number
in the inputstring
in its selection set (i.e output)string
in the resolver (GraphQL parses string
or number
received from the client to string
)string
or number
(GraphQL serializes the value to string
before sending it to the client )Currently, we represent every Scalar with only one type. This is what codegen generates as base type:
export type Scalars = {
ID: string;
};
Then, this is used in both input and output type e.g.
export type Book = {
__typename?: 'Book';
id: Scalars['ID']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']; // Input's ID can be `string` or `number`. However, the type is only `string` here 👎
};
This PR extends each Scalar to have input and output:
export type Scalars = {
ID: {
input: string | number;
output: string;
};
};
Then, each input/output GraphQL type can correctly refer to the correct input/output scalar type:
export type Book = {
__typename?: 'Book';
id: Scalars['ID']['output']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']['input']; // Input's ID can be `string` or `number` 👍
};
Note that for typescript-resolvers
, the type of ID needs to be inverted. However, the referenced types in GraphQL input/output types should still work correctly:
export type Scalars = {
ID: {
input: string;
output: string | number;
}
}
export type Book = {
__typename?: "Book";
id: Scalars["ID"]['output']; // Resolvers can return `string` or `number` in ID fields 👍
};
export type QueryBookArgs = {
id: Scalars["ID"]['input']; // Resolvers receive `string` in ID fields 👍
};
export type ResolversTypes = {
ID: ID: ResolverTypeWrapper<Scalars['ID']['output']>; // Resolvers can return `string` or `number` in ID fields 👍
}
export type ResolversParentTypes = {
ID: Scalars['ID']['output']; // Resolvers receive `string` or `number` from parents 👍
};
Config changes:
config: {
scalars: {
ID: {
input: 'string',
output: 'string | number'
}
}
}
config: {
scalars: {
ID: 'string'; // This means `string` will be used for both ID's input and output types
}
}
config: {
scalars: {
ID: './path/to/scalar-module';
}
}
If correctly, wired up, the following will be generated:
// Previously, imported `ID` type can be a primitive type, now it must be an object with input/output fields
import { ID } from './path/to/scalar-module';
export type Scalars = {
ID: { input: ID['input']; output: ID['output'] };
};
BREAKING CHANGE: This changes Scalar types which could be referenced in other plugins. If you are a plugin maintainer and reference Scalar, please update your plugin to use the correct input/output types.
bb66c2a31
Thanks @n1ru4l! - Require Node.js >= 16
. Drop support for Node.js 14
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
#9304 e1dc75f3c
Thanks @esfomeado! - Added support for disabling suffixes on Enums.
4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
#9375 ba84a3a27
Thanks @eddeee888! - Implement Scalars with input/output types
In GraphQL, Scalar types can be different for client and server. For example, given the native GraphQL ID:
string
or number
in the inputstring
in its selection set (i.e output)string
in the resolver (GraphQL parses string
or number
received from the client to string
)string
or number
(GraphQL serializes the value to string
before sending it to the client )Currently, we represent every Scalar with only one type. This is what codegen generates as base type:
export type Scalars = {
ID: string;
};
Then, this is used in both input and output type e.g.
export type Book = {
__typename?: 'Book';
id: Scalars['ID']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']; // Input's ID can be `string` or `number`. However, the type is only `string` here 👎
};
This PR extends each Scalar to have input and output:
export type Scalars = {
ID: {
input: string | number;
output: string;
};
};
Then, each input/output GraphQL type can correctly refer to the correct input/output scalar type:
export type Book = {
__typename?: 'Book';
id: Scalars['ID']['output']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']['input']; // Input's ID can be `string` or `number` 👍
};
Note that for typescript-resolvers
, the type of ID needs to be inverted. However, the referenced types in GraphQL input/output types should still work correctly:
export type Scalars = {
ID: {
input: string;
output: string | number;
}
}
export type Book = {
__typename?: "Book";
id: Scalars["ID"]['output']; // Resolvers can return `string` or `number` in ID fields 👍
};
export type QueryBookArgs = {
id: Scalars["ID"]['input']; // Resolvers receive `string` in ID fields 👍
};
export type ResolversTypes = {
ID: ID: ResolverTypeWrapper<Scalars['ID']['output']>; // Resolvers can return `string` or `number` in ID fields 👍
}
export type ResolversParentTypes = {
ID: Scalars['ID']['output']; // Resolvers receive `string` or `number` from parents 👍
};
Config changes:
config: {
scalars: {
ID: {
input: 'string',
output: 'string | number'
}
}
}
config: {
scalars: {
ID: 'string'; // This means `string` will be used for both ID's input and output types
}
}
config: {
scalars: {
ID: './path/to/scalar-module';
}
}
If correctly, wired up, the following will be generated:
// Previously, imported `ID` type can be a primitive type, now it must be an object with input/output fields
import { ID } from './path/to/scalar-module';
export type Scalars = {
ID: { input: ID['input']; output: ID['output'] };
};
BREAKING CHANGE: This changes Scalar types which could be referenced in other plugins. If you are a plugin maintainer and reference Scalar, please update your plugin to use the correct input/output types.
bb66c2a31
Thanks @n1ru4l! - Require Node.js >= 16
. Drop support for Node.js 14
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
#9339 50471e651
Thanks @AaronMoat! - Add excludeTypes config to resolversNonOptionalTypename
This disables the adding of __typename
in resolver types for any specified typename. This could be useful e.g. if you're wanting to enable this for all new types going forward but not do a big migration.
Usage example:
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: {
unionMember: true,
excludeTypes: ['MyType'],
},
},
},
},
};
#9229 5aa95aa96
Thanks @eddeee888! - Use generic to simplify ResolversUnionTypes
This follows the ResolversInterfaceTypes
's approach where the RefType
generic is used to refer back to ResolversTypes
or ResolversParentTypes
in cases of nested Union types
#9304 e1dc75f3c
Thanks @esfomeado! - Added support for disabling suffixes on Enums.
#9229 5aa95aa96
Thanks @eddeee888! - Extract interfaces to ResolversInterfaceTypes and add to resolversNonOptionalTypename
ResolversInterfaceTypes
is a new type that keeps track of a GraphQL interface and its implementing types.For example, consider this schema:
extend type Query {
character(id: ID!): CharacterNode
}
interface CharacterNode {
id: ID!
}
type Wizard implements CharacterNode {
id: ID!
screenName: String!
spells: [String!]!
}
type Fighter implements CharacterNode {
id: ID!
screenName: String!
powerLevel: Int!
}
The generated types will look like this:
export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = {
CharacterNode: Fighter | Wizard;
};
export type ResolversTypes = {
// other types...
CharacterNode: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['CharacterNode']>;
Fighter: ResolverTypeWrapper<Fighter>;
Wizard: ResolverTypeWrapper<Wizard>;
// other types...
};
export type ResolversParentTypes = {
// other types...
CharacterNode: ResolversInterfaceTypes<ResolversParentTypes>['CharacterNode'];
Fighter: Fighter;
Wizard: Wizard;
// other types...
};
The RefType
generic is used to reference back to ResolversTypes
and ResolversParentTypes
in some cases such as field returning a Union.
resolversNonOptionalTypename
also affects ResolversInterfaceTypes
Using the schema above, if we use resolversNonOptionalTypename
option:
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: true, // Or `resolversNonOptionalTypename: { interfaceImplementingType: true }`
},
},
},
};
Then, the generated type looks like this:
export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = {
CharacterNode: (Fighter & { __typename: 'Fighter' }) | (Wizard & { __typename: 'Wizard' });
};
export type ResolversTypes = {
// other types...
CharacterNode: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['CharacterNode']>;
Fighter: ResolverTypeWrapper<Fighter>;
Wizard: ResolverTypeWrapper<Wizard>;
// other types...
};
export type ResolversParentTypes = {
// other types...
CharacterNode: ResolversInterfaceTypes<ResolversParentTypes>['CharacterNode'];
Fighter: Fighter;
Wizard: Wizard;
// other types...
};
4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
#9375 ba84a3a27
Thanks @eddeee888! - Implement Scalars with input/output types
In GraphQL, Scalar types can be different for client and server. For example, given the native GraphQL ID:
string
or number
in the inputstring
in its selection set (i.e output)string
in the resolver (GraphQL parses string
or number
received from the client to string
)string
or number
(GraphQL serializes the value to string
before sending it to the client )Currently, we represent every Scalar with only one type. This is what codegen generates as base type:
export type Scalars = {
ID: string;
};
Then, this is used in both input and output type e.g.
export type Book = {
__typename?: 'Book';
id: Scalars['ID']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']; // Input's ID can be `string` or `number`. However, the type is only `string` here 👎
};
This PR extends each Scalar to have input and output:
export type Scalars = {
ID: {
input: string | number;
output: string;
};
};
Then, each input/output GraphQL type can correctly refer to the correct input/output scalar type:
export type Book = {
__typename?: 'Book';
id: Scalars['ID']['output']; // Output's ID can be `string` 👍
};
export type QueryBookArgs = {
id: Scalars['ID']['input']; // Input's ID can be `string` or `number` 👍
};
Note that for typescript-resolvers
, the type of ID needs to be inverted. However, the referenced types in GraphQL input/output types should still work correctly:
export type Scalars = {
ID: {
input: string;
output: string | number;
}
}
export type Book = {
__typename?: "Book";
id: Scalars["ID"]['output']; // Resolvers can return `string` or `number` in ID fields 👍
};
export type QueryBookArgs = {
id: Scalars["ID"]['input']; // Resolvers receive `string` in ID fields 👍
};
export type ResolversTypes = {
ID: ID: ResolverTypeWrapper<Scalars['ID']['output']>; // Resolvers can return `string` or `number` in ID fields 👍
}
export type ResolversParentTypes = {
ID: Scalars['ID']['output']; // Resolvers receive `string` or `number` from parents 👍
};
Config changes:
config: {
scalars: {
ID: {
input: 'string',
output: 'string | number'
}
}
}
config: {
scalars: {
ID: 'string'; // This means `string` will be used for both ID's input and output types
}
}
config: {
scalars: {
ID: './path/to/scalar-module';
}
}
If correctly, wired up, the following will be generated:
// Previously, imported `ID` type can be a primitive type, now it must be an object with input/output fields
import { ID } from './path/to/scalar-module';
export type Scalars = {
ID: { input: ID['input']; output: ID['output'] };
};
BREAKING CHANGE: This changes Scalar types which could be referenced in other plugins. If you are a plugin maintainer and reference Scalar, please update your plugin to use the correct input/output types.
bb66c2a31
Thanks @n1ru4l! - Require Node.js >= 16
. Drop support for Node.js 14
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
#9304 e1dc75f3c
Thanks @esfomeado! - Added support for disabling suffixes on Enums.
4d9ea1a5a
, 4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
#9196 3848a2b73
Thanks @beerose! - Add @defer
directive support
When a query includes a deferred fragment field, the server will return a partial response with the non-deferred fields first, followed by the remaining fields once they have been resolved.
Once start using the @defer
directive in your queries, the generated code will automatically include support for the directive.
// src/index.tsx
import { graphql } from './gql';
const OrdersFragment = graphql(`
fragment OrdersFragment on User {
orders {
id
total
}
}
`);
const GetUserQuery = graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
...OrdersFragment @defer
}
}
`);
The generated type for GetUserQuery
will have information that the fragment is incremental, meaning it may not be available right away.
// gql/graphql.ts
export type GetUserQuery = { __typename?: 'Query'; id: string; name: string } & ({
__typename?: 'Query';
} & {
' $fragmentRefs'?: { OrdersFragment: Incremental<OrdersFragment> };
});
Apart from generating code that includes support for the @defer
directive, the Codegen also exports a utility function called isFragmentReady
. You can use it to conditionally render components based on whether the data for a deferred
fragment is available:
const OrdersList = (props: { data: FragmentType<typeof OrdersFragment> }) => {
const data = useFragment(OrdersFragment, props.data);
return (
// render orders list
)
};
function App() {
const { data } = useQuery(GetUserQuery);
return (
{data && (
<>
{isFragmentReady(GetUserQuery, OrdersFragment, data)
&& <OrdersList data={data} />}
</>
)}
);
}
export default App;
#9353 d7e335b58
Thanks @charpeni! - Implement the ability the specify the hash algorithm used for persisted documents via persistedDocuments.hashAlgorithm
#9449 4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/documents@^1.0.0
↗︎ (from ^0.1.0
, in dependencies
)@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)#9385 a7dda3546
Thanks @beerose! - Improve isFragmentReady utility function to work with noUncheckedIndexedAccess TSC setting
#9196 3848a2b73
Thanks @beerose! - Pass emitLegacyCommonJSImports
and isStringDocumentMode
to the client preset config
#9414 ca02ad172
Thanks @beerose! - Include nested fragments in string documentMode
Updated dependencies [4d9ea1a5a
, 4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)4d9ea1a5a
, 4d9ea1a5a
, f46803a8c
, 3848a2b73
, ba84a3a27
, 63827fabe
, 50471e651
, 5aa95aa96
, ca02ad172
, e1dc75f3c
, bb66c2a31
, 5950f5a68
, 5aa95aa96
]:
bec804225
Thanks @renovate! - dependencies updates:
[email protected]
↗︎ (from 13.3.0
, in dependencies
)4d9ea1a5a
, f46803a8c
, 63827fabe
, bb66c2a31
]:
#9449 4d9ea1a5a
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/utils@^10.0.0
↗︎ (from ^9.0.0
, in dependencies
)#9332 f46803a8c
Thanks @eddeee888! - Update GitHub loader TypeScript type and usage docs
#9360 63827fabe
Thanks @beerose! - Add handleAsSDL property to UrlSchemaOptions type
Published by theguild-bot over 1 year ago
#9267 183749346
Thanks @milesrichardson! - Fix watch mode to listen to longest common directory prefix of relevant files, rather than only files below the current working directory (fixes #9266).
#9280 ca1d72c40
Thanks @saihaj! - fix the default output directory for init command
#9301 386cf9044
Thanks @wassim-k! - Fix fragment imports for near-operation-file with graphQLTag
#9231 402cb8ac0
Thanks @eddeee888! - Implement resolversNonOptionalTypename for mapper cases
386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
#9231 402cb8ac0
Thanks @eddeee888! - Implement resolversNonOptionalTypename for mapper cases
Updated dependencies [386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
386cf9044
, 402cb8ac0
]:
Published by theguild-bot over 1 year ago
#9151 b7dacb21f
Thanks @eddeee888! - Add watchPattern
config option for generates
sections.
By default, watch
mode automatically watches all GraphQL schema and document files. This means when a change is detected, Codegen CLI is run.
A user may want to run Codegen CLI when non-schema and non-document files are changed. Each generates
section now has a watchPattern
option to allow more file patterns to be added to the list of patterns to watch.
In the example below, mappers are exported from schema.mappers.ts
files. We want to re-run Codegen if the content of *.mappers.ts
files change because they change the generated types file. To solve this, we can add mapper file patterns to watch using the glob pattern used for schema and document files.
// codegen.ts
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
mappers: {
User: './user/schema.mappers#UserMapper',
Book: './book/schema.mappers#BookMapper',
},
}
watchPattern: 'src/schema/**/*.mappers.ts', // Watches mapper files in `watch` mode. Use an array for multiple patterns e.g. `['src/*.pattern1.ts','src/*.pattern2.ts']`
},
},
};
Then, run Codegen CLI in watch
mode:
yarn graphql-codegen --watch
Now, updating *.mappers.ts
files re-runs Codegen! 🎉
Note: watchPattern
is only used in watch
mode i.e. running CLI with --watch
flag.
b7dacb21f
, f104619ac
]:
#9146 9f4d9c5a4
Thanks @eddeee888! - [typescript-resolvers] Add resolversNonOptionalTypename
config option.
This is extending on ResolversUnionTypes
implemented in https://github.com/dotansimha/graphql-code-generator/pull/9069
resolversNonOptionalTypename
adds non-optional __typename
to union members of ResolversUnionTypes
, without affecting the union members' base intefaces.
A common use case for non-optional __typename
of union members is using it as the common field to work out the final schema type. This makes implementing the union's __resolveType
very simple as we can use __typename
to decide which union member the resolved object is. Without this, we have to check the existence of field/s on the incoming object which could be verbose.
For example, consider this schema:
type Query {
book(id: ID!): BookPayload!
}
type Book {
id: ID!
isbn: String!
}
type BookResult {
node: Book
}
type PayloadError {
message: String!
}
union BookPayload = BookResult | PayloadError
With optional __typename
: We need to check existence of certain fields to resolve type in the union resolver:
// Query/book.ts
export const book = async () => {
try {
const book = await fetchBook();
// 1. No `__typename` in resolver results...
return {
node: book,
};
} catch (e) {
return {
message: 'Failed to fetch book',
};
}
};
// BookPayload.ts
export const BookPayload = {
__resolveType: parent => {
// 2. ... means more checks in `__resolveType`
if ('message' in parent) {
return 'PayloadError';
}
return 'BookResult';
},
};
With non-optional __typename
: Resolvers declare the type. This which gives us better TypeScript support in resolvers and simplify __resolveType
implementation:
// Query/book.ts
export const book = async () => {
try {
const book = await fetchBook();
// 1. `__typename` is declared in resolver results...
return {
__typename: 'BookResult', // 1a. this also types `node` for us 🎉
node: book,
};
} catch (e) {
return {
__typename: 'PayloadError',
message: 'Failed to fetch book',
};
}
};
// BookPayload.ts
export const BookPayload = {
__resolveType: parent => parent.__typename, // 2. ... means a very simple check in `__resolveType`
};
Using resolversNonOptionalTypename
: add it into typescript-resolvers
plugin config:
// codegen.ts
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: true, // Or `resolversNonOptionalTypename: { unionMember: true }`
},
},
},
};
#9206 e56790104
Thanks @eddeee888! - Fix ResolversUnionTypes
being used in ResolversParentTypes
Previously, objects with mappable fields are converted to Omit format that references its own type group or ResolversTypes
or ResolversParentTypes
e.g.
export type ResolversTypes = {
Book: ResolverTypeWrapper<BookMapper>;
BookPayload: ResolversTypes['BookResult'] | ResolversTypes['StandardError'];
// Note: `result` on the next line references `ResolversTypes["Book"]`
BookResult: ResolverTypeWrapper<Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }>;
StandardError: ResolverTypeWrapper<StandardError>;
};
export type ResolversParentTypes = {
Book: BookMapper;
BookPayload: ResolversParentTypes['BookResult'] | ResolversParentTypes['StandardError'];
// Note: `result` on the next line references `ResolversParentTypes["Book"]`
BookResult: Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> };
StandardError: StandardError;
};
In https://github.com/dotansimha/graphql-code-generator/pull/9069, we extracted resolver union types to its own group:
export type ResolversUnionTypes = {
// Note: `result` on the next line references `ResolversTypes["Book"]` which is only correct for the `ResolversTypes` case
BookPayload: (Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }) | StandardError;
};
export type ResolversTypes = {
Book: ResolverTypeWrapper<BookMapper>;
BookPayload: ResolverTypeWrapper<ResolversUnionTypes['BookPayload']>;
BookResult: ResolverTypeWrapper<Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }>;
StandardError: ResolverTypeWrapper<StandardError>;
};
export type ResolversParentTypes = {
Book: BookMapper;
BookPayload: ResolversUnionTypes['BookPayload'];
BookResult: Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> };
StandardError: StandardError;
};
This change creates an extra ResolversUnionParentTypes
that is referenced by ResolversParentTypes
to ensure backwards compatibility:
export type ResolversUnionTypes = {
BookPayload: (Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> }) | StandardError;
};
// ... and the reference is changed in ResolversParentTypes:
export type ResolversParentTypes = {
// ... other fields
BookPayload: ResolversUnionParentTypes['BookPayload'];
};
#9194 acb647e4e
Thanks @dstaley! - Don't emit import statements for unused fragments
Updated dependencies [b7dacb21f
, f104619ac
]:
e56790104
, b7dacb21f
, f104619ac
, acb647e4e
, 9f4d9c5a4
]:
2256c8b5d
Thanks @beerose! - Add TypedDocumentNode
string alternative that doesn't require GraphQL AST on the client. This change requires @graphql-typed-document-node/core
in version 3.2.0
or higher.e56790104
, b7dacb21f
, f104619ac
, acb647e4e
, 9f4d9c5a4
]:
e56790104
, b7dacb21f
, f104619ac
, 92d86b009
, acb647e4e
, 9f4d9c5a4
]:
#9146 9f4d9c5a4
Thanks @eddeee888! - [typescript-resolvers] Add resolversNonOptionalTypename
config option.
This is extending on ResolversUnionTypes
implemented in https://github.com/dotansimha/graphql-code-generator/pull/9069
resolversNonOptionalTypename
adds non-optional __typename
to union members of ResolversUnionTypes
, without affecting the union members' base intefaces.
A common use case for non-optional __typename
of union members is using it as the common field to work out the final schema type. This makes implementing the union's __resolveType
very simple as we can use __typename
to decide which union member the resolved object is. Without this, we have to check the existence of field/s on the incoming object which could be verbose.
For example, consider this schema:
type Query {
book(id: ID!): BookPayload!
}
type Book {
id: ID!
isbn: String!
}
type BookResult {
node: Book
}
type PayloadError {
message: String!
}
union BookPayload = BookResult | PayloadError
With optional __typename
: We need to check existence of certain fields to resolve type in the union resolver:
// Query/book.ts
export const book = async () => {
try {
const book = await fetchBook();
// 1. No `__typename` in resolver results...
return {
node: book,
};
} catch (e) {
return {
message: 'Failed to fetch book',
};
}
};
// BookPayload.ts
export const BookPayload = {
__resolveType: parent => {
// 2. ... means more checks in `__resolveType`
if ('message' in parent) {
return 'PayloadError';
}
return 'BookResult';
},
};
With non-optional __typename
: Resolvers declare the type. This which gives us better TypeScript support in resolvers and simplify __resolveType
implementation:
// Query/book.ts
export const book = async () => {
try {
const book = await fetchBook();
// 1. `__typename` is declared in resolver results...
return {
__typename: 'BookResult', // 1a. this also types `node` for us 🎉
node: book,
};
} catch (e) {
return {
__typename: 'PayloadError',
message: 'Failed to fetch book',
};
}
};
// BookPayload.ts
export const BookPayload = {
__resolveType: parent => parent.__typename, // 2. ... means a very simple check in `__resolveType`
};
Using resolversNonOptionalTypename
: add it into typescript-resolvers
plugin config:
// codegen.ts
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
resolversNonOptionalTypename: true, // Or `resolversNonOptionalTypename: { unionMember: true }`
},
},
},
};
#9206 e56790104
Thanks @eddeee888! - Fix ResolversUnionTypes
being used in ResolversParentTypes
Previously, objects with mappable fields are converted to Omit format that references its own type group or ResolversTypes
or ResolversParentTypes
e.g.
export type ResolversTypes = {
Book: ResolverTypeWrapper<BookMapper>;
BookPayload: ResolversTypes['BookResult'] | ResolversTypes['StandardError'];
// Note: `result` on the next line references `ResolversTypes["Book"]`
BookResult: ResolverTypeWrapper<Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }>;
StandardError: ResolverTypeWrapper<StandardError>;
};
export type ResolversParentTypes = {
Book: BookMapper;
BookPayload: ResolversParentTypes['BookResult'] | ResolversParentTypes['StandardError'];
// Note: `result` on the next line references `ResolversParentTypes["Book"]`
BookResult: Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> };
StandardError: StandardError;
};
In https://github.com/dotansimha/graphql-code-generator/pull/9069, we extracted resolver union types to its own group:
export type ResolversUnionTypes = {
// Note: `result` on the next line references `ResolversTypes["Book"]` which is only correct for the `ResolversTypes` case
BookPayload: (Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }) | StandardError;
};
export type ResolversTypes = {
Book: ResolverTypeWrapper<BookMapper>;
BookPayload: ResolverTypeWrapper<ResolversUnionTypes['BookPayload']>;
BookResult: ResolverTypeWrapper<Omit<BookResult, 'result'> & { result?: Maybe<ResolversTypes['Book']> }>;
StandardError: ResolverTypeWrapper<StandardError>;
};
export type ResolversParentTypes = {
Book: BookMapper;
BookPayload: ResolversUnionTypes['BookPayload'];
BookResult: Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> };
StandardError: StandardError;
};
This change creates an extra ResolversUnionParentTypes
that is referenced by ResolversParentTypes
to ensure backwards compatibility:
export type ResolversUnionTypes = {
BookPayload: (Omit<BookResult, 'result'> & { result?: Maybe<ResolversParentTypes['Book']> }) | StandardError;
};
// ... and the reference is changed in ResolversParentTypes:
export type ResolversParentTypes = {
// ... other fields
BookPayload: ResolversUnionParentTypes['BookPayload'];
};
f104619ac
Thanks @saihaj! - Resolve issue with nesting fields in @provides
directive being prevented
Updated dependencies [e56790104
, b7dacb21f
, f104619ac
, 92d86b009
, acb647e4e
, 9f4d9c5a4
]:
2256c8b5d
Thanks @beerose! - Add TypedDocumentNode
string alternative that doesn't require GraphQL AST on the client. This change requires @graphql-typed-document-node/core
in version 3.2.0
or higher.e56790104
, b7dacb21f
, f104619ac
, acb647e4e
, 9f4d9c5a4
]:
#9150 92d86b009
Thanks @rliljest! - Properly escape enum identifiers when enumsAsConst is used
Updated dependencies [e56790104
, b7dacb21f
, f104619ac
, acb647e4e
, 9f4d9c5a4
]:
2256c8b5d
Thanks @beerose! - Add TypedDocumentNode
string alternative that doesn't require GraphQL AST on the client. This change requires @graphql-typed-document-node/core
in version 3.2.0
or higher.2256c8b5d
Thanks @beerose! - dependencies updates:
@graphql-typed-document-node/[email protected]
↗︎ (from 3.1.2
, in dependencies
)e56790104
, b7dacb21f
, f104619ac
, 92d86b009
, 2256c8b5d
, acb647e4e
, 9f4d9c5a4
]:
e56790104
, b7dacb21f
, f104619ac
, acb647e4e
, 9f4d9c5a4
]:
#9228 a5ec5af36
Thanks @eddeee888! - Add complex test cases for resolvers tests
Updated dependencies [b7dacb21f
, f104619ac
]:
#9151 b7dacb21f
Thanks @eddeee888! - Add watchPattern
config option for generates
sections.
By default, watch
mode automatically watches all GraphQL schema and document files. This means when a change is detected, Codegen CLI is run.
A user may want to run Codegen CLI when non-schema and non-document files are changed. Each generates
section now has a watchPattern
option to allow more file patterns to be added to the list of patterns to watch.
In the example below, mappers are exported from schema.mappers.ts
files. We want to re-run Codegen if the content of *.mappers.ts
files change because they change the generated types file. To solve this, we can add mapper file patterns to watch using the glob pattern used for schema and document files.
// codegen.ts
const config: CodegenConfig = {
schema: 'src/schema/**/*.graphql',
generates: {
'src/schema/types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
mappers: {
User: './user/schema.mappers#UserMapper',
Book: './book/schema.mappers#BookMapper',
},
}
watchPattern: 'src/schema/**/*.mappers.ts', // Watches mapper files in `watch` mode. Use an array for multiple patterns e.g. `['src/*.pattern1.ts','src/*.pattern2.ts']`
},
},
};
Then, run Codegen CLI in watch
mode:
yarn graphql-codegen --watch
Now, updating *.mappers.ts
files re-runs Codegen! 🎉
Note: watchPattern
is only used in watch
mode i.e. running CLI with --watch
flag.
Published by theguild-bot over 1 year ago
a34cef35b
, a34cef35b
]:
#9086 a34cef35b
Thanks @beerose! - dependencies updates:
graphql-config@^4.5.0
↗︎ (from ^4.4.0
, in dependencies
)jiti@^1.17.1
↗︎ (to dependencies
)cosmiconfig-typescript-loader@^4.3.0
↗︎ (from dependencies
)ts-node@^10.9.1
↗︎ (from dependencies
)#9086 a34cef35b
Thanks @beerose! - Support codegen.ts
in ESM projects
#9110 ba0610bbd
Thanks @gilgardosh! - Custom mappers with placeholder will apply omit
#9069 4b49f6fbe
Thanks @eddeee888! - Extract union types to ResolversUnionTypes
#8895 b343626c9
Thanks @benkroeger! - Preserve .js extension when importDocumentNodeExternallyFrom and emitLegacyCommonJSImports is false
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
#9110 ba0610bbd
Thanks @gilgardosh! - Custom mappers with placeholder will apply omit
#9069 4b49f6fbe
Thanks @eddeee888! - Extract union types to ResolversUnionTypes
Updated dependencies [ba0610bbd
, 4b49f6fbe
, b343626c9
]:
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
9430c3811
Thanks @renovate! - dependencies updates:
@graphql-typed-document-node/[email protected]
↗︎ (from 3.1.1
, in dependencies
)ba0610bbd
, 4b49f6fbe
, b343626c9
]:
ba0610bbd
, 4b49f6fbe
, b343626c9
]:
Published by theguild-bot over 1 year ago
f7313f7ca
, f7313f7ca
]:
Published by theguild-bot over 1 year ago
288ed0977
, 288ed0977
]:
288ed0977
Thanks @saihaj! - dependencies updates:
@parcel/watcher@^2.1.0
↗︎ (to dependencies
)chokidar@^3.5.2
↗︎ (from dependencies
)Published by n1ru4l over 1 year ago
#8893 a118c307a
Thanks @n1ru4l! - It is no longer mandatory to declare an empty plugins array when using a preset
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
4c422ccf6
Thanks @renovate! - dependencies updates:
@whatwg-node/fetch@^0.8.0
↗︎ (from ^0.6.0
, in dependencies
)8206b268d
, 8206b268d
, a118c307a
, a3309e63e
]:
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, a118c307a
, a3309e63e
]:
b13aa7449
Thanks @KGAdamCook! - Updated customResolveInfo to use the correct importType for external imports8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
#8893 a118c307a
Thanks @n1ru4l! - It is no longer mandatory to declare an empty plugins array when using a preset
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
#8879 8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)#8995 fe2e9c7a5
Thanks @charpeni! - Use gqlTagName
for generated examples
#8971 6b6fe3cbc
Thanks @n1ru4l! - Allow passing fragment documents to APIs like Apollos readFragment
Updated dependencies [8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, a118c307a
, fe2e9c7a5
, 6b6fe3cbc
, 6b6fe3cbc
, a3309e63e
]:
#8893 a118c307a
Thanks @n1ru4l! - It is no longer mandatory to declare an empty plugins array when using a preset
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, 8206b268d
, a118c307a
, fe2e9c7a5
, 6b6fe3cbc
, 6b6fe3cbc
, a3309e63e
]:
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
#8893 a118c307a
Thanks @n1ru4l! - mark plugins
in config optional
#8723 a3309e63e
Thanks @kazekyo! - Introduce a new feature called DocumentTransform.
DocumentTransform is a functionality that allows you to modify documents
before they are processed by plugins. You can use functions passed to the documentTransforms
option to make changes to GraphQL documents.
To use this feature, you can write documentTransforms
as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
},
],
},
},
};
export default config;
For instance, to remove a @localOnlyDirective
directive from documents
, you can write the following code:
import type { CodegenConfig } from '@graphql-codegen/cli';
import { visit } from 'graphql';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: [
{
transform: ({ documents }) => {
return documents.map(documentFile => {
documentFile.document = visit(documentFile.document, {
Directive: {
leave(node) {
if (node.name.value === 'localOnlyDirective') return null;
},
},
});
return documentFile;
});
},
},
],
},
},
};
export default config;
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to documentTransforms
.
Let's create the document transform as a file:
module.exports = {
transform: ({ documents }) => {
// Make some changes to the documents
return documents;
},
};
Then, you can specify the file name as follows:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
documentTransforms: ['./my-document-transform.js'],
},
},
};
export default config;
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)4c422ccf6
, a118c307a
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, a118c307a
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, a118c307a
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, a118c307a
, a3309e63e
]:
#8879 8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)#8971 6b6fe3cbc
Thanks @n1ru4l! - Always inline referenced fragments within their document. This prevents issues with duplicated fragments or missing fragments.
Updated dependencies [8206b268d
, a118c307a
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
#8879 8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)#8995 fe2e9c7a5
Thanks @charpeni! - Use gqlTagName
for generated examples
Updated dependencies [8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
#8879 8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)#8971 6b6fe3cbc
Thanks @n1ru4l! - Allow passing fragment documents to APIs like Apollos readFragment
Updated dependencies [8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, 8206b268d
, 8206b268d
, a118c307a
, 6b6fe3cbc
, a3309e63e
]:
8206b268d
Thanks @renovate! - dependencies updates:
tslib@~2.5.0
↗︎ (from ~2.4.0
, in dependencies
)8206b268d
, a118c307a
, a3309e63e
]:
Published by github-actions[bot] over 1 year ago
321d5112e
, fd0b0c813
]:
#8883 321d5112e
Thanks @Solo-steven! - Fix PluckConfig overwrite problem.
Updated dependencies [fc79b65d4
, fd0b0c813
]:
Updated dependencies [fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
Updated dependencies [fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
Updated dependencies [fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
#8885 fd0b0c813
Thanks @n1ru4l! - dependencies updates:
@babel/helper-plugin-utils@^7.20.2
↗︎ (from ^7.14.5
, in dependencies
)@babel/template@^7.20.7
↗︎ (from ^7.15.4
, in dependencies
)Updated dependencies [fc79b65d4
, fd0b0c813
]:
Updated dependencies [fc79b65d4
, fd0b0c813
]:
Updated dependencies [fc79b65d4
, fd0b0c813
]:
fc79b65d4
, fd0b0c813
]:
Published by github-actions[bot] over 1 year ago
4fa0a566e
Thanks @renovate! - dependencies updates:
[email protected]
↗︎ (from 13.2.9
, in dependencies
)Published by github-actions[bot] over 1 year ago
e4d073b16
, 884d25c4e
, e4d073b16
]:
#8865 e4d073b16
Thanks @n1ru4l! - dependencies updates:
@graphql-codegen/core@^2.6.8
↗︎ (from 2.6.8
, in dependencies
)@graphql-tools/load@^7.8.0
↗︎ (from 7.8.0
, in dependencies
)cosmiconfig-typescript-loader@^4.3.0
↗︎ (from 4.3.0
, in dependencies
)graphql-config@^4.4.0
↗︎ (from 4.4.0
, in dependencies
)ts-node@^10.9.1
↗︎ (to dependencies
)ts-node@>=10
↗︎ (from peerDependencies
)#8865 e4d073b16
Thanks @n1ru4l! - move ts-node from peer dependencies to dependencies
a98198524
Thanks @charle692! - Fix issue where visitor-plugin-common emitted ESM imports for Operations when emitLegacyCommonJSImports is truea98198524
]:
a98198524
]:
a98198524
]:
a98198524
]:
a98198524
]:
a98198524
]:
#8757 4f290aa72
Thanks @n1ru4l! - Add support for persisted documents.
You can now generate and embed a persisted documents hash for the executable documents.
/** codegen.ts */
import { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
documents: ['src/**/*.tsx'],
ignoreNoDocuments: true, // for better experience with the watcher
generates: {
'./src/gql/': {
preset: 'client',
plugins: [],
presetConfig: {
persistedDocuments: true,
},
},
},
};
export default config;
This will generate ./src/gql/persisted-documents.json
(dictionary of hashes with their operation string).
In addition to that each generated document node will have a __meta__.hash
property.
import { gql } from './gql.js';
const allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ `
query allFilmsWithVariablesQuery($first: Int!) {
allFilms(first: $first) {
edges {
node {
...FilmItem
}
}
}
}
`);
console.log((allFilmsWithVariablesQueryDocument as any)['__meta__']['hash']);
#8757 4f290aa72
Thanks @n1ru4l! - Add support for embedding metadata in the document AST.
It is now possible to embed metadata (e.g. for your GraphQL client within the emitted code).
/** codegen.ts */
import { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
documents: ['src/**/*.tsx'],
ignoreNoDocuments: true, // for better experience with the watcher
generates: {
'./src/gql/': {
preset: 'client',
plugins: [],
presetConfig: {
onExecutableDocumentNode(documentNode) {
return {
operation: documentNode.definitions[0].operation,
name: documentNode.definitions[0].name.value,
};
},
},
},
},
};
export default config;
You can then access the metadata via the __meta__
property on the document node.
import { gql } from './gql.js';
const allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ `
query allFilmsWithVariablesQuery($first: Int!) {
allFilms(first: $first) {
edges {
node {
...FilmItem
}
}
}
}
`);
console.log((allFilmsWithVariablesQueryDocument as any)['__meta__']);
4f290aa72
Thanks @n1ru4l! - dependencies updates:
@graphql-tools/documents@^0.1.0
↗︎ (to dependencies
)a98198524
]:
a98198524
]:
Published by github-actions[bot] almost 2 years ago
4774247e9
, fe12b4826
]:
#8770 4774247e9
Thanks @renovate! - dependencies updates:
[email protected]
↗︎ (from 4.3.6
, in dependencies
)#8790 fe12b4826
Thanks @renovate! - dependencies updates:
@whatwg-node/fetch@^0.6.0
↗︎ (from ^0.5.0
, in dependencies
)902451601
Thanks @shmax! - remove extra asterisk and add missing semicolon in generated output#8796 902451601
Thanks @shmax! - remove extra asterisk and add missing semicolon in generated output
Updated dependencies [902451601
]:
#8796 902451601
Thanks @shmax! - remove extra asterisk and add missing semicolon in generated output
Updated dependencies [902451601
]:
Published by github-actions[bot] almost 2 years ago
ad5d83313
]:
ad5d83313
Thanks @louisscruz! - add ts-node as a peerDependencyeb454d06c
]:
2a33fc774
Thanks @ElvisUpUp! - change the client-preset generated templateeb454d06c
]:
eb454d06c
]:
eb454d06c
]:
eb454d06c
]:
eb454d06c
]:
eb454d06c
, 2a33fc774
]:
eb454d06c
]: